代码之家  ›  专栏  ›  技术社区  ›  tloflin

被ASP上的Graph API认证弄糊涂了。Net MVC

  •  0
  • tloflin  · 技术社区  · 5 年前

    我似乎无法理解这一点。我对整个身份验证过程感到困惑。有很多术语——令牌、身份验证代码、身份、帐户、租户、声明主体、作用域、客户端应用程序、OWIN、OpenID、MSAL、ADAL、Azure、AD、Office365、Graph API等。而且它已经更改了几次,所以我看到的任何文档都可能不适用于当前版本!

    我将逐步解决我目前的问题,但我也在寻求一些一般性的帮助。对于站点身份验证,我的Startup类中有一些代码用于初始化站点的身份验证:

    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
    
    app.UseCookieAuthentication(new CookieAuthenticationOptions { CookieManager = new SystemWebCookieManager() });
    
    string authority = string.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
    
    app.UseOpenIdConnectAuthentication(
        new OpenIdConnectAuthenticationOptions
        {
            ClientId = clientID,
            Authority = authority,
    
            Notifications = new OpenIdConnectAuthenticationNotifications()
            {
                // when an auth code is received...
                AuthorizationCodeReceived = OnAuthorizationCodeReceivedAsync,
                AuthenticationFailed = (context) =>
                {
                    context.HandleResponse();
                    return Task.FromResult(0);
                }
            }
        });
    

    我认为这可以处理将用户发送出去登录的问题。然后(我认为?!)微软会发回一个身份验证代码,在这里处理:

    private async Task OnAuthorizationCodeReceivedAsync(AuthorizationCodeReceivedNotification notification)
    {
        var idClient = ConfidentialClientApplicationBuilder.Create(clientID)
            .WithAuthority(AzureCloudInstance.AzurePublic, tenant)
            .WithRedirectUri(notification.Request.Uri.AbsoluteUri)
            .WithClientSecret(clientSecret)
            .Build();
    
        var signedInUser = new ClaimsPrincipal(notification.AuthenticationTicket.Identity);
        var tokenStore = new MemoryTokenStore(idClient.UserTokenCache, HttpContext.Current, signedInUser);
    
        try
        {
            string[] scopes = graphScopes.Split(' ');
    
            var result = await idClient.AcquireTokenByAuthorizationCode(scopes, notification.Code).ExecuteAsync();
    
            var graphClient = new GraphServiceClient(
                new DelegateAuthenticationProvider(
                    async (requestMessage) => {
                        requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
                    }));
    
            // Grab and cache user details...
        }
        catch (Exception ex) 
        {
            // Handle exception...
        }
    }
    

    然后在我的控制器中,我用以下内容装饰安全操作 [Authorize] 我相信以上所有工作都正常。我真的不明白它在做什么,但我可以登录并查看安全操作。我遇到问题的地方是在操作中访问Graph API:

    public async Task<GraphServiceClient> GetAuthenticatedClient()
    {
        var idClient = ConfidentialClientApplicationBuilder.Create(clientID)
            .WithAuthority(AzureCloudInstance.AzurePublic, tenant)
            .WithRedirectUri(HttpContext.Request.Url.AbsoluteUri)
            .WithClientSecret(clientSecret)
            .WithLogging(writeToLog, LogLevel.Verbose, true)
            .Build();
    
        var tokenStore = new MemoryTokenStore(idClient.UserTokenCache, HttpContext, ClaimsPrincipal.Current);
    
        var accounts = await idClient.GetAccountsAsync();
    
        var scopes = graphScopes.Split(' ');
        var result = await idClient.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync();
    
        return new GraphServiceClient(
            new DelegateAuthenticationProvider(
                async (requestMessage) => {
                    requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
                }
            )
        );
    }
    

    我所做的基本上与站点内身份验证完全相同,但由于我没有身份验证代码,我尝试使用AcquireTokenSilent。但这需要一个身份,我在阅读的教程中说,我应该从ConfidentialClientApplication获得身份,如图所示。但大多数时候,调用GetAccountsAsync()时,我得到的帐户数为零。有一两次我拿到了账户,一切正常,但很断断续续。当我查看调试信息时,我得到这样的结果:

    Tried to use network cache provider for login.microsoftonline.com. Success? False
    
    Tried to use known metadata provider for login.microsoftonline.com. Success? True
    

    在一个实例中,它在我调试时成功检索到帐户,它说:

    Tried to use network cache provider for login.microsoftonline.com. Success? True
    
    0 回复  |  直到 4 年前
        1
  •  1
  •   Gary Archer    5 年前

    最重要的是,在使用基于OAuth的技术时,我建议:

    • 了解基于标准的解决方案
    • 能够查看OAuth消息

    我有一些笔记 Azure AD Troubleshooting 这可能会向您展示我使用的方法类型——它还具有一些Azure/Graph设置。

    如果你能达到可以发布HTTP消息的状态,而不是C#代码,你将得到最佳答案。