【问题标题】:Get access token in MVC application在 MVC 应用程序中获取访问令牌
【发布时间】:2016-07-15 05:15:55
【问题描述】:

我正在尝试检索访问令牌,以便可以存储它,并稍后将其传递给 ExchangeService。 Startup.Auth 看起来像这样:

 app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = clientId,
                Authority = authority,
                UseTokenLifetime = false,
                /*
                * Skipping the Home Realm Discovery Page in Azure AD
                * http://www.cloudidentity.com/blog/2014/11/17/skipping-the-home-realm-discovery-page-in-azure-ad/
                */
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    RedirectToIdentityProvider = OpenIdConnectNotification.RedirectToIdentityProvider,
                    MessageReceived = OpenIdConnectNotification.MessageReceived,
                    SecurityTokenReceived = OpenIdConnectNotification.SecurityTokenReceived,
                    SecurityTokenValidated = OpenIdConnectNotification.SecurityTokenValidated,
                    AuthorizationCodeReceived = OpenIdConnectNotification.AuthorizationCodeReceived,
                    AuthenticationFailed = OpenIdConnectNotification.AuthenticationFailed
                },

            });

然后在 SecurityTokenValidated 中我这样做了:

public static async Task<Task>  SecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
    {
        string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
        string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
        var authContext = new AuthenticationContext(aadInstance + "/oauth2/token", false);
        var authResult =await authContext.AcquireTokenByAuthorizationCodeAsync(context.ProtocolMessage.Code,
            new Uri(aadInstance), new ClientAssertion(clientId, "‎5a95f1c6be7bf3c61f6392ec84ddd044acef61d9"));
        var accessToken = authResult.Result.AccessToken;
        context.AuthenticationTicket.Identity.AddClaim(new Claim("access_token", accessToken));
        return Task.FromResult(0);
    }

我没有收到任何错误,但应用程序在此行挂起:

 var accessToken = authResult.Result.AccessToken;

ClientAssertion 是使用我在 IIS 中安装的 SSL 证书的指纹构造的,不确定证书是否是错误的类型...

更新: 我更新了 SecurityTokenValidated 以反映 Saca 的评论,但我收到“AADSTS50027:无效的 JWT 令牌。令牌格式无效”错误。 我也试过这段代码:

   string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
            string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
            var authContext = new AuthenticationContext(aadInstance, false);
            var cert = new X509Certificate2("...", "...");
            var cacert = new ClientAssertionCertificate(clientId, cert);
            var authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(context.ProtocolMessage.Code, new Uri(aadInstance), cacert);
            var accessToken = authResult.AccessToken;
            context.AuthenticationTicket.Identity.AddClaim(new Claim("access_token", accessToken));
            return Task.FromResult(0);

但是这样我得到“AADSTS70002:验证凭据时出错。AADSTS50012:客户端断言包含无效签名。”

【问题讨论】:

    标签: asp.net-mvc oauth-2.0 owin azure-active-directory


    【解决方案1】:

    应用程序挂起,因为您通过访问 authResult 的 .Result 阻塞了异步任务的结果。

    您应该将其更改为:

    public static async Task SecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
    {
        string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
        string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
        var authContext = new AuthenticationContext(aadInstance + "/oauth2/token", false);
        var authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(context.ProtocolMessage.Code,
            new Uri(aadInstance), new ClientAssertion(clientId, "‎5a95f1c6be7bf3c61f6392ec84ddd044acef61d9"));
        var accessToken = authResult.AccessToken;
        context.AuthenticationTicket.Identity.AddClaim(new Claim("access_token", accessToken));
    }
    

    【讨论】:

    • 这修复了悬挂部分,但我仍然没有 access_token。应用程序加载,然后当我尝试访问令牌时,声明不存在......
    • 嗯...我认为 chrome 缓存了一些东西,因为我尝试在 IE 中进行测试,但我收到了一个错误的请求,这解释了丢失的令牌。现在的问题是如何找出我的请求有什么问题? :(
    【解决方案2】:

    我设法获得了访问令牌:

     public static async Task<Task> SecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
        {
            string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
            string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
            string clientSecret = ConfigurationManager.AppSettings["ida:ClientSecret"];
            string source = ConfigurationManager.AppSettings["ExchangeOnlineId"];
    
            var authContext = new AuthenticationContext(aadInstance, false);
            var credentials = new ClientCredential(clientId, clientSecret);
            var appRedirectUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + "/";
            var authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(context.ProtocolMessage.Code, new Uri(appRedirectUrl), credentials, source);
            var accessToken = authResult.AccessToken;
            var applicationUserIdentity = new ClaimsIdentity(context.OwinContext.Authentication.User.Identity);
            applicationUserIdentity.AddClaim(new Claim("AccessToken", accessToken));
            context.OwinContext.Authentication.User.AddIdentity(applicationUserIdentity);
            return Task.FromResult(0);
        }
    

    最初我想使用 ClientAssertion,这样我就不必公开客户端 Secret,但管理证书的工作量太大...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-18
      • 1970-01-01
      • 2013-08-05
      • 2011-05-26
      • 2018-08-04
      • 2011-05-12
      • 1970-01-01
      相关资源
      最近更新 更多