0

In my Angular routing, I want to add a route for serving authenticated files from the backend:

{ path: 'files/:id/:name', pathMatch: 'full', ??? }

I already have an HTTP interceptor which adds the token headers to other requests. What I want to achieve is simply that the (existing) interceptor adds the token headers, then passes the request on to the server.

(The server will then validate the authentication headers and e.g. return an image. The response will have no additional headers, the result will just be a plain image. Example: "files/1337/logo.svg".)

I don't need a component for that, do I? How can I achieve that in the simplest way?

Thanks for your help!

Doidel
  • 319
  • 8
  • 23

3 Answers3

1

You'll need to add the following code to you interceptor:

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    request = request.clone({
        setHeaders: {
            Authorization: `Bearer <your token>`
        }
    });

    return next.handle(request);
}
OfirBE
  • 11
  • 1
  • Thank you, but I think there's a misunderstanding. The question is about routing, not about the interceptor. The interceptor already exists and is working fine for regular components. – Doidel Aug 27 '20 at 14:31
1

If a user navigates to a route you have defined in Angular, there is no request submitted to the server. The Angular router reacts to the url change and loads your component inside the router-outlet. You could create a component that reads the variable part of your url and then request the image from an API.

To do that, inject the class ActivatedRoute into your component and use either params or paramMap to retrieve the parameter. Inside the subscribe block you can use the HttpClient to call your API.

@Component({
    selector: 'app-test',
    templateUrl: './test.component.html',
    styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {


    constructor(private readonly route: ActivatedRoute) {
        this.route.params.subscribe((params: Params) => {
         
        });
        this.route.paramMap.subscribe((paramMap: ParamMap) => {
          
        });
    }

    ngOnInit(): void {
    }

}

As your images are secured you probably want to fetch them as a 'blob' and then load them into an img tag. Look at this question

tobiso
  • 521
  • 3
  • 11
  • Hmm I see. I've tried to avoid using the Blob way because of some obvious downsides: no caching, no partial downloads, no modern image attributes like "load=lazy", etc. But your answer helps me understand Angular's routing. So what if I type in the full URL manually, will Angular's routing still catch it? I'm thinking about "open image in new tab". – Doidel Sep 01 '20 at 05:22
  • 1
    You can avoid using Blob by adding the bearer token as a query param to the img tag src attribute. But be careful your token will be exposed in any access logs. I have solved this in the past by first requesting a very short-lived custom token from the api with my access token and then using this token to fetch the image. Caching will still be a problem though. – tobiso Sep 02 '20 at 13:47
  • 1
    About the second question: Your server (nginx, apache ...) should be configured in a way that the first request (exact path does not matter) serves the index html of the angular app. Then the angular routing will kick in and handle the rest. – tobiso Sep 02 '20 at 13:51
1

You want to access static files and protect those with a token in http header. Okay, fine.

But why do you need an Angular route for that?

Since it is a static file on the server you need to configure your backend/server so that the files are available on the path you request in your app (with an img tag and src attribute for example => btw. there you would rather use a pipe to add the needed token to the src attribute).

The Angular route configuration is for loading components based on the path. It simulates a "page based" site, although behind the scenes it is a single page app and only your index.html was loaded.

gestj
  • 151
  • 9
  • Oh they are available on that path. But only if the request comes with the right headers, otherwise the authorization will fail. I wasn't aware that you can add pipe's to img src attributes. If it would allow me to modify the normal image request and add those token headers, then that might be what I'm looking for. – Doidel Sep 01 '20 at 05:25
  • 1
    When you want to use the pipe thingy I mentioned you need to have control over the template in your code. From where does the image request / tag comes from? (Referring to your comment on https://stackoverflow.com/a/63671717/13439198) => That is why I asked about Angular routing in the beginning... *yeah, I don't want to rewrite what @tobiso already explained... And yes, Angular routing works also on a new tab (answering your question there). But of course your webserver needs to be configured correctly so that the "route" gets forwarded to the host page of your Angular app. – gestj Sep 01 '20 at 10:35
  • Thank you very much for the clarification. It connected the remaining dots for me after @tobiso's answer. – Doidel Sep 01 '20 at 10:50