1

之前通過Web應用程序和API有Azure的AD是 -獲取用戶信息,如果的WebAPI是基於客戶端憑證驗證

用戶輸入ID和密碼的應用形式 - >用戶獲取登錄(Asp.net身份) - >使用相同的憑證,在WebAPI上獲取生成的令牌(grant_type = password) - >將此令牌存儲爲稍後使用的cookie。

現在,隨着Azure的AD -

我遇到的情況,我有使用Azure的AD驗證用戶。 Azure中的webapi傳遞包含登錄用戶信息的JWT。從這些信息中,我提取用戶電子郵件並強制我的Web應用程序登錄用戶(Asp.net標識)。

Web應用程序調用WebAPI獲取令牌,因爲我無法傳遞密碼,因此我的令牌調用更改爲(grant_type = client_credentials)。但是,我忘記了登錄到Web API的個人用戶的信息。如果我檢查context.user,它指向唯一的客戶端ID而不是任何用戶。

我知道它很混亂,但要求是使用相同的應用程序進行Azure AD身份驗證以及前提表單身份驗證。請建議是否有更簡單的方法來實現這一點。

編輯:我使用Owin的OAuth

我使用兩種形式的驗證和Azure的AD相同的應用程序。然而,最近必須在web api級別添加記錄機制,該機制適用於使用用戶名/密碼進行記錄的內部應用程序。但是,如果webapi使用客戶端證書頒發令牌,則不起作用。我試圖通過用戶名作爲參數,同時驗證客戶端ID(在ValidateClientAuthentication中)並登錄用戶。然而webapi不能保留這個用戶信息。

+0

如果我知道您使用的是什麼協議和技術,這將有所幫助。 OpenIdConnect,OAuth? Katana/Asp.net核心1.0/etc? –

回答

0

這裏是我已經做了解決我的問題 - 而不是爲客戶端分配claimsIdentity我生成的用戶身份。 (_username是局部變量,它會從參數指定的值「ValidateClientAuthentication」我明白,這未必是理想的方法,但現在我的應用程序現在可以在窗體身份驗證以及使用JWT令牌Azure的AD)

public override async Task GrantClientCredentials(OAuthGrantClientCredentialsContext context) 
     { 
      var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>(); 

      ApplicationUser user = await userManager.FindByNameAsync(_userName); 

      ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, CookieAuthenticationDefaults.AuthenticationType); 

      var ticket = new AuthenticationTicket(oAuthIdentity, null); 

      context.Validated(ticket); 
     } 
0

客戶端憑證流用於守護程序應用程序或服務以委託應用程序來操作資源。在這種情況下,沒有用戶上下文信息。

基於我的理解,當我們使用Azure AD作爲身份提供者時,我們使用OpenId connect協議來獲取id_token形式的Azure AD。 OpenId連接也支持混合流程以獲取授權碼id_token在相同的請求。

如果您使用OWIN組件開發MVC,則默認情況下爲此流程。我們只需要通過Azure AD返回的授權碼(OAuth 2.0代碼授權流)獲取訪問令牌來調用Web API,這不需要用戶再次登錄。並獲得與授權碼的原因,我們可以添加通知像下面的代碼:

public void ConfigureAuth(IAppBuilder app) 
{ 
     app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); 

     app.UseCookieAuthentication(new CookieAuthenticationOptions()); 

     app.UseOpenIdConnectAuthentication(
      new OpenIdConnectAuthenticationOptions 
      { 
       ClientId = clientId, 
       Authority = Authority, 
       PostLogoutRedirectUri = redirectUri, 
       RedirectUri = redirectUri, 
       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 = OnAuthorizationCodeReceived, 
        AuthenticationFailed = OnAuthenticationFailed 
       } 

      }); 
} 

private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context) 
{ 
     var code = context.Code; 

     ClientCredential credential = new ClientCredential(clientId, appKey); 
     string userObjectID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; 
     AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectID)); 

     // If you create the redirectUri this way, it will contain a trailing slash. 
     // Make sure you've registered the same exact Uri in the Azure Portal (including the slash). 
     Uri uri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)); 

     AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, uri, credential, graphResourceId); 
} 

完整的代碼示例來調用Web應用程序的網絡API,你可以參考here