繁体   English   中英

IdentityServer3 + AzureAD和RedirectUri混淆

[英]IdentityServer3 + AzureAD and RedirectUri Confusion

我正在努力了解IdentityServer3,AzureAD和私有数据库如何一起工作。 最大的问题是如何处理重定向URI。

我的情况是我有一个独立的IdentityServer3。 它的工作是针对AzureAD或私有数据库对用户进行身份验证。 在ID3服务器上的Startup.cs文件中,我具有以下OpenID Connect代码:

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,它们指向应用程序,但是这些似乎无关紧要。

当然,当我使用事物的“ Cookie”端登录时,一切都可以正常运行-我看到了所有针对用户的声明。 并且,花了一些时间与Microsoft通话,他们提出了ID3之外的解决方案,该解决方案有效,但这不是我们需要的方法。 我们将有多个应用程序根据我们的ID3进行身份验证,因此我们需要在内部包含和控制流。

我真的需要一些帮助来尝试解决最后一公里的问题。 我知道我已经接近了,我一直在盯着这么久,以至于我可能正盯着我的错误而没有看到它。

2016年10月22日编辑
进一步的测试和启用Serilog揭示了RedirectUriPostLogoutRedirectUri的问题,导致我在URI的末尾添加了/identity ,这与app.Map中设置的值相对应。 这解决了我返回到IdentityServer3的“空白”页面的问题,现在我返回到IdentityServer3登录屏幕。 Azure AD仍然认为我已登录,只是在应用程序中没有正确设置令牌。

由于身份验证流程有点复杂,因此我尝试使用下图进行说明: 在此处输入图片说明

首先,重定向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 / ,该URL在IdentyServer3上注册,下面的代码是Web应用程序,使用OWIN OpenId Connect将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"
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM