Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Client Secret POST vs Client Secret BASIC #1519

Open
dana-n opened this issue Dec 16, 2024 · 2 comments
Open

Question: Client Secret POST vs Client Secret BASIC #1519

dana-n opened this issue Dec 16, 2024 · 2 comments

Comments

@dana-n
Copy link

dana-n commented Dec 16, 2024

Which version of Duende IdentityServer are you using?

6.3.10

Which version of .NET are you using?

.NET 8

Describe the issue

Is it possible to use BASIC Auth for OAuth 2.0 Authorization Code Grant Type?

We have configured an OidcProvider (Dynamic Identity Providers) to authorize against an external identity system that we do not control. This system expects ClientId and ClientSecret to be sent in an Basic Auth header.

Using raw HTTP, we tried sending sending client_id and client_secret in the body and get a 401 Unauthorized response:

POST: https://example.com/v2/oauth/token
Accept: application/json
Content-Type: application/x-www-form-urlencoded

client_id=example_client&client_secret=example_secret&code=example_code&scope=email&grant_type=authorization_code&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback

However, if we move credentials to the Authorization header, we get 200 OK:

POST: https://example.com/v2/oauth/token
Authorization: BASIC <base64 encoded creds>
Accept: application/json
Content-Type: application/x-www-form-urlencoded

code=example_code&scope=email&grant_type=authorization_code&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback

I have traced the issue to OpenIdConnectHandler.RedeemAuthorizationCodeAsync which is not part of Dunde's solution directly.

Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectProtocolException: Message contains error: 'Unauthorized', error_description: 'error_description is null', error_uri: 'error_uri is null'.
   at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.RedeemAuthorizationCodeAsync(OpenIdConnectMessage tokenEndpointRequest)
   at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleRemoteAuthenticateAsync()
   --- End of inner exception stack trace ---
   at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
   at Duende.IdentityServer.Hosting.FederatedSignOut.AuthenticationRequestHandlerWrapper.HandleRequestAsync() in /_/src/IdentityServer/Hosting/FederatedSignOut/AuthenticationRequestHandlerWrapper.cs:line 38

Interestingly enough, this functionality is supported from the IdentityModel NuGet package.

TokenResponse tokenResponse = await _httpClient.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest
{
    RequestUri = new Uri(TokenUrl),
    Code = code,
    RedirectUri = returnUrl,
    ClientId = ClientId,
    ClientSecret = ClientSecret,
    ClientCredentialStyle = ClientCredentialStyle.AuthorizationHeader,
});

I am just not seeing a way to set ClientCredentialStyle on the dynamic identity provider.

@AndersAbel
Copy link
Member

The Microsoft OpenIdConnectHandler only supports having the credentials in the post body and not in the authorization header.

It is possible to override the entire code redemption step through events. Implement the OnAuthorizationCodeReceived event and send the request to the token endpoint yourself. There is a prepared token request in the AuthorizationCodeReceivedContext.TokenEndpointRequest, you would just have to move the client id and secret out of it and into the authorization header (with proper encoding of course). When you have the response, call HandleCodeRedemption on the context to hand the result back for continued processing.

As a reference, this is what the Microsoft code for redeeming the code looks like if you want a starting point for your own implementation: https://github.com/dotnet/aspnetcore/blob/v8.0.11/src/Security/Authentication/OpenIdConnect/src/OpenIdConnectHandler.cs#L872-L915

@dana-n
Copy link
Author

dana-n commented Dec 19, 2024

@AndersAbel - Thanks for the tip!

We will see if we can plug into the OnAuthorizationCodeReceived like you are describing. Since we won't want this on all of the OidcProviders, I think we might be able to get this to work by saving an extra setting in the DB and later looking it up by using the ClientId on the token endpoint request object.

Thanks again for the information.

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

No branches or pull requests

2 participants