2019-05-21
Oauth 2.0 | SPA | How does id_token disguise as an access_token for accessing restricted web resources?
stackoverflow
Question

I am working on integrating Azure Active Directory for my Angular SPA (or any Javascript) application. Application has a front-end (built with JavaScript) and a Web API (built with any c# or any server side languages).

For reference, https://github.com/Azure-Samples/active-directory-angularjs-singlepageapp

I know that I configured OAuth 2.0 Implicit Grant in SPA AAD Registration. OAuth 2.0 Implicit Grant is slightly relaxed to let SPA gaining access to web resources tied to SPA AAD Registration by redeeming 'id_token'.

OAuth 2.0 Implicit Grant Protocol:

  1. Reach Azure Auth Endpoint with client_id, resource,.. for id_token
  2. Challenge it with credentials
  3. Get id_token as it is posted back to SPA URI.
  4. Use id_token as bearer token to access the restricted web resources.

SPA works very well with id_token and OAuth 2.0 Implicit Grant Protocol.

Reason why we could not acquire access_token from SPA or JS:

SPA could not send XHR to Azure Token Endpoint as SPA is blocked by CORS Policy of Azure Token Endpoint. So, SPA XHR could not acquire access_token.

It looks like this is a special case for SPA alone.

QUESTIONS:

  1. How does AAD determine which web resources that 'id_token' holder can access? By looking up the web resources tied to SPA AAD Registration?

    [OP] Adal.js is responsible for intercepting our post-backs to receive and store tokens like id_token & access_token

  2. Cannot AAD implement the following approach?

    • Redirect to Azure Auth Endpoint with client_id, resource,.. for Auth Code.
    • Acquire Authorization_Code from Azure Auth Endpoint by posting it back to SPA URI.
    • Instead for XHR to Azure Token Endpoint, can't we redirect to Azure Token Endpoint with Auth_Code, client_id, resource,.. to let Azure Token Endpoint post back the access_token back to redirect_uri?

    [OP] Adal.js had other plans to use iFrames to call Cross-domain API (Az Token Endpoint, in this case) and acquire Access Tokens.

P.S. I need real answers for above questions. This case is now solved :)!

Answer
1

How does AAD determine which web resources that 'id_token' holder can access? By looking up the web resources tied to SPA AAD Registration?

It doesn't. If your API is configured to accept valid AAD tokens with the audience set to your front-end app's client id, it'll accept the token. This isn't a good pattern though, you should use access tokens to call APIs.

As for your question regarding access tokens, a front-end can acquire access tokens through implicit flow by using a redirect or a hidden iframe. If you use ADAL.js or MSAL.js, they do this for you automatically if you ask for an access token from them.

Essentially they open an iframe that goes to the /authorize endpoint with:

  • response_type=token
  • resource=https%3A%2F%2Fgraph.microsoft.com or scope=https%3A%2F%2Fgraph.microsoft.com%2FUser.Read if using v2/MSAL
  • prompt=none

The last parameter tells AAD to not do a prompt (it's a hidden iframe). If a valid session still exists in the user's browser and consent has been granted for the scopes asked, a token is returned as a redirect to your SPA within the iframe. ADAL/MSAL then can grab the token from the iframe URL as they are running on the same host name.

Because of the way this works, you'll want to check if you are within an iframe when your SPA loads and not render the app at all if it is.

And no, you cannot call the /token endpoint from a JS front-end.

Oauth 2.0 | SPA | How does id_token disguise as an access_token for accessing restricted web resources?
See more ...