auth0 / auth0-angular

Auth0 SDK for Angular Single Page Applications
MIT License
174 stars 57 forks source link

HttpInterceptor does not allow correct workflow without refresh token fallback. #627

Open rouven-s opened 4 days ago

rouven-s commented 4 days ago

Checklist

Description

Due to browser restrictions we had to disable the refresh token fallback (useRefreshTokensFallBack: false) and are now catching the according potential errors as described (https://auth0.github.io/auth0-spa-js/interfaces/Auth0ClientOptions.html#useRefreshTokensFallback) during the login flow, which works correctly.

We have API routes that are accessible anonymously but provide additional information for logged in users. They are configured using "allowAnonymous: true". When the access token for these expires, but the user is authenticated, we would like to do a loginWithRedirect to retrieve a new token.

The problem is that the AuthHttpInterceptor does a "getAccessTokenSilently()" (which will fail with "missing_refresh_token"), then checks if the route is configured as "allowAnonymous" and ignores the error if this is the case, executing the request without a token and without a possibility to react to the error as a result. (See https://github.com/auth0/auth0-angular/blob/main/projects/auth0-angular/src/lib/auth.interceptor.ts#L72)

I can see two possible solutions:

  1. Add an option to add an error callback function that can be used to manually react to the "missing_refresh_token" and "invalid_grant" errors
  2. Mark the 'findMatchingRoute' method as 'protected' instead of 'private'. This way, a subclass of the interceptor could be used to add the custom check before the provided library 'intercept' method is called. Alternatively, 'findMatchingRoute' could be provided as separate function that could be used in a custom HttpInterceptor.

tl;dr Current AuthHttpInterceptor implementation does not comply with recommended workflow for "useRefreshTokensFallBack: false" configuration (see example https://auth0.github.io/auth0-spa-js/interfaces/Auth0ClientOptions.html#useRefreshTokensFallback)[](url)

Reproduction

  1. Setup route that is accessible both anonymously and when authenticated (with additional information)
  2. Configure AuthHttpInterceptor with route as "allowAnonymous: true"
  3. Configure auth0 with "useRefreshTokensFallBack: false"
  4. Login and call route
  5. Let token expire or delete it in local storage and call route again
  6. There will be no error, since the "getAccessTokenSilently" in the interceptor ignores "missing_refresh_token" and no possibility to react to this error

Additional context

No response

auth0-angular version

2.2.3

Angular version

18.0.0

Which browsers have you tested in?

Chrome, Firefox, Other

frederikprijck commented 4 days ago

HttpInterceptor does not allow correct workflow without refresh token fallback.

I do not think this is an accurate description. The behavior you are seeing is expected. AllowAnonymous is meant exactly for this (ignore when we have no token, pass the token when we do have one). You will see the same behavior when u set useRefreshTokenFallback to true and you have no active session with Auth0.

I think your use-case is rather unique in such a way that I'd recommend rolling your own interceptor.

rouven-s commented 4 days ago

@frederikprijck but doesn't that mean that the interceptor can never be used correctly when not using the refreshFallback option? Since you can't react to the "getAccessTokenSilently" the way that is recommended here: https://auth0.github.io/auth0-spa-js/interfaces/Auth0ClientOptions.html#useRefreshTokensFallback

If that's the case, it would still be great to somehow use the "findMatchingRoute" method using the SDK, since otherwise I'd have to copy it for the custom solution and it will be out of sync with future updates to the SDK

frederikprijck commented 4 days ago

You can, but not with allowAnonymous set to true for the endpoint.

Im happy to review a PR that makes it protected.