登录 Azure Web 应用程序失败并显示“AADSTS50079:用户需要使用多重身份验证”

Posted

技术标签:

【中文标题】登录 Azure Web 应用程序失败并显示“AADSTS50079:用户需要使用多重身份验证”【英文标题】:Login to Azure Web Application fails with 'AADSTS50079: The user is required to use multi-factor authentication' 【发布时间】:2018-01-29 16:35:35 【问题描述】:

我们有一个 Azure Web 应用程序,它通过 Azure 多重身份验证进行身份验证,并访问 Graph API 和 Power BI。我们已经设置了 Azure 应用注册所需的权限。我们使用 Redis 缓存将 Token 详细信息存储在 NaiveSessionCache 中。对于少数用户,当用户尝试登录时,我们会收到以下错误。

AADSTS50079:用户需要使用多重身份验证

"AADSTS50079:用户需要使用多重身份验证。\r\n跟踪 ID:63c180a9-6951-4a8a-96ca-e1ff38fc4400\r\n相关 ID:3f12d4b1-d401-4d99-be30-36bf972d74a5\r\ nTimestamp: 2017-08-21 14:21:59Z","parsedStack":["assembly":"Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.13.9.1126, Culture=neutral, PublicKeyToken=31bf3856ad364e35","method ":"Microsoft.IdentityModel.Clients.ActiveDirectory.AdalHttpClient+d__211.MoveNext","level":0,"line":0,"assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","method":"System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess","level":1,"line":0,"assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","method":"System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification","level":2,"line":0,"assembly":"Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.13.9.1126, Culture=neutral, PublicKeyToken=31bf3856ad364e35","method":"Microsoft.IdentityModel.Clients.ActiveDirectory.AdalHttpClient+<GetResponseAsync>d__201.MoveNext","level":3,"line":0,"assembly":"mscorlib, Version=4.0.0.0, Culture =中性,PublicKeyToken=b77a5c561934e089","method":"System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess","level":4,"line":0,"assembly":"mscorlib, Version=4.0.0.0 , Culture=neutral, PublicKeyToken=b77a5c561934e089","method":"System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification","level":5,"line":0,"assembly":"Microsoft.IdentityModel.Clients .ActiveDirectory,版本=3.13.9.1126,文化=中性,PublicKeyToken=31bf3856ad3 64e35","method":"Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase+d__67.MoveNext","level":6,"line":0,"assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","method":"System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess","level":7,"line":0,"assembly":"mscorlib, Version=4.0. 0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089","method":"System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification","level":8,"line":0,"assembly":"Microsoft.IdentityModel. Clients.ActiveDirectory,版本=3.13.9.1126,Culture=neutral,PublicKeyToken=31bf3856ad364e35","method":"Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase+d__64.MoveNext","level":9,"line":0 ,"assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","method":"System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess","level":10,"line" :0,“程序集”:“mscorlib,版本=4.0.0.0,文化=ne utral, PublicKeyToken=b77a5c561934e089","method":"System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification","level":11,"line":0,"assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","method":"System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd","level":12,"line":0,"assembly":"Microsoft.IdentityModel.Clients. ActiveDirectory,版本=3.13.9.1126,文化=中性,PublicKeyToken=31bf3856ad364e35","method":"Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase+d__55.MoveNext","level":13,"line":0, “程序集”:“mscorlib,版本=4.0.0.0,文化=中性,PublicKeyToken=b77a5c561934e089”,“方法”:“System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess”,“级别”:14,“行”:0 ,"assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","method":"System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification","level":15,"line" :0,"程序集":"微软。 IdentityModel.Clients.ActiveDirectory,版本=3.13.9.1126,文化=中性,PublicKeyToken=31bf3856ad364e35","method":"Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext+d__48.MoveNext","level":16,"line" :0,"程序集":"mscorlib, 版本=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","method":"System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess","level":17," line":0,"assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","method":"System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification","level":18 “行”:0,“程序集”:“Microsoft.IdentityModel.Clients.ActiveDirectory,版本=3.13.9.1126,文化=中性,PublicKeyToken=31bf3856ad364e35”,“方法”:“Microsoft.IdentityModel.Clients.ActiveDirectory。 AuthenticationContext+d__30.MoveNext","level":19,"line":0,"assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","method":"System. Runtime.CompilerServices。 TaskAwaiter.ThrowForNonSuccess","level":20,"line":0,"assembly":"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","method":"System.Runtime. CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification","level":21,"line":0,"assembly":"Assembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","method":"Startup+c+d.MoveNext","level":22,"line":68,"fileName":"App_Start\Startup.Auth.cs"],"type":"Microsoft.IdentityModel.Clients.ActiveDirectory .AdalServiceException","id":"52129856"

这里是用于接收授权码的 startup.cs 文件。

public void ConfigureAuth(IAppBuilder 应用程序) 尝试

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions());

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                
                    ClientId = clientId,
                    Authority = Authority,
                    PostLogoutRedirectUri = postLogoutRedirectUri,
                    AuthenticationMode = AuthenticationMode.Active,
                    Notifications = new OpenIdConnectAuthenticationNotifications()
                    
                        // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                        AuthorizationCodeReceived = async (context) =>
                        
                            try 
                                IConnectionString _connectionString = new RedisConnectionString(ConfigurationReader.RedisCacheConfig as string);

                                ICacheManager cacheManager = new RedisCacheManager(_connectionString);
                                var code = context.Code;
                                ClientCredential credential = new ClientCredential(clientId, appKey);
                                string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(Constants.OBJECT_IDENTIFIER).Value;

                                AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(signedInUserID));
                                //Getting Power BI token
                                AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(
                                    code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, pbiResourceID);

                                //Getting Graph token
                                AuthenticationResult graphResult = await authContext.AcquireTokenByAuthorizationCodeAsync(
                                    code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);
                                UserTokenCache cache = new UserTokenCache
                                
                                    GraphAccessToken = graphResult.AccessToken,
                                    PBIAccessToken = result.AccessToken,
                                    PBITokenExpires = result.ExpiresOn,
                                    GraphTokenExpires = graphResult.ExpiresOn
                                ;

                                string encryptedCache = CryptographyUtility.Encrypt(JsonConvert.SerializeObject(cache));

                                cacheManager.set(signedInUserID, encryptedCache);
                             catch (Exception ex)
                            
                                ExceptionLogger.LogInApplicationInsight(ex);
                            
                        ,
                        AuthenticationFailed = async (context) =>
                        
                            ExceptionLogger.LogInApplicationInsight(context.Exception);
                            await Task.FromResult(0);
                        

                    
                );
        
        catch (SystemException sx)
        
            ExceptionLogger.LogInApplicationInsight(sx);
        
        catch (ApplicationException ax)
        
            ExceptionLogger.LogInApplicationInsight(ax);
        
        catch (Exception ex)
        
            ExceptionLogger.LogInApplicationInsight(ex);
        
    

我在这里遗漏了什么吗?由于此原因,很少有用户无法获取令牌,并且嵌入式 Power BI 报告未加载

【问题讨论】:

【参考方案1】:

此错误表明用户需要注册或执行多重身份验证。

500079: 注册 MFA

500076: 用户必须执行 MFA

要解决这两个问题,它是相同的协议。您的应用需要执行指定失败资源的交互式请求。

假设您尝试为需要 MFA 的 Microsoft Graph 获取令牌。您可能已经为另一个资源授予了刷新令牌(或已登录但未请求资源),然后您向 Azure AD 请求 Microsoft Graph 的新令牌。此请求位于 /token 端点上,该端点是 POST 并且无法执行 MFA。然后,您的应用程序应捕获此错误,并执行一个新请求(使用 AcquireToken 或 OWIN OpenId Connect Challenge)请求resource=https://graph.microsoft.com 或任何失败的资源。

【讨论】:

在上面的代码 sn-p 中,我试图依次获取 Power BI 和 Graph Token 的 Token。如您所说,Power BI 令牌已成功生成,但获取 Graph 令牌导致异常。此外,要使用 AcquireToken 获取 Graph Token,我们需要 UserAssertion。我们应该使用什么令牌来创建 UserAssertion? Here's 更多关于正在发生的事情的概念性信息。有关实际编码的帮助,您将处理类似的案例this example middleware handles (built for Azure AD v2.0 endpoint, so you'll use a resource rather than a scope for v1.0... ...最有帮助的部分是GenerateAuthorizationUrl,中间件在其中构造失败的新请求(在这种情况下动态同意失败)。 我找到了一种使用以下方法获取授权 URL 的方法 graphAuthUri = await authContext.GetAuthorizationRequestUrlAsync(graphResourceId, clientId, new Uri(RedirectUri), UserIdentifier.AnyUser, null);我正在通过 javascript 重定向到上述 URL。唯一的问题是,发布 MFA,StartUp.Auth.cs 中的 AuthorizationCodeReceived 通知函数未执行,但代码作为查询参数发送到 rediectUri。有没有可能去 AuthorizationCodeReceived 的方法?

以上是关于登录 Azure Web 应用程序失败并显示“AADSTS50079:用户需要使用多重身份验证”的主要内容,如果未能解决你的问题,请参考以下文章

Azure 应用服务部署失败并出现错误:“凭据”不能为空

Azure部署失败

Azure Pipelines“Cache@2”失败并显示“##[错误]系统找不到指定的文件”

Azure Web 应用服务在几个小时内变得不可用

Azure 数据工厂复制活动失败。用户登录失败

生成 ASP 应用程序并将其部署到 Azure Web 应用程序失败