0

我很努力地瞭解IdentityServer3,AzureAD和私有數據庫如何一起工作。最大的問題是如何處理重定向URI。IdentityServer3 + AzureAD和RedirectUri混淆

我的場景是我有一個獨立的IdentityServer3。它的工作是根據AzureAD或私人數據庫對用戶進行身份驗證。內的ID3服務器上的文件Startup.cs,我有以下ID連接代碼:

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     app.Map("/identity", s3App => 
     { 
      s3App.UseIdentityServer(new IdentityServerOptions 
      { 
       SiteName = "3S", 
       SigningCertificate = Certificate.Load(), 

       Factory = new IdentityServerServiceFactory() 
           .UseInMemoryUsers(InMemoryUsers.Get()) 
           .UseInMemoryClients(InMemoryClients.Get()) 
           .UseInMemoryScopes(InMemoryScopes.Get()), 

       AuthenticationOptions = new AuthenticationOptions 
       { 
        EnablePostSignOutAutoRedirect = true, 
        EnableSignOutPrompt = false, 
        IdentityProviders = ConfigureAdditionalIdentityProviders 
       } 
      }); 
     }); 
    } 

    public static void ConfigureAdditionalIdentityProviders(IAppBuilder app, string signInAsType) 
    { 
     app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
     { 
      AuthenticationType = "AzureAd", 
      Caption = "Login", 
      ClientId = "4613ed32-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // GUID of registered application on Azure 
      Authority = "https://login.microsoftonline.com/our-tenant-id/", 

      PostLogoutRedirectUri = "https://localhost:44348/identity", 
      RedirectUri = "https://localhost:44348/identity", 

      Scope = "openid email profile", 
      ResponseType = "id_token", 
      AuthenticationMode = AuthenticationMode.Passive, 
      SignInAsAuthenticationType = signInAsType, 
      TokenValidationParameters = new TokenValidationParameters 
      { 
       AuthenticationType = Constants.ExternalAuthenticationType, 
       ValidateIssuer = false 
      } 
     }); 
    } 

我不明白爲什麼ID3服務器將需要要麼RedirectUri或PostLogoutRedirectUri ......難道不應該從請求認證的應用程序「通過」?畢竟,我們想要回到應用程序,而不是ID3服務器。當然,我不認爲這是什麼原因導致我的問題,但很好理解爲什麼這些在這裏。

我會說,我已經「接近」這個工作。

當我的應用程序需要身份驗證請求對AzureAD的身份驗證時,我被重定向到Microsoft帳戶登錄屏幕以輸入我的工作帳戶的用戶名/密碼。我提交我的憑據,然後重定向到ID3服務器或我的應用程序,具體取決於上面的代碼中使用了哪個RedirectUri。

爲了論證,我們假設我使用我的應用程序的RedirectUri。我將被髮送回應用程序,但不會發送到最初提示身份驗證質詢的頁面,如果我點擊需要身份驗證的頁面,我會將其發送回AzureAD服務器以再次登錄,只有這次AzureAD將我識別爲已登錄。

不幸的是,似乎沒有在AzureAD重定向之後確認/設置SecurityTokenValidated通知。

下面是在應用程序Startup.cs找到的代碼:

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     app.UseCookieAuthentication(new CookieAuthenticationOptions 
     { 
      AuthenticationType = "Cookies" 
     }); 

     app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
     { 
      Authority = "https://localhost:44348/identity", 
      ClientId = "3af8e3ba-5a04-4acc-8c51-1d30f8587ced", // Local ClientID registered as part of the IdentityServer3 InMemoryClients 
      Scope = "openid profile roles", 
      RedirectUri = "http://localhost:52702/", 
      PostLogoutRedirectUri = "http://localhost:52702/", 
      ResponseType = "id_token", 

      SignInAsAuthenticationType = "Cookies", 
      UseTokenLifetime = false, 

      Notifications = new OpenIdConnectAuthenticationNotifications 
      { 
       SecurityTokenValidated = n => 
       { 
        var id = n.AuthenticationTicket.Identity; 
        var givenName = id.FindFirst(Constants.ClaimTypes.GivenName); 
        var familyName = id.FindFirst(Constants.ClaimTypes.FamilyName); 
        var sub = id.FindFirst(Constants.ClaimTypes.Subject); 
        var roles = id.FindAll(Constants.ClaimTypes.Role); 

        var nid = new ClaimsIdentity(
         id.AuthenticationType, 
         Constants.ClaimTypes.GivenName, 
         Constants.ClaimTypes.Role 
         ); 

        nid.AddClaim(givenName); 
        nid.AddClaim(familyName); 
        nid.AddClaim(sub); 
        nid.AddClaims(roles); 

        nid.AddClaim(new Claim("application_specific", "Some data goes here. Not sure what, though.")); 
        nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken)); 

        n.AuthenticationTicket = new AuthenticationTicket(nid, n.AuthenticationTicket.Properties); 

        return Task.FromResult(0); 
       }, 

       RedirectToIdentityProvider = n => 
       { 
        if (n.ProtocolMessage.RequestType != OpenIdConnectRequestType.LogoutRequest) 
         return Task.FromResult(0); 

        var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token"); 

        if (idTokenHint != null) 
        { 
         n.ProtocolMessage.IdTokenHint = idTokenHint.Value; 
        } 
        return Task.FromResult(0); 
       }, 

       AuthenticationFailed = (context) => 
       { 
        context.HandleResponse(); 
        context.Response.Redirect("/Error/message=" + context.Exception.Message); 
        //Debug.WriteLine("*** AuthenticationFailed"); 
        return Task.FromResult(0); 
       }, 

      } 
     }); 

     AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject; 
     JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>(); 
    } 
} 

你會發現OpenIdConnectAuthenticationOptions還含有RedirectUri和PostLogoutRedirectUri其指向應用程序,但這些似乎並不重要。

當然,當我使用cookies的一面登錄時,一切都很完美 - 我看到了我對用戶的所有要求。而且,在微軟的電話上花費了一些時間,他們提出了ID3之外的解決方案,但這不是我們需要的方式。我們將有多個應用程序對我們的ID3進行身份驗證,因此我們需要在內部包含和控制流程。

我真的需要一些幫助,試圖找出這最後一英里問題。我知道我很接近,我只是一直盯着這麼長時間,我可能正盯着我的錯誤,而沒有看到它。

2016年10月22日編輯
進一步的測試和實現Serilog發現的問題與RedirectUriPostLogoutRedirectUri導致我加入/identity,其對應於app.Map設定值中的URI的結尾。這解決了我返回到IdentityServer3的「空白」頁面的問題,現在我返回到IdentityServer3登錄屏幕。 Azure AD仍然認爲我已登錄,但我沒有在應用程序中正確設置令牌。

回答

2

由於身份驗證流程有點複雜,我想用下面的圖說明了它: enter image description here

首先重定向URL需要註冊的身份提供者,因此服務器將匹配在請求中的redirectUrl以確保響應按預期重定向,而不是重定向到像釣魚網站(安全考慮)。

而且如圖所示,要將Azure AD用作IdentityServer3的外部身份提供程序,我們需要在Azure AD上註冊這些應用程序。但是,由於應用程序用於與Identity Server進行通信,因此Azure門戶上的重定向URL註冊應重定向到IdentityServer3而不是應用程序的URL。

例如,我的身份服務器3的URL是https://localhost:44333,那麼我使用下面的代碼來添加其他身份提供者。而這個URL是在Azure門戶網站重定向URL:

public static void ConfigureAdditionalIdentityProviders(IAppBuilder app, string signInAsType) 
{ 
     app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
     { 
      AuthenticationType = "aad", 
      Caption = "Azure AD", 
      SignInAsAuthenticationType = signInAsType, 

      Authority = "https://login.microsoftonline.com/04e14a2c-0e9b-42f8-8b22-3c4a2f1d8800", 
      ClientId = "eca61fd9-f491-4f03-a622-90837bbc1711", 
      RedirectUri = "https://localhost:44333/core/aadcb", 
     }); 
} 

和我的應用程序的URL是http://localhost:1409/這是對IdentyServer3和下面的代碼註冊爲Web應用程序使用OWIN ID連接到IdentyServer3添加爲身份數據提供者:

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
{ 
     AuthenticationType = "oidc", 
     SignInAsAuthenticationType = "cookies", 
     Authority = "https://localhost:44333", 
     ClientId = "mvc", 
     RedirectUri = "http://localhost:1409/", 
     ResponseType = "id_token", 
     Scope = "openid profile email" 
}); 
+0

我用你的插圖和代碼片斷來更改/驗證我正在使用的代碼。不幸的是,同樣的問題正在發生......一旦我對Azure AD進行身份驗證,我將被重定向到IdentityServer3,而不是根據需要應用到我的應用程序。我還驗證了IdentityServer3中的客戶端具有正確的RedirectUris和PostLogoutRedirectUris。我只是從不回到我的應用程序。 – rcastagna

+0

由於上面的測試對我很好,我建議您通過** Fiddler **跟蹤HTTP請求/重定向/響應,以查看請求重定向到Identity Server3時是否存在錯誤消息。 –