Hello,
tl;dr I would like to understand how I can extract the User Sub claim from an Access Token.
Context:
We’re building an SPA that exclusively uses serverless function (from Vercel) to make authenticated calls to an IdP at throughput (60 calls/min, which are bursted in <1 sec, every sec) that is faster than the Auth0 Authentication /userinfo
endpoint ratelimit (5 calls/min). We use this endpoint to hit the Management /api/v2/users/{id}
endpoint and retrieve the IdP Access Tokens, which we then store in a Redis DB to be cache’d for future requests. However we would still need to make a /userinfo
call every time the serverless function runs so we can obtain the sub which used as the key in Redis. If the serverless function can decode the sub from the access token, we could just ask the redis cache directly, avoiding calls to Auth0 for all requests outside of login.
System Arch:
The following are how we understand and implement both Login and Authenticated Calls to IdP flows, followed by how we would ideally like to make the Authenticated Calls to IdP.
Login:
- Trigger
loginWithPopup()
on the browser client and login with IdP - Auth0 completes OAuth1 flow with IdP API
- IdP API returns IdP Access tokens to Auth0 *which is stored in an Auth0 DB
- (accidentally labeled this 5) Auth0 return ID and accessTokens to Browser? (this part is unclear to me, tho probably not important to the problem)
- ^^
- Browser Client sends Access Token retrieved by the
auth0-spa-js
functiongetTokenSilently()
to Vercel - Vercel hits
/userinfo
endpoint with Access Token as Bearer - Auth0 replies with User Info
- Vercel hits
/api/v2/users/{id}
where ID is the extracted Sub Claim from the Auth0 response is the previous step - Auth0 responds with an object that contains the IdP access token *which was retreived from an Auth0 DB
- Finally Vercel stores the info in a Redis DB where the key is the sub and the value is the IdP Access Token
Authenticated Call to IdP (this is made 60/min) :
- Logged In User makes request that requires data from the IdP with the Auth0 Access Token retrieved by the
auth0-spa-js
functiongetTokenSilently()
passed in the request - Vercel hits
/userinfo
endpoint with Access Token as Bearer - Auth0 replies with User Info
- Vercel sends extracted Sub Claim from the Auth0 response is the previous step to Redis DB
- Redis DB finds the key (Sub Claim) and returns the value (IdP Access Token)
- Vercel makes authenticated request to IdP using the user’s IdP Access Token
- IdP API returns payload
- Vercel passes payload back to User
Steps 2 and 3 are the problematic ones because this call to Auth0 would be made 60/min, bursted in <2sec
Referencing some documentation from Auth0:
https://auth0.com/docs/tokens/access-tokens
The token does not contain any information about the user except for the user ID (located in the
sub
claim).
Since we use the Sub Claim to store the IdP Access Token, we could decode the Access Token instead of making the call to Auth0 to get the Sub Claim.
However in our testing we found that the Access Token retrieved by the auth0-spa-js
function getTokenSilently()
is not a JWT, which is corroborated by Auth0 Docs:
https://auth0.com/docs/tokens#access-tokens
Access tokens (which aren’t always JWTs) […]
In what ways could we decode the Access Token into a Sub Claim. And if this is not possible, how can we avoid calls to Auth0 API when we need make requests to the IdP. Our ideal flow would look like the following: