簡體   English   中英

ASP.NET Web API 和 OpenID Connect:如何從授權碼獲取訪問令牌

[英]ASP.NET Web API and OpenID Connect: how to get Access Token from Authorization Code

我嘗試讓 OpenID Connect 運行...我的 Web API 的用戶設法獲得了 OpenID Connect 提供程序的授權代碼。 我應該如何將此代碼傳遞給我的 ASP.NET Web API? 我必須如何配置 OWIN 中間件才能使用授權碼獲取訪問令牌?

更新:SPA 使用 AJAX 與我的 Web 服務(ASP.NET Web API)進行通信。 在我的 Web 服務中使用 OWIN 中間件。 我將 OpenIDConnect 設置為身份驗證機制。 第一次調用 Web 服務時,它成功地將用戶重定向到 OpenID Connect 提供程序的登錄頁面。 結果,用戶可以登錄並獲得授權碼。 AFAIK 此代碼現在可以(由我的 Web 服務)用於訪問令牌。 但是,我不知道如何將此代碼返回到我的 Web 服務(這是使用標頭完成的嗎?)以及如何配置以獲取訪問令牌。 我想我可以手動調用令牌端點,但我想改用 OWIN 組件。

看起來推薦的方法是使用AuthorizationCodeReceived事件來交換訪問令牌的身份驗證代碼。 Vittorio 有一個博客條目概述了整個流程。

以下是GitHub 上此示例應用程序Startup.Auth.cs代碼示例,用於進行設置:

app.UseOpenIdConnectAuthentication(
    new OpenIdConnectAuthenticationOptions
    {
        ClientId = clientId,
        Authority = Authority,
        Notifications = new OpenIdConnectAuthenticationNotifications()
        {
            AuthorizationCodeReceived = (context) =>
           {
               var code = context.Code;
               ClientCredential credential = new ClientCredential(clientId, appKey);
               string tenantID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
               string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
               AuthenticationContext authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}", tenantID), new EFADALTokenCache(signedInUserID));
               AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
                           code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceID);

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

注意: AuthorizationCodeReceived事件僅在真正發生授權時調用一次。 如果已經生成並存儲了驗證碼,則不會調用此事件。 您必須注銷或清除 cookie 才能強制發生此事件。

BenV 已經回答了這個問題,但還有更多需要考慮的。

class partial Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        // ...

        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
          {
            ClientId = clientId,
            Authority = authority,
            Notifications = new OpenIdConnectAuthenticationNotifications() {
                AuthorizationCodeReceived = (context) => {
                   string authorizationCode = context.Code;
                   // (tricky) the authorizationCode is available here to use, but...
                   return Task.FromResult(0);
                }
            }
          }
    }
}

兩個問題:

  • 首先, authorizationCode會很快過期。 存儲它沒有意義。
  • 第二個問題是AuthorizationCodeReceived事件不會因任何頁面重新加載而被觸發,只要 AuthorizationCode 未過期並存儲在會話中。

您需要做的是調用AcquireTokenByAuthorizationCodeAsync ,它將緩存它並在TokenCache.DefaultShare正確處理:

AuthorizationCodeReceived = (context) => {
    string authorizationCode = context.Code;
    AuthenticationResult tokenResult = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, new Uri(redirectUri), credential);
    return Task.FromResult(0);
}

現在,在每次調用資源之前,調用AcquireTokenSilentAsync以獲取 accessToken(它將使用 TokenCache 或靜默使用 refreshToken )。 如果令牌過期,它將引發AdalSilentTokenAcquisitionException異常(調用訪問代碼更新程序)。

// currentUser for ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")
AuthenticationResult authResult = await context.AcquireTokenSilentAsync(resourceUri, credential, currentUser);

如果緩存了令牌,則調用AcquireTokenSilentAsync會非常快。

您需要繞過默認的 owin 驗證來進行自定義授權:

           new OpenIdConnectAuthenticationOptions
            {
                ...,
                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidateIssuer = false
                },
TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name", RoleClaimType = ClaimTypes.Role },

這行代碼解決了我的問題。 我們需要驗證發行人是假的。

這適用於我使用 Microsoft.AspNetCore.Authentication.OpenIdConnect 庫 5.0.6。

 var accessToken = await HttpContext.GetTokenAsync("access_token");
 var refreshToken = await HttpContext.GetTokenAsync("refresh_token");

有關混合流的 Identity Server 4 文檔中的更多信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM