I've created an issue on github in case this is a bug.
PROBLEM
I'm trying to log in to an ASP.Net Core 2 Web App, using Azure AD with MSAL.
When I call AcquireTokenByAuthorizationCodeAsync
I get an error message.
MsalServiceException: AADSTS90023: Public clients can't send a client secret.
.
There's not many examples of coding doing exactly what I'm doing, but what does exist shows the ClientSecret
being passed to the ConfidentialClientApplication
as a ClientCredential
.
It's doubly confusing because the error message refers to a PublicClientApplication
which is not what I'm using, I'm using ConfidentialClientApplication
.
CODE
Here's the full method where the error occurs:
public void Configure(string name, OpenIdConnectOptions options)
{
options.Authority = $"{azureADOptions.Instance}{azureADOptions.TenantId}";
options.CallbackPath = azureADOptions.CallbackPath;
options.ClientId = azureADOptions.ClientId;
options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
options.UseTokenLifetime = true;
options.Events = new OpenIdConnectEvents
{
OnAuthorizationCodeReceived = async context =>
{
var clientID = options.ClientId;
var authority = options.Authority;
var redirectUri = this.azureADOptions.RedirectUri;
var clientCredentials = new ClientCredential(azureADOptions.ClientSecret);
var tokenCache = AzureADUtils.GetTokenCache(context.HttpContext, context.Principal);
var clientApp = new ConfidentialClientApplication(clientID, authority, redirectUri, clientCredentials, tokenCache, null);
try
{
var code = context.ProtocolMessage.Code;
var scopes = new[]
{
AzureADScopes.User.ReadBasicAll,
AzureADScopes.Group.ReadAll
};
//AJ: This line is where the exception is thrown.
var result = await clientApp.AcquireTokenByAuthorizationCodeAsync(code, scopes);
context.HandleCodeRedemption(result.AccessToken, result.IdToken);
}
catch (Exception)
{
throw;
}
}
};
}
The error message appears to come from the server-side, rather than being generated client-side, which makes a bit more sense as to why it's getting confused as to the type of *ClientApplication
class I'm using.
REQUEST & RESPONSE
Here's the request I send:
POST https://login.microsoftonline.com/[REMOVED]/oauth2/v2.0/token HTTP/1.1
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
Accept: application/json
Cookie: x-ms-gateway-slice=006; stsservicecookie=ests; esctx=[REMOVED]
x-client-SKU: MSAL.CoreCLR
x-client-Ver: 1.1.0.0
x-client-OS: Microsoft Windows 10.0.15063
client-request-id: [REMOVED]
return-client-request-id: true
x-ms-request-root-id: [REMOVED]
x-ms-request-id: [REMOVED]
Request-Id: [REMOVED]
Content-Length: 981
Host: login.microsoftonline.com
client_id=[REMOVED]
&client_info=1
&client_secret=[REMOVED]
&scope=Group.Read.All+offline_access+openid+profile+User.ReadBasic.All
&grant_type=authorization_code
&code=[REMOVED]
&redirect_uri=https%3A%2F%2Flocalhost%3A44365%2Fsignin-oidc
And the response I get back:
{
"error": "invalid_request",
"error_description": "AADSTS90023: Public clients can't send a client secret.\r\nTrace ID: [REMOVED]\r\nCorrelation ID: [REMOVED]\r\nTimestamp: 2017-09-18 16:12:51Z",
"error_codes": [90023],
"timestamp": "2017-09-18 16:12:51Z",
"trace_id": "[REMOVED]",
"correlation_id": "[REMOVED]"
}
This is very close to what is described in this MSDN Blog post under the heading "Step 2 - Get Access Token".
APP REGISTRATION
I've created a "Converged" application registration, which should be using the Azure AD v2 app model.
It has a single Application Secret, a Password, which is used as the Client Secret.
It has a single Platform, Web, with Allow Implicit Flow enabled, a single Redirect URL set, and no Logout URL.
I know the post is quiet old, but I just have had exactly the same problem. I found a resolution thanks to the documentation found here : https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Client-credential-flows.
My code works now with :
Be very careful to have a scope for which the user has consent and DO NOT USE
common
ororganization
as tenant id in theWithAuthority
method parameter but your tenant id (the guid one)Hope it's help !