Skip to content
This repository has been archived by the owner on Mar 3, 2022. It is now read-only.

Network Error when trying to use PKCE with Angular SPA and Azure Active Directory #1024

Closed
blueelvis opened this issue Dec 22, 2019 · 12 comments

Comments

@blueelvis
Copy link

Hi!

I am trying to use this package for getting PKCE to work with an Angular SPA with Azure Active Directory.

I am using the following blog posts for reference -

  1. Initial Setup - https://www.scottbrady91.com/Angular/SPA-Authentiction-using-OpenID-Connect-Angular-CLI-and-oidc-client
  2. PKCE Setup (Just changing the response_type to code) - https://www.scottbrady91.com/Angular/Migrating-oidc-client-js-to-use-the-OpenID-Connect-Authorization-Code-Flow-and-PKCE

The problem is that when I am using the Access Tokens or ID Tokens workflow, the setup is working fine and I am able to hit the backend API. But, when I change the response_type to code, I am getting a Network Error like below -

image

I checked the network tab and I seem to be successfully getting the Azure Active Directory Bearer Token using the PKCE flow but because of the above, I am not able to query the backend API. It spits out the error while doing the following -

completeAuthentication(): Promise<void> {
      return this.manager.signinRedirectCallback().then(user => {
          this.user = user;
      });
  }

Any idea what I might be doing wrong?

Thanks,
Pranav

@brockallen
Copy link
Member

Can you provide more info on the request/response payload for the token endpoint HTTP call?

@blueelvis
Copy link
Author

@brockallen - Please find the information below (I have edited some of the tokens and GUIDs to remove potentially sensitive information -

POST
https://login.microsoftonline.com/b1519f0f-aaaa-aaaa-aaaa-a686ce97588a/oauth2/v2.0/token

Request Headers -

Host: login.microsoftonline.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 993
Origin: https://localhost:4200
DNT: 1
Connection: keep-alive
Referer: https://localhost:4200/

Response Headers -

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
x-ms-request-id: 6fbba727-1faa-4710-ab65-d5ce90728100
x-ms-ests-server: 2.1.9767.22 - SAN ProdSlices
Referrer-Policy: strict-origin-when-cross-origin
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"
Set-Cookie: fpc=ArYcKccR2xhAmH0bPVDWXoU8kAppAQAAAFNiktUOAAAA; expires=Wed, 22-Jan-2020 07:23:00 GMT; path=/; secure; HttpOnly; SameSite=None
Set-Cookie: x-ms-gateway-slice=prod; path=/; SameSite=None; secure; HttpOnly
Set-Cookie: stsservicecookie=ests; path=/; SameSite=None; secure; HttpOnly
Date: Mon, 23 Dec 2019 07:23:00 GMT
Content-Length: 2589

Request Payload

client_id=baf7d4b2-aaaa-aaaa-aaaa-10464c3b8c67&code=OAQABAAIAAACQN9QBRU3jT6bcBQLZNUj7knCH6fdDWS6mHIRC7Azp7jaPuJhNc3itJUHsXTV3edVb_qUVndtP-H2xUq-VP9cJWX5nGOQgc3AVk4yncUHFTMOeIS1na1i1rWs_IWI69Oaw4ddbbGVPWxi0ZeJRYIb7CaMO8ews4eIEbFjZ_Eo3M52kKq8KlTYu5ZjqbFBl7XMKxV-II33NvGtVTiY-wT12pm1xEfZncGoPgwvmijC2FFumlbOXFNym231B879CPaM19OK8HCx8OYYWZtFKkyyQDGN3YfOoWtiLp25DEqe9h5TWmiLcN6kIwx9svjYwFiLCCTWiM6hEaAdr1njVR9t-YrkoCnGJdka8nfkyneyds0D5sdwrCR9JnYcSfcgYUsjdpzxsEEZ_vt-CkmRHa_nJtN-Lwo2bG0JX3GxWx8OgT8xK0tyfWiiJIhCOy-YAC_16qnY0TQCYx31tz9R35hLirCFNC-QNS8bjvUIr-UHLIel8H04CgYTlL3GVyyqHRrKMTVNlQmY6JC_Yn9qcxfsrMTF8mlbCbzRpZ4t87oxB1lNldke640pgERxdPcuG1OKXtvmsNNFltI6kghDrKydZeHXX0rvmrJDisL5AhsIv8l8NRvjxNevme3lBojFIUGB6B6cVLFZiRk1iQWeR4Xr21ojwrJZF3sslP6zFiRxU0Xa3ujTjvPkvgmliMm9Q3EKpccO8WWBzU-yxdFVKTC_AIAA&redirect_uri=https%3A%2F%2Flocalhost%3A4200%2Fauth-callback&code_verifier=3fc1ca6240484b57b9d72ac9666fdd5ca3fbead3f4df428dbd47c041b8bd0ed8542e348313804feb90d7218111dc4116&grant_type=authorization_code

Response Payload -

{"token_type":"Bearer","scope":"ab10f4de-aaaa-aaaa-aaaa-d6b3ef854364/access_as_user","expires_in":3599,"ext_expires_in":3599,"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6InBpVmxsb1FEU01LeGgxbTJ5Z3FHU1ZkZ0ZwQSIsImtpZCI6InBpVmxsb1FEU01LeGgxbTJ5Z3FHU1ZkZ0ZwQSJ9.eyJhdWQiOiJhYjEwZjRkZS01NDRlLTQ5YzctYTViOC1kNmIzZWY4NTQzNjQiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9iMTUxOWYwZi0yZGJmLTRlMjEtYmYzNC1hNjg2Y2U5NzU4OGEvIiwiaWF0IjoxNTc3MDg1NDgwLCJuYmYiOjsImV4cCI6MTU3NzA4OTM4MCwiYWNyIjoiMSIsImFpbyI6IjQyVmdZQ2c0d0xmWFdTRzMzdXQxQXgvYjRSdHFwWFhHTStSL1c1NllyNXNqMjliakoxVVVwZjVjWCt5S3d5c3BZMXVWUitXM0FRPT0iLCJhbXIiOlsicHdkIl0sImFwcGlkIjoiYmFmN2Q0YjItNjE5OS00NGNkLTgyZGItMTA0NjRjM2I4YzY3IiwiYXBwaWRhY3IiOiIwIiwiZ2l2ZW5fbmFtZSI6InByYWNkZXYiLCJpcGFkZHIiOiIxMjguMTk5LjIwMy45NyIsIm5hbWUiOiJwcmFjZGV2Iiwib2lkIjoiMzNlZWI0OTMtOWU0Yy00MzRkLWJiNjktNjZiMjkzZjY2ZDFlIiwib25wcmVtX3NpZCI6IlMtMS01LTIxLTIwOTY3MTE1OTAtMTQzOTUwNTcwMi03NDM3OTQzMDAtNzM4NzYwIiwic2NwIjoiYWNjZXNzX2FzX3VzZXIiLCJzdWIiOiItRWt1Vm9pNVRYcDJqUWJmR3NyU2ttYzgtSlI4NVgxUGlqNzRTRVF6OTNBIiwidGlkIjoiYjE1MTlmMGYtMmRiZi00ZTIxLWJmMzQtYTY4NmNlOTc1ODhhIiwidW5pcXVlX25hbWUiOiJwcmFjZGV2QGF2ZW5kcmEuY29tIiwidXBuIjoicHJhY2RldkBhdmVuZHJhLmNvbSIsInV0aSI6Iko2ZTdiNm9mRUVlclpkWE9rSEtCQUEiLCJ2ZXIiOiIxLjAifQ.gq8M3UFSiuRirz8CnbthtU-y2YCR0g94Cg9crUyjWnJRL6Ky6WgWmBC4iguoyJmpN4RJS816a1539NRfUdcE1Br7GnYgh-EqnOX2rKw9WxL5DgjEXy4ivR50LbjrHrND8NKfATt19IZh7e7ZP4fhuxlJXxBHmjsQ0qNi3CMkPMxQNXr5xC4l-sylUyaAV4Qpm4aEtOy8sfCTbO_tg25hgC8Vsd74Fx7gjPaZYbEk-am1sZ_J55MYj1dcDM8dD9vOLVwYQLUmqmiXqzN3aaHr0NmsRMGxLUDT-YJwQ3j8zW8Tta2vIZx0i_8ygieYSEusTSdyrxEPJ5-ZbE6BThzO_Q","id_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InBpVmxsb1FEU01LeGgxbTJ5Z3FHU1ZkZ0ZwQSJ9.eyJhdWQiOiJiYWY3ZDRiMi02MTk5LTQ0Y2QtODJkYi0xMDQ2NGMzYjhjNjciLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vYjE1MTlmMGYtMmRiZi00ZTIxLWJmMzQtYTY4NmNlOTc1ODhhL3YyLjAiLCJpYXQiOjE1NzcwODU0ODAsIm5iZiI6MTU3NzA4NTQ4MCwiZXhwIjoxNTc3MDg5MzgwLCJhaW8iOiJBVFFBeS84TkFBQUFFV2ZNc0thaTFnWWZFmS3UzdmtTSmpHQUlVTUhSb2VZbVBoR0RLc0xJK0ZSbUVEdWgzdVZNdktLIiwic3ViIjoiUDNoOEs2N19iTWxJbE9pdGdHZEJPTmEyeVNYM3pWSHBINlNqS0IwbVd0ayIsInRpZCI6ImIxNTE5ZjBmLTJkYmYtNGUyMS1iZjM0LWE2ODZjZTk3NTg4YSIsInV0aSI6Iko2ZTdiNm9mRUVlclpkWE9rSEtCQUEiLCJ2ZXIiOiIyLjAifQ.AD3SAUl1Rv0U8b9IsgYk5dI78fuPcaB0FH1WfTKXNQLx30yoSH2YOgAgK7FoqiqfWVvPhc2laNvYjBSwjJuzc77VopdQ7ogRA_h2seYW7IDWOq_8w4C9ThYxWnpbx6zqa6WX_31MIFUj1AzzhVqSqPc7ltJH7bvzUEXFZiOru5bUfQQ4ot62qE6fzfvhOMbIWoVFB0gn1odX44-n2RYaNJ063gmGxV5SeN8Ru8o3qI4XlyPmyIx_k86FEoPFQ5nZQjxZJkgQyEmQtVlPJlQimCmeXxAnatrfQCFHR4RAdFeTfA_0WbBmJLf2OdGahg2Mb7IewUKFzje1anYMJkP6Yw"}

Here is the config which is being used in the code -

export function getUserManagerSettings(): UserManagerSettings {
  return {
        authority: 'https://login.microsoftonline.com/b1519f0f-aaaa-aaaa-aaaa-a686ce97588a',
        client_id: 'baf7d4b2-aaaa-aaaa-aaaa-10464c3b8c67',
        redirect_uri: 'https://localhost:4200/auth-callback',
        post_logout_redirect_uri: 'https://localhost:4200/',
        response_type: 'code',
        response_mode: 'query',
        scope: 'openid ab10f4de-aaaa-aaaa-aaaa-d6b3ef854364/access_as_user',
        filterProtocolClaims: false,
        loadUserInfo: false,
        metadataUrl: 'https://login.microsoftonline.com/b1519f0f-aaaa-aaaa-aaaa-a686ce97588a/v2.0/.well-known/openid-configuration'
  };
}

@jorgecarleitao
Copy link

In Azure AD, is your app registered as a native / desktop app? Checking since last time I checked, client_secret is required for web apps with the code flow.

In the portal, you can check this under app registration > authentication > Redirect URIs. The redirect url's type should be Public client / Native for the PKCE to work on Azure AD.

The explanation is found here, on the item client_secret.

@blueelvis
Copy link
Author

@jorgecarleitao - Yep. The redirect URI is set to "Public Client/Native". As mentioned above, the PKCE flow seems to work because I am getting the code and token. Just seems as if there is some issue in the code with this library in saving it properly?

@jorgecarleitao
Copy link

I was able to reproduce this issue on the vanilla example. I pushed the changes to reproduce the issue here.

The steps to reproduce are:

  1. npm start
  2. go to http://localhost:3000/user-manager-sample.html
  3. press start signin main window
  4. authenticate
  5. press end signin main window

This will cause the Network error that @blueelvis is describing.

@brockallen
Copy link
Member

@jorgecarleitao thx for that. i'll have a look when i can

@jorgecarleitao
Copy link

jorgecarleitao commented Dec 23, 2019

I have some time, so I spent some time investigating this.

My conclusion is that this is an error on the AD side.

Some facts:

  1. The error is triggered on this line because the request's status is !== 200
  2. The request is completed (readyState === 4) and its status is 0
  3. status 0 is not a valid HTTP status, so it can never be sent by the server.
  4. As per this SO question, when the header for CORS is not present XMLHttpRequest can have a status 0.
  5. The browser shows an error about a missing CORS header on the request to /token.
  6. The browser shows that the response is status 200.
  7. The response does not contain the header Access-Control-Allow-Origin

Overall, this explains why the browser receives the response with status 200 and the token, but it does not pass it down to the js: the server is telling it not to.

So, it seems to me that Microsoft is not allowing CORS requests to the /token endpoint, which is counter the whole idea of PKCE on clients, of as far as I can understand of OAuth2.

Could someone with more experience of this chip in and validate/refute this hypothesis? If valid, we should raise it on Microsoft side and close this issue.

EDIT: To validate this hypothesis, I installed a Firefox extension to temporarily disable CORS checks, and I was able to get the response across and no error was shown.

EDIT 2: upon further investigation, PKCE for SPA is not supported by Microsoft AD, as per this discussion and in particular this comment. I thus recommend that we close this as won't fix.

@brockallen
Copy link
Member

Could someone with more experience of this chip in and validate/refute this hypothesis? If valid, we should raise it on Microsoft side and close this issue.

This all sounds legit to me. I know they didn't support CORS on the discovery endpoint for the longest time. It'd not surprise me if they didn't support CORS on the token endpoint.

@brockallen
Copy link
Member

I asked someone who might know: https://twitter.com/BrockLAllen/status/1209178114804375552

@brockallen
Copy link
Member

EDIT 2: upon further investigation, PKCE for SPA is not supported by Microsoft AD, as per this discussion and in particular this comment. I thus recommend that we close this as won't fix.

Ah, sorry -- I missed this last comment. Thanks for looking into it.

@blueelvis
Copy link
Author

blueelvis commented Jan 1, 2020

@brockallen @jorgecarleitao - Thanks a lot guys for the detailed explanation and investigation on this! Just curious but is it possible to catch the situation particularly about the CORS and mention in the logs? Otherwise, the way the log is written, it seems quite something else.

Happy new year!

@brockallen
Copy link
Member

Well, from the http error you can't quite tell that's the exact reason.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

No branches or pull requests

3 participants