#jwt -refresh token

5 messages · Page 1 of 1 (latest)

swift wind
#

Hello everyone,

I've set up an authentication system with JWT and refresh token in an Angular application + Symfony API. However, I have a specific problem on the home page of my site, which does not require a connection (URL: https://matchLove.com).

Problem
On this page, a request is automatically made to the /api/me endpoint to check the user's connection status. However, as the user is not supposed to be authenticated on this page, the API returns a 401 error, which triggers the refresh token mechanism. This creates an infinite loop of attempts to refresh the token and blocks the rest of the page from loading.

Question
How could I configure my HTTP interceptor in Angular to :

Ignore the login check (request to /api/me) only on the home page,
Prevent the refresh token from being triggered in the event of a 401 only on this page?
Here is my current interceptor to handle 401 errors and refresh the token:

#

import { HttpErrorResponse, HttpInterceptorFn } from '@angular/common/http';
import { AuthService } from './service/auth.service';
import { inject } from '@angular/core';
import { catchError, switchMap, throwError, BehaviorSubject, filter, take, finalize } from 'rxjs';

let isRefreshing = false;
const refreshTokenSubject = new BehaviorSubject<string | null>(null);

export const requestInterceptor: HttpInterceptorFn = (req, next) => {
const authService = inject(AuthService);
const currentUrl = window.location.href;

// Ignorer la requête /api/me sur la page d'accueil
if (currentUrl.includes('https://matchLove.com/') && req.url === '/api/me') {
return next(req);
}

const clonedRequest = req.clone({
withCredentials: true
});

return next(clonedRequest).pipe(
catchError((error: HttpErrorResponse) => {
if (error.status === 401 && !isRefreshing) {
isRefreshing = true;
refreshTokenSubject.next(null);

    return authService.refreshToken().pipe(
      switchMap((tokenResponse) => {
        refreshTokenSubject.next(tokenResponse.token);
        const retryRequest = req.clone({
          withCredentials: true
        });
        return next(retryRequest);
      }),
      catchError(err => {
        authService.logout();
        return throwError(() => err);
      }),
      finalize(() => {
        isRefreshing = false;
      })
    );
  } else if (error.status === 401 && isRefreshing) {
    return refreshTokenSubject.pipe(
      filter(token => token !== null),
      take(1),
      switchMap(() => next(clonedRequest))
    );
  }
  return throwError(() => error);
})

);
};

tiny perchBOT
#

Hi @swift wind, we do not recommend implementing your own Authorization/Authentication solution.

From experience, we know that Auth is a complex subject and an incorrect implementation could compromise an entire project.

An Auth solution complying with industry standards like OAuth2, OpenID, SAML, etc., requires extensive knowledge and a substantial amount of development time to implement and maintain.

We advise projects requiring Auth, to use a recognized third party Identity Provider (including, but not limited to: Auth0, AWS Cognito, Keycloak, Okta, etc.)

Many of these Identity Providers offer a free tier, which is suitable for use during development or for use in smaller projects.

swift wind
# tiny perch Hi <@1234401170236379222>, we do **not** recommend implementing your own Authori...

Hello and thank you for your advice.

In our case, the choice of an internal authentication solution was made beforehand, and our backend is already structured around this approach with Symfony and a JWT system. Migrating to an external identity provider would be complex at this stage, but it's a possibility we could consider for future projects. Thanks again for your suggestions, and we'll keep this option in mind for future developments.

tired niche
#

I still strongly suggest to consider migrating to a third party IDP.
That said, I think that a refresh token should be asked for only when there's an already expired one, and only for route actually needing access privileges.
I think what you need for your purpose in that page is more an IdToken than an Access/Refresh one.
Again, all these issues (that are just the surface of a really complex topic), would be addressed by a clientside lib provided by a professional IDP.