使用 IdentityServer4 登录 Umbraco 8 后台

Ran*_*ndy 1 c# identityserver4 umbraco8

背景

我对 Umbraco 很陌生,但一直在尝试使用IdentityServer4作为 Umbraco 的后台。对于 IDP,我使用了此处的内存配置(is4inmem 模板)。

对于 Umbraco,我使用UmbracoIdentityExtensions来配置 OpenId Connect。

我主要关注的是教程(不过这是针对 Umbraco 7 的)。

问题

我确实有配置的“使用 OpenId 连接登录”按钮,但是当我尝试使用 IDP 登录时,Umbraco 不会让我登录。我总是返回到登录页面。然而,每当我访问 IDP 页面时,我都会登录并可以看到我已授予访问权限,如下图所示。 在此输入图像描述

每当我使用 Umbraco 帐户登录,然后尝试“链接您的 OpenId Connect 帐户”时,它什么也不做,但注销后屏幕上会出现一条错误消息:“发生错误,无法获取外部登录信息”尝试过使用不同的配置设置,但没有成功。

代码

IDP 配置.cs

public static IEnumerable<IdentityResource> Ids =>
            new IdentityResource[]
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
                new IdentityResources.Email(),
                new IdentityResource(
                    name: "application.profile",
                    displayName: "Application profile",
                    claimTypes: new[] { ClaimTypes.GivenName, ClaimTypes.Surname }
                )
            };

... etc ...

 public static IEnumerable<Client> Clients =>
            new Client[]
            {
                new Client
                {
                    ClientId = "u-client-bo",
                    ClientSecrets = new List<Secret>
                    {
                        new Secret("secret".Sha256()),
                    },
                    ClientName = "Umbraco Client",
                    AllowedGrantTypes = GrantTypes.Hybrid,
                    RequireConsent = false,
                    RedirectUris           = { "https://localhost:44302/Umbraco" },
                    PostLogoutRedirectUris = { "https://localhost:44302/Umbraco" },
                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.Email,
                        "application.profile",
                    },
                    AllowAccessTokensViaBrowser = true,
                    AlwaysIncludeUserClaimsInIdToken = false
                }
            };
Run Code Online (Sandbox Code Playgroud)

对于 Umbraco,我已将UmbracoCustomOwinStartup编辑为以下内容:

public class UmbracoCustomOwinStartup : UmbracoDefaultOwinStartup
{
    protected override void ConfigureUmbracoUserManager(IAppBuilder app)
    {
        app.ConfigureUserManagerForUmbracoBackOffice(
            Services,
            Mapper,
            UmbracoSettings.Content,
            GlobalSettings,

            global::Umbraco.Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider().AsUmbracoMembershipProvider());
    }

    protected override void ConfigureUmbracoAuthentication(IAppBuilder app)
    {
        app
            .UseUmbracoBackOfficeCookieAuthentication(UmbracoContextAccessor, RuntimeState, Services.UserService, GlobalSettings, UmbracoSettings.Security, PipelineStage.Authenticate)
            .UseUmbracoBackOfficeExternalCookieAuthentication(UmbracoContextAccessor, RuntimeState, GlobalSettings, PipelineStage.Authenticate)
            .UseUmbracoPreviewAuthentication(UmbracoContextAccessor, RuntimeState, GlobalSettings, UmbracoSettings.Security, PipelineStage.Authorize);

        var identityOptions = new OpenIdConnectAuthenticationOptions
        {
            ClientId = "u-client-bo",
            SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie,
            Authority = "https://localhost:44393",
            RedirectUri = "https://localhost:44302/Umbraco",
            ResponseType = "code id_token token",
            Scope = "openid profile application.profile",
            PostLogoutRedirectUri = "https://localhost:44302/Umbraco",

            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                SecurityTokenValidated = ClaimsTransformer.GenerateUserIdentityAsync
            }
        };

        // Configure BackOffice Account Link button and style
        identityOptions.ForUmbracoBackOffice("btn-microsoft", "fa-windows");
        identityOptions.Caption = "OpenId Connect";

        // Configure AutoLinking
        identityOptions.SetExternalSignInAutoLinkOptions(
            new ExternalSignInAutoLinkOptions(autoLinkExternalAccount: true));

        app.UseOpenIdConnectAuthentication(identityOptions);
    }
}
Run Code Online (Sandbox Code Playgroud)

ClaimsTransformer.GenerateUserIdentityAsync方法向 Identity 添加其他声明。

我是否缺少其他配置或组件?

提前致谢!

Ran*_*ndy 5

我终于想通了。有几个问题:

1.更正auth cookie

我现在使用的不是DefaultAuthenticationTypes.ExternalCookieas ,而是.SignInAsAuthenticationTypeUmbraco.Core.Constants.Security.BackOfficeExternalAuthenticationType

2. 设置身份验证类型

设置AuthenticationTypeOpenIdConnectAuthenticationOptions. 它必须与 的名称匹配Authority才能使自动链接发挥作用。

重要提示:显式后再次设置它,identityOptions.ForUmbracoBackOffice("btn-microsoft", "fa-windows");因为它'Umbraco.'在方法调用后添加了前缀。

3. 包含电子邮件声明

我已经添加了电子邮件声明,这也是自动链接正常工作所必需的。

Scope = "openid email profile application.profile",

4. 确保您有任何形式的姓名权主张

我已在 IDP 中设置AlwaysIncludeUserClaimsInIdToken为,因此 id 声明会自动在 Umbraco 中获取。trueClaimsTransformer现在的样子是这样的:

public class ClaimsTransformer
{
    public static async Task GenerateUserIdentityAsync(
        SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
    {
        // Now this contains ID claims (e.g. GivenName in my case)
        var id = notification.AuthenticationTicket.Identity;

        var identityUser = new ClaimsIdentity(
            id.Claims, // copy the claims I have
            notification.AuthenticationTicket.Identity.AuthenticationType,
            // set the nameType, so Umbraco can use the 'ExternalLogin.Name' for auto-link to work
            ClaimTypes.GivenName, // <-- You have to set a correct nameType claim
            ClaimTypes.Role);

         notification.AuthenticationTicket = new AuthenticationTicket(identityUser,
                notification.AuthenticationTicket.Properties);
    }
}
Run Code Online (Sandbox Code Playgroud)

5.删除其他Umbraco Auth中间件

app.UseUmbracoBackOfficeXXX在我的例子中不需要这些语句,事实上,它们破坏了功能。我UmbracoCustomOwinStartup现在的样子是这样的:

public class UmbracoCustomOwinStartup : UmbracoDefaultOwinStartup
{
    protected override void ConfigureUmbracoAuthentication(IAppBuilder app)
    {
        base.ConfigureUmbracoAuthentication(app);

        var identityOptions = new OpenIdConnectAuthenticationOptions
        {
            ClientId = "u-client-bo",
            SignInAsAuthenticationType = Umbraco.Core.Constants.Security.BackOfficeExternalAuthenticationType,
            AuthenticationType = "https://localhost:44393",
            Authority = "https://localhost:44393",
            RedirectUri = "https://localhost:44302/Umbraco",
            ResponseType = "code id_token token",
            Scope = "openid email profile application.profile",
            PostLogoutRedirectUri = "https://localhost:44302/Umbraco",

            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                SecurityTokenValidated = ClaimsTransformer.GenerateUserIdentityAsync
            }
        };

        // Configure BackOffice Account Link button and style
        identityOptions.ForUmbracoBackOffice("btn-microsoft", "fa-windows");
        identityOptions.Caption = "OpenId Connect";

        identityOptions.AuthenticationType = "https://localhost:44393";

        // Configure AutoLinking
        identityOptions.SetExternalSignInAutoLinkOptions(
            new ExternalSignInAutoLinkOptions(autoLinkExternalAccount: true));

        app.UseOpenIdConnectAuthentication(identityOptions);
    }

}
Run Code Online (Sandbox Code Playgroud)

提示:不要忘记在您的web.config.

我希望你们中的一些人觉得这很有帮助,我找不到很多关于 Umbraco 8 与 IdentityServer4 结合使用的文档。