1
votes

I am currently implementing an authentication system wherein a user logs in and receives a JWT token from the server, which is stored in localStorage. I also wrote a custom HttpInterceptor that attaches the user's token to outgoing HTTP requests. This works fine for local endpoints, however I also have a GET request fetching each user's avatar from GitHub's API and this is no longer working due to the interceptor. I am getting a 401 authentication error from GitHub.

Here is the code from the HttpInterceptor:

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    const idToken = localStorage.getItem("access_token");

    if (idToken && req.url.includes("localhost")) {
      const cloned = req.clone({
        headers: req.headers.set("Authorization", `Bearer ${idToken}`)
      });
      return next.handle(cloned);
    } else {
      return next.handle(req);
    }
  }
}

Here are the request headers that are being sent to GitHub:

Accept: application/json, text/plain, */*
Authorization: token ... (removed for privacy)
Content-Type: application/json
Origin: http://localhost:4200
Referer: http://localhost:4200/contacts
User-Agent: ...(removed for privacy)

Here is the response from GitHub API:

Request URL: https://api.github.com/users/...
Request Method: GET
Status Code: 401 Unauthorized
Remote Address: 192.30.253.117:443
Referrer Policy: no-referrer-when-downgrade

And here is the code from the service which fetches the GitHub avatar:

const githubOptions = {
  headers: new HttpHeaders({
    "Content-Type": "application/json",
    Authorization: "token ..." // removed for privacy
  })
};

@Injectable({
  providedIn: "root"
})
export class ContactServiceService {
  constructor(private http: HttpClient) {}

  ...

  getGithub(user: string): Promise<any> {
    return this.http
      .get<any>(`https://api.github.com/users/${user}`, githubOptions)
      .toPromise();
  }
}

The weird thing is, if I double click the HTTP request in the Chrome Network console, it goes through fine and returns the desired response. But for whatever reason, the HttpInterceptor is preventing it from going through in my code.

Any help is greatly appreciated!

1

1 Answers

1
votes

This is because your application's Authorization header is overriding the one for github. Actually you are trying to avoid this by checking the url with this if statement if (idToken && req.url.includes("localhost")) {

However it seems like your req.headers.set call is overriding the Authorization header for other requests too. Try setting the header like this:

const cloned = request.clone({
  setHeaders: {
    Authorization: `Bearer ${idToken}`
  }
});