Skip to content

Conversation

@markdespain
Copy link
Contributor

Greetings!

I discovered oauth2c today, and it is was exactly what I was looking for.

However, I have an app in Entra that is registed as a desktop application that uses the "authorization code flow with PKCE", and I'd like to be able to get an access token for it.

Unfornately, I discoved that

  • Entra interprets the Origin header as an indicator that is a different type of app, returning an error (see Before below)
  • oauth2c always includes an Origin header when a --redirect-url is specified

In order to help oauth2c support my use case, this PR adds a --no-origin flag, to indicate that the Origin header not be emitted (see After farther below). Though, do let me know if they may be another way to handle this, as there could easily be something I've overlooked.

Cheers!

Before

oauth2c https://login.microsoftonline.com/<redacted> \
  --client-id <redacted> \
  --response-types code \
  --response-mode query \
  --grant-type authorization_code \
  --auth-method none \
  --scopes "<scopes>" \
  --pkce \
  --redirect-url http://localhost:50051/oauth/redirect

... the response is like so...

Response:                                                                                                                                                                           
{                                                                                                                                                                                   
  "error": "invalid_request",
  "error_description": "AADSTS9002326: Cross-origin token redemption is permitted only for the 'Single-Page Application' client-type. Request origin: 'http://localhost:50051'. Trace ID: 787a709b-5a37-41a9-b410-9a2ecedb8100 Correlation ID: 686bfee3-0e2f-48fc-abd7-0fa83caa40f1 Timestamp: 2025-05-22 10:44:42Z"
}
                                                                                                                                                                                    
  ERROR   400: invalid_request         

After: using new --no-origin flag

% go build -o ./oauth2c
% ./oauth2c https://login.microsoftonline.com/<redacted> \
  --client-id <client-id> \
  --response-types code \
  --response-mode query \
  --grant-type authorization_code \
  --auth-method none \
  --scopes "<redacted>" \
  --pkce \
  --redirect-url http://localhost:50051/oauth/redirect
 --no-origin

As a result an access token can be successfully obtained for my Entra app:

┌─────────────────────────────────────────────────────────────────────────────────────────┐
| Issuer URL     | https://login.microsoftonline.com/<redacted> |
| Grant type     | authorization_code                                                     |
| Auth method    | none                                                                   |
| Scopes         | <redacted>         |
| Response types | code                                                                   |
| Response mode  | query                                                                  |
| PKCE           | true                                                                   |
| Client ID      | <redacted>                                   |
└─────────────────────────────────────────────────────────────────────────────────────────┘

                                                                                                                                                                                    
                                                                              Authorization Code Flow                                                                               
                                                                                                                                                                                    

# Request authorization

GET https://login.microsoftonline.com/<redacted>/oauth2/authorize
Query params:
  nonce: <redacted>
  state: <redacted>
  client_id: <redacted>
  redirect_uri: http://localhost:50051/oauth/redirect
  response_mode: query
  response_type: code
  scope: <redacted>
  code_challenge: <redacted>
  code_challenge_method: S256

┌─ PKCE ──────────────────────────────────────────────────────────┐
| code_verifier = <redacted>     |
| code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) |
└─────────────────────────────────────────────────────────────────┘

Go to the following URL:

https://login.microsoftonline.com/<redacted>/oauth2/authorize?client_id=<redacted>

Opening browser...

GET /oauth/redirect                                                                                                                                                                 
Query params:                                                                                                                                                                       
<redacted>                                                                                                                             
                                                                                                                                                                                    
 SUCCESS  Obtained authorization code                                                                                                                                               


# Exchange authorization code for token

POST https://login.microsoftonline.com/<redacted>/oauth2/token                                                                                            
Headers:                                                                                                                                                                            
  Content-Type: application/x-www-form-urlencoded                                                                                                                                   
Form post:                                                                                                                                                                          
  grant_type: authorization_code                                                                                                                                                    
  client_id: 7dfaabe0-f70a-4ca6-9f7b-a3c5303f4071                                                                                                                                   
  redirect_uri: http://localhost:50051/oauth/redirect                                                                                                                               
  code: <redacted>                                                                                                                       
Response:                                                                                                                                                                           
{                                                                                                                                                                                   
  "access_token": "<redacted>",
  "expires_in": 4655,
  "id_token": "<redacted>",
  "refresh_token": "<redacted>",
  "scope": "<redacted>",
  "token_type": "Bearer"
}
Access token:                                                                                                                                                                       
{                                                                                                                                                                                   
<redacted>
}
ID token:                                                                                                                                                                           
{                                                                                                                                                                                   
<redacted>
}
                                                                                                                                                                                    
 SUCCESS  Exchanged authorization code for access token                                                                                                                             

{"access_token":"<redacted>","expires_in":4655,"id_token":"<redacted>,"scope":"<redacted>","token_type":"Bearer"}

@mbilski
Copy link
Contributor

mbilski commented May 28, 2025

Hi @markdespain

Thank you for your PR.

Although this is a valid fix, I started wondering if always adding the Origin headers makes sense.

Please take a look at #108 and #109

Perhaps it would be better to introduce a slight breaking change, and instead of adding a --no-origin flag, we should add a --with-origin flag instead?

What do you think?

@markdespain
Copy link
Contributor Author

Hi @mbilski ,

Thanks for taking a look.

Although this is a valid fix, I started wondering if always adding the Origin headers makes sense.

I haven't looked deeply into this consideration, but my understanding of OAuth is that the Origin header is not always required. Though, there seem to be case where it must be and where it must not be, as can be seen across this PR and those you've shared.

For my case, my application is registered as "Mobile and desktop application"... i.e. not running brower. So, for that case I can rationalize why Entra might not want an Origin header for that case.

Perhaps it would be better to introduce a slight breaking change, and instead of adding a --no-origin flag, we should add a --with-origin flag instead?

What do you think?

Solution-wise, I'm flexible and am happy to defer to you and any broader concensus.

I can easily flip the logic of my PR to implement --with-origin. So, perhpas let me know your thoughts on what makes sense for a next step.

@markdespain
Copy link
Contributor Author

Just touching base, @mbilski . Do you by chance have a suggestion based on my reply?

Copy link
Contributor

@mbilski mbilski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@markdespain sorry for the late response, let's go with the --no-origin flag

@mbilski mbilski requested a review from ikawalec June 23, 2025 09:10
@mbilski mbilski enabled auto-merge (squash) June 23, 2025 09:10
@mbilski mbilski merged commit 3741094 into SecureAuthCorp:master Jun 23, 2025
3 checks passed
@markdespain
Copy link
Contributor Author

@markdespain sorry for the late response, let's go with the --no-origin flag

All good! Appreciate the responses, and thanks for approving!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants