【问题标题】:Identity4Server many SPA clients best approach?Identity4Server 许多 SPA 客户端的最佳方法?
【发布时间】:2019-08-30 14:04:32
【问题描述】:

您好,我继承了这样的系统:

一个 Api 和许多 Fronts (spa) 它们共享一个通用菜单,其中包含用于导航到彼此的链接,但它们是不同的反应应用程序,具有不同的 url。用于验证 Api 的 Azure Active Directory 受 Bearer 令牌的保护。

类似这样的:

现在我有授权要求,业务人员希望分配给每个用户的自定义权限,用于他们可以执行或不执行的操作以及可见性。

我想将 Identity4Server 与活动目录一起用作开放 ID 提供程序。然后使用提供者 api 来获取自定义权限并将这些权限放入声明中。然后在需要指定角色和声明以完成权限规范的 Api impl 策略中。

类似这样的:

Identity4Server 配置:

services.AddAuthentication()
                .AddOpenIdConnect("oidc", "OpenID Connect", options =>
                {
                    options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                    options.SignOutScheme = IdentityServerConstants.SignoutScheme;
                    options.SaveTokens = true;
                    options.RequireHttpsMetadata = false;

                    options.Authority = "https://login.microsoftonline.com/tenant/";
                    options.ClientId = "ClientId";
                    options.ClientSecret = "ClientSecret";

                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        NameClaimType = "name",
                        RoleClaimType = "role"
                    };
                });

API:

services
                .AddAuthentication(configure =>
                {
                    configure.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    configure.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                .AddJwtBearer(options =>
                {
                    options.Audience = "api";
                    options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;
                });

var clientsPolicy = new AuthorizationPolicyBuilder()
                .AddAuthenticationSchemes("Bearer")
                .AddRequirements(new ClaimsAuthorizationRequirement("ClientsModule", new[] { "1" }))
                .RequireRole("Admin")
                .Build();

            services.AddAuthorization(options =>
            {
                options.AddPolicy("Clients", clientsPolicy);
            });

对于反应应用程序,我使用这个 npm "oidc-client": "1.7.0" 和https://medium.com/@franciscopa91/how-to-implement-oidc-authentication-with-react-context-api-and-react-router-205e13f2d49 的类似方法 客户端配置是:(提供者非常相似,唯一改变的是 url localhost:3001)

export const IDENTITY_CONFIG = {
    authority: "http://localhost:5000",
    clientId: "fronts",
    redirect_uri: "http://localhost:3000/signin-oidc",
    login: "http://localhost:5000/login",
    automaticSilentRenew: false,
    loadUserInfo: false,
    silent_redirect_uri: "http://localhost:3000/silentrenew",
    post_logout_redirect_uri: "http://localhost:3000/signout-callback-oidc",
    audience: "fronts",
    responseType: "id_token token",
    grantType: "password",
    scope: "openid api",
    webAuthResponseType: "id_token token"
};

如果用户登录到客户端 (localhost:3000) 前面然后导航到提供程序 (localhost:3001) 前面它不应该再次登录。为了做到这一点,我用相同的客户端 ID 配置了所有前端,但我不知道这是否是正确的方法。现在我在身份服务器中的配置类是:

public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            {
                new Client
                {
                    ClientId = "fronts",
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    ClientName = "All fronts",
                    AllowedGrantTypes = GrantTypes.Implicit,
                    AllowAccessTokensViaBrowser = true,

                    RedirectUris = { "http://localhost:3000/signin-oidc", "http://localhost:3001/signin-oidc" },
                    PostLogoutRedirectUris = { "http://localhost:3000/signout-callback-oidc", "http://localhost:3001/signout-callback-oidc" },
                    AllowedCorsOrigins = { "http://localhost:3000", "http://localhost:3001" },

                    AllowedScopes = new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "api"
                    }
                }
            };
        }

您认为这种配置是正确的方法还是有更好的方法?

【问题讨论】:

    标签: c# reactjs asp.net-core single-page-application identityserver4


    【解决方案1】:

    你提到

    许多不同的反应应用程序,具有不同的网址

    但在您的代码 sn-p 中,我只看到 Clients(localhost:3000)

    无论如何,协议规范告诉我们要注册尽可能多的客户端。 SSO 是身份提供者的主要职责。

    您只需在 IdSrv 中将 RequireConsent = false; 添加到您的客户端 def 即可避免额外的意外用户交互。

    此外,现在推荐的 spa-s 身份验证流程是“code+pkce”。您可以查看this article 以获取过渡的详细信息。

    【讨论】:

    • 嗨 d_f 感谢您的回复。我会看一下这篇文章。您还可以看到具有不同 url 的 Providers(localhost:3001)。我将使用 spa 身份配置更新问题。另外问题是没有注册很多客户,我可以在每个 spa 站点注册 1 个客户,问题是如果我登录一个站点并导航到另一个站点,我不必再次登录。
    • 当然!正如我所提到的,这是 IdP 的主要工作,它为用户创建会话并为每个下一个应用程序静默登录,代表同一个用户。
    • 您需要在 IdSrv 中将 RequireConsent = false; 添加到您的客户端 def 以避免额外的意外用户交互。将其添加到答案中。
    • 还有一件小事:ClientSecret 不是隐式或代码+PKCE 授权类型所必需的。 ClientSecret 必须秘密保存,而基于浏览器的应用程序代码在设计上是公开的。
    猜你喜欢
    • 1970-01-01
    • 2020-07-18
    • 2010-11-02
    • 2011-03-08
    • 2011-04-05
    • 1970-01-01
    • 1970-01-01
    • 2020-09-13
    • 1970-01-01
    相关资源
    最近更新 更多