'AADSTS70000:传输数据解析器失败:授权码格式错误或无效

'AADSTS70000: Transmission data parser failure: Authorization Code is malformed or invalid

我在使用 Microsoft 帐户验证用户时遇到问题。我正在使用 OpenId Connect 身份验证,但是当我调用 AcquireTokenByAuthorizationCodeAsync 方法时,我收到以下消息。

Exception thrown: 'Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException' in System.Private.CoreLib.dll: 'AADSTS70000: Transmission data parser failure: Authorization Code is malformed or invalid.

授权选项如下:

services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;

        }).AddOpenIdConnect(openIdOptions => 
        {
            openIdOptions.ResponseType = OpenIdConnectResponseType.CodeIdToken;
            openIdOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            openIdOptions.Authority = String.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}{1}", "common", "/v2.0");
            openIdOptions.ClientId = Configuration["MicrosoftAuth:ClientId"];
            openIdOptions.ClientSecret = Configuration["MicrosoftAuth:ClientSecret"];
            openIdOptions.SaveTokens = true;
            openIdOptions.TokenValidationParameters = new TokenValidationParameters{
                ValidateIssuer = false
            };
            var scopes = Configuration["MicrosoftAuth:Scopes"].Split(' ');
                foreach (string scope in scopes){
                    openIdOptions.Scope.Add(scope);
            }
            openIdOptions.Events = new OpenIdConnectEvents{
                OnAuthorizationCodeReceived = async (context) =>
                {   
                    var code = context.ProtocolMessage.Code;
                    var identifier = context.Principal.Claims.First(item => item.Type == ObjectIdentifierType).Value;
                    IMemoryCache memoryCache = context.HttpContext.RequestServices.GetRequiredService<IMemoryCache>();
                    var result = await GetTokenByAuthorizationCodeAsync(identifier, code, memoryCache);
                    context.HandleCodeRedemption(result.AccessToken, result.IdToken);
                },
            };
        });

这就是我的 GetTokenByAuthorizationCodeAsync 的样子(我知道它不漂亮,只是想让它工作):

public async Task<AuthenticationResult> GetTokenByAuthorizationCodeAsync(string userId, string code, IMemoryCache memoryCache)
    {
        TokenCache userTokenCache = new SessionTokenCache(userId, memoryCache).GetCacheInstance();
        try
        {
            AuthenticationContext authContext = new AuthenticationContext("https://login.microsoftonline.com/common/oauth2/v2.0/token/", userTokenCache);
            ClientCredential credential = new ClientCredential(Configuration["MicrosoftAuth:ClientId"], Configuration["MicrosoftAuth:ClientSecret"]);
            string[] scope = new List<String>().Append("https://graph.windows.net").ToArray();
            AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(code,new Uri(Configuration["MicrosoftAuth:RedirectUri"]), credential, Configuration["MicrosoftAuth:ResourceId"]);
            return result;
        }
        catch (Exception)
        {
            return null;
        }
    }

我不知道是什么导致了这个错误。如果我发送邮递员请求,我可以使用授权码,但我仍然无法在该请求中添加资源 ID。

我已在 Microsoft 的应用程序注册门户 (https://apps.dev.microsoft.com/) 中注册了该应用程序。

您正在使用 Microsoft.IdentityModel.Clients.ActiveDirectory 库来获取访问令牌。此库用于在 Azure 门户而不是 Azure AD v2.0 端点上注册的 Azure AD 应用程序。

要获取 Azure AD V2.0 应用程序的令牌,我们可以使用 MSAL 库。这是供您参考的代码示例:

OnAuthorizationCodeReceived = async (context) =>
{
    var code = context.ProtocolMessage.Code;
    ConfidentialClientApplication cca =
        new ConfidentialClientApplication(Configuration["AzureAD:ClientId"], Configuration["AzureAd:PostLogoutRedirectUri"]+ "signin-oidc", new ClientCredential(Configuration["AzureAD:Secret"]), null, null);
    var result =await cca.AcquireTokenByAuthorizationCodeAsync(code,new string[]{"user.read"});
    context.HandleCodeRedemption(result.AccessToken, result.IdToken);
}