Failed to get AccessToken via authorization code using MSAL 1.1.0-preview in asp.net core

房东的猫 提交于 2019-12-11 04:25:18

问题


I followed official steps as below to try the scenario "web app calling a Web API in Azure Ad B2C", the only difference is I am using Asp.Net core. I am using AuthorizationCode to get the access token, but it always returns with id token and NULL access token.

  • Create an Azure AD B2C tenant.
  • Register a web api.
  • Register a web app.
  • Set up policies.
  • Grant the web app permissions to use the web api.

My code:

app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
    AuthenticationScheme = OpenIdConnectDefaults.AuthenticationScheme,
    AutomaticChallenge = true,
    ClientId = aadB2cSettings.ClientId,
    MetadataAddress = $"{aadB2cSettings.Instance}{aadB2cSettings.Tenant}/v2.0/.well-known/openid-configuration?p={aadB2cSettings.B2cSignUpOrSignInPolicy}",
    PostLogoutRedirectUri = aadB2cSettings.RedirectUrl,

    ResponseType = OpenIdConnectResponseType.CodeIdToken,
    TokenValidationParameters = new TokenValidationParameters
    {
        NameClaimType = "name"
    },

    Events = new OpenIdConnectEvents
    {
        OnAuthorizationCodeReceived = async context =>
        {
            var authCode = context.TokenEndpointRequest.Code;
            var b2cAuthority = $"{aadB2cSettings.Instance}tfp/{aadB2cSettings.Tenant}/{aadB2cSettings.B2cSignUpOrSignInPolicy}/v2.0/.well-known/openid-configuration";
            var cca = new ConfidentialClientApplication(
                aadB2cSettings.ClientId, 
                b2cAuthority,
                aadB2cSettings.RedirectUrl, 
                new ClientCredential(aadB2cSettings.ClientSecret), 
                new TokenCache(), 
                null);

            try
            {
                var authResult = await cca.AcquireTokenByAuthorizationCodeAsync(authCode, new[] { "https://hulab2c.onmicrosoft.com/b2cdemo/all" });
                context.HandleCodeRedemption(authResult.AccessToken, authResult.IdToken);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    },

Used fiddler to capture the request, it is:

POST https://login.microsoftonline.com/hulab2c.onmicrosoft.com/oauth2/v2.0/token?p=b2c_1_signuporsignin HTTP/1.1

Request Body:

client_id=1ff91f47-08ee-4973-83f4-379ad7e0679c&client_info=1&client_secret=......&scope=https%3A%2F%2Fhulab2c.onmicrosoft.com%2Fb2cdemo%2Fall+offline_access+openid+profile&grant_type=authorization_code&code=......&redirect_uri=https%3A%2F%2Flocalhost%3A44383%2F

Return:

{"id_token":"......","token_type":"Bearer","not_before":1494494423,"client_info":"......","scope":""}

So only id token, no access token. But we should get access token here, right?


回答1:


Finally found out my failure reason: the request to get AuthorizationCode doesn't contain the target scope. Reflect in code, for OpenIdConnectOption in aspnetcore, the Scope parameter is readonly and its default value is "opened profile". Scope is readonly in OpenIdConnectOption

So the default authorization code request sent is:

GET https://login.microsoftonline.com/hulab2c.onmicrosoft.com/oauth2/v2.0/authorize?p=b2c_1_signuporsignin&client_id=7f865ca0-271e-4f27-be21-6f0072fe3ad7&redirect_uri=https%3A%2F%2Flocalhost%3A44355%2Fsignin-oidc&response_type=code%20id_token&scope=openid%20profile&response_mode=form_post&nonce=...... HTTP/1.1

Thus, using this authorization code in response to get token, even we set right scope in the token request, we still can't get the access code but only id token, because the provide authorization code is only for "openid profile".

To fix this, we need to add target web api scope into the authorization code as well. Here is the how-to-fix code:

Events = new OpenIdConnectEvents
{
       OnRedirectToIdentityProvider = context =>
       {
            context.ProtocolMessage.Scope += $" offline_access {myapiscope}";

            return Task.FromResult(0);
       },
       ......
}

In AspNet, we don't need to do this because its scope is not readonly as aspnetcore and can be set directly:

new OpenIdConnectAuthenticationOptions
{
      ......
      Scope = $"openid profile offline_access {ReadTasksScope} {WriteTasksScope}"
}



回答2:


https://github.com/Azure-Samples/active-directory-b2c-dotnet-webapp-and-webapi/issues/4 Microsoft have reproduced the issue and working on fix



来源:https://stackoverflow.com/questions/43970669/failed-to-get-accesstoken-via-authorization-code-using-msal-1-1-0-preview-in-asp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!