0

I have a linux Web App on Azure (fastAPI) that currently has these responsibilites

  • serves a Single Page Application (SPA)
  • is a reverse proxy for the backend

For this API, I use the built-in authentication feature "Easy Auth".

What I currently do is the following flow:

  • User requests SPA -> is redirected to the identity provider -> authenticates himself, gets the a cookie injected into his browser and is redirected to the web app through the callback URL setup in the AAD App & gets the SPA code
  • SPA then makes requests against the protected API with the injected cookie (HTTP cookie)

Because the SPA does not call the API with a auth token (bearer token), I want to exchange the cookie for an auth token on the server (API). For this, the API uses that cookie from the request to call the /.auth/me endpoint (blob storage token store) to get more information about the user, from which it can extract the id_token or the access_token.

From here, I noticed that the id_token can be used to call to another API that is protected by the same Azure AD App through EasyAuth.

However, the id_token is sometimes expired and calling the /.auth/refresh does only refresh the access_token.


Question(s):

General question: Why can the id_token be used to access the downstream API. I thought this is the job of the access_token?.

Edit: Turns out that:

The OAuth 2.0 implicit flow in Azure AD is designed to return an ID token when the resource for which the token is being requested is the same as the client application.

Actual question: Is there a way to also refresh the id_token without needing the user to re-authenticate? Similar to calling the /.auth/refresh endpoint? Or what would be the right approach? Or am I doing things completely wrong and the SPA should just get a auth token and then make requests against the API?


Simliar questions:

Johannes Schmidt
  • 371
  • 3
  • 12
  • _"From here, I noticed that the `id_token` can be used to call to another API that is protected by the same Azure AD App through EasyAuth."_ - that shouldn't be possible:: [the OIDC spec](https://openid.net/specs/openid-connect-core-1_0.html) (which builds on OAuth2) make it abundantly clear that `id_token` **cannot** be used as a bearer-token: it's just a bunch of user-profile claims and info about the user's session: [Auth0 (an IdP-as-a-Service company) has a good article on that topic](https://auth0.com/blog/id-token-access-token-what-is-the-difference/) – Dai Jul 12 '23 at 19:49
  • @Dai That's what I thought and this is what confuses the hell out of me. The `id_token` as bearer token is accepted by the API but not the `access_token`. Does this mean that this is specifc to Azure? Thanks for article, I'll read it thorougly. – Johannes Schmidt Jul 12 '23 at 20:20
  • @Dai Found the answer for this behaviour in Azure: [id_token as bearer token](https://stackoverflow.com/questions/54988875/azure-ad-id-token-as-bearer-token) – Johannes Schmidt Jul 12 '23 at 20:24
  • Yikes, wow - that's rather egregious – Dai Jul 12 '23 at 20:30

1 Answers1

0

I created an Azure AD SPA Application like below:

enter image description here

For sample, I generated ID token using Implicit flow:

https://login.microsoftonline.com/TenantID/oauth2/v2.0/authorize?
client_id=ClientID
&response_type=id_token
&redirect_uri=https://jwt.ms
&scope=scope
&response_mode=fragment
&state=12345
&nonce=678910

enter image description here

Yes, you are right @Johannes Schmidt, when a resource for which a token is the same as the client application, the OAuth 2.0 implicit flow in Azure AD is intended to return an ID token. To generate access token, modify &response_type=token.

  • When making calls to the backend API of your application, this ID token can then be used as a bearer token.

  • In most cases, the ID token is acquired during the first authentication flow and is not meant to be refreshed separately. Re-authenticate the user in order to get a new ID token, if the ID token expires.

  • You can make use of access token instead of ID token to call the APIs as access token is used for authorization and ID token is used for authentication.

  • Make use of one Azure Ad App for each app service instead of same Azure Ad app

Reference:

oauth 2.0 - Azure AD: id_token as bearer token - Stack Overflow by Imran Arshad

Rukmini
  • 6,015
  • 2
  • 4
  • 14
  • Thanks for the answer. However, I don't want to modify the SPA to aquire a token for the user but rather that requests from the SPA to the server use the cookie. How would I modify the AppService's EasyAuth settings (authsettingsV2) so that the implicit flow returns an access token instead of an id token? It reads like we can't do that. That's why right now my solution would be to not share the same AzureAD App for both frontend and backend and instead use one AzureAD app for each App Service. – Johannes Schmidt Jul 13 '23 at 13:14
  • While helpful, the question was not how to get an access token (instead of id_token) but rather how the flow that I described can be used with a single Azure AD App. Turns out that the consequence of this configuration (in AZURE!) is that we have to deal with id_tokens instead of access_token. This means that the "right" solution would be to use a second Azure AD app as described in the [docs](https://learn.microsoft.com/en-us/azure/app-service/tutorial-auth-aad?pivots=platform-linux). – Johannes Schmidt Jul 13 '23 at 13:32
  • You're right, I will provide a full, detailed answer later on. – Johannes Schmidt Jul 13 '23 at 14:32