I'm trying to create an authentication flow where the user's access token is kept in a server-side session along with the refresh token, and when the token expires it is renewed if the session is still valid. However, the token I get back from Azure AD after refresh has an invalid signature, when verifying it with the same method as the original token.
Here's a runnable gist that illustrates the problem: https://gist.github.com/tlycken/fdaf47dc31e03de43a1a07fbbea2ab91
What I'm doing is basically this:
When the user requests a page, check for a session. If none exists, redirect to /auth
which redirects to Azure AD, and when I'm returned I have a valid token which I store in the session.
Verify the token from the session using jwks-rsa
. (This normally works fine, so I'm purposely adding something to the token string to make the signature invalid in the test code.)
If token verification failed, and there is a refresh token on the session, try to fetch a new token using that refresh token. This request normally returns with status 200 OK
and a new set of access/refresh tokens.
Verify the new access token using the same code as was used to verify the old one (now without garbling the token). This should work, IIUC, but it fails with the error invalid signature
.
Why does my newly refreshed token not pass verification?
Update: I was able to create a simpler flow for reproducing this; the gist has been updated. It now does the following (printing these messages, along the way):
no session, redirecting to /auth
successful auth callback, redirecting to /
verifying old token
decoded user id e7f02a6e-510c-430d-905c-f8a0e63206c2
refreshing
fetching /me with renewed token
got user id e7f02a6e-510c-430d-905c-f8a0e63206c2
verifying new token
token verification failed: invalid signature
In addition to validating the token myself, I now also send a request to Azure with it, hoping that such a request would fail for an invalid token. But it passes!
Refresh the access token The OAuth 2.0 authorization code grant can be used in apps that are installed on a device to gain access to protected resources, such as web APIs. Using the Microsoft identity platform implementation of OAuth 2.0, you can add sign in and API access to your mobile and desktop apps.
Therefore, when you receive the OAuth access token from the caller, you should first validate two things: This token was generated by Azure AD & its contents have not been altered The second part of this validation process is very simple. You need to check the audience part of the JWT token.
Azure Active Directory (Azure AD) supports all OAuth 2.0 flows. Rich client and modern app scenarios and RESTful web API access. User: Requests a service from the web application (app). The user is typically the resource owner who owns the data and has the power to allow clients to access the data or resource.
The OAuth 2.0 authorization code flow is described in section 4.1 of the OAuth 2.0 specification. With OIDC, it's used to perform authentication and authorization in the majority of app types, including single page apps, web apps, and natively installed apps.
You're code is using the v1 Endpoint to obtain the initial access token but the v2 Endpoint to exorcise the refresh token. These two endpoints operate differently. In particular, the v1 Endpoint uses "resource" while v2 uses "scopes".
The reason this is happening is your calling v1 explicitly but relying on the v2 /openid-configuration
for the Refresh Token endpoint.
To correct this, change line 19 of refresh-auth-token.js
to
const configResponse =
await fetch(`https://login.microsoftonline.com/${AZURE_TENANT}/.well-known/openid-configuration`)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With