繁体   English   中英

单个项目中的 Identityserver4 和 API

[英]Identityserver4 and API in single project

我有一个 IdentityServer4 asp.net-core 主机设置用于资源所有者密码授予,使用 JWT Bearer 令牌和一个单独的 asp.net-core 主机中的 API,该主机具有我的 API 和两个 Angular 客户端。
身份验证和授权从我的两个 Angular 客户端到我的 API。
现在我需要在 IdentityServer4 主机中公开一个 API,以便我可以从其中一个 Angular 客户端创建用户。
我已将我的身份验证和授权设置从我的 API 复制到我的 IdentityServer4 主机,但是,我无法对其进行身份验证。

在下面的代码中,在 API 中,我可以在 jwt.Authority... 行上设置一个断点,第一次调用将在我的 API 中触发此断点,但不会在 IdentityServer4 主机中触发。

验证

services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
  .AddJwtBearer(jwt =>
  {
    jwt.Authority = config.Authentication.Authority; //Breakpoint here
    jwt.RequireHttpsMetadata = config.Authentication.RequireHttpsMetadata;
    jwt.Audience = Common.Authorization.Settings.ServerApiName;
  });

授权

我不确定它是否相关,但我使用的是基于角色的授权,以下是为此设置。

var authPolicyBuilder = new AuthorizationPolicyBuilder()
    .RequireRole(Common.Authorization.Settings.ServerApiRoleBasePolicyName)
    .Build();

services.AddMvc(options =>
    {
        options.Filters.Add(new AuthorizeFilter(authPolicyBuilder));

        ...

services.AddAuthorization(options =>
    {
        options.AddPolicy(Common.Authorization.Settings.ServerApiSetupClientAdminRolePolicyName, policy =>
        {
            policy.RequireClaim("role", Common.Authorization.Settings.ServerApiSetupClientAdminRolePolicyName);

我从日志中提取了以下内容:我看到的是在非工作情况下,我从来没有达到调用 JWT 验证的地步(工作日志中的#3)。
这只是我日志的一小部分摘录,如果需要,我可以完整地分享它们。

在职的

1 请求开始 HTTP/1.1 GET http://localhost:5100/packages/
(SourceContext:Microsoft.AspNetCore.Hosting.Internal.WebHost)
2 连接 ID“0HLC8PLQH2NRU”已启动。
(SourceContext:Microsoft.AspNetCore.Server.Kestrel)
3 请求开始 HTTP/1.1 GET http://localhost:5000/.well-known/openid-configuration
(SourceContext:Microsoft.AspNetCore.Hosting.Internal.WebHost)
--截断--

不工作

1 请求开始 HTTP/1.1 GET http://localhost:5000/users
(SourceContext:Microsoft.AspNetCore.Hosting.Internal.WebHost)
--截断--

客户

new Client
{
    ClientId = "setup_app",
    ClientName = "Setup App",
    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
    AccessTokenType = AccessTokenType.Jwt,
    AccessTokenLifetime = 3600,
    IdentityTokenLifetime = 3600,
    UpdateAccessTokenClaimsOnRefresh = true,
    SlidingRefreshTokenLifetime = 3600,
    AllowOfflineAccess = false,
    RefreshTokenExpiration = TokenExpiration.Absolute,
    RefreshTokenUsage = TokenUsage.OneTimeOnly,
    AlwaysSendClientClaims = true,
    Enabled = true,
    RequireConsent = false,
    AlwaysIncludeUserClaimsInIdToken = true,

    AllowedCorsOrigins = { config.CorsOriginSetupClient },


    ClientSecrets =
    {
        new Secret(Common.Authorization.Settings.ServerApiSetupClientSecret.Sha256())
    },

    AllowedScopes =
    {
        Common.Authorization.Settings.ServerApiName,
    }
},
new Client
{
    ClientId = "client_app",
    ClientName = "Client App",
    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
    AccessTokenType = AccessTokenType.Jwt,
    AccessTokenLifetime = 3600,
    IdentityTokenLifetime = 3600,
    UpdateAccessTokenClaimsOnRefresh = true,
    SlidingRefreshTokenLifetime = 3600,
    AllowOfflineAccess = false,
    RefreshTokenExpiration = TokenExpiration.Absolute,
    RefreshTokenUsage = TokenUsage.OneTimeOnly,
    AlwaysSendClientClaims = true,
    Enabled = true,
    RequireConsent = false,
    AlwaysIncludeUserClaimsInIdToken = true,

    AllowedCorsOrigins = { config.CorsOriginSetupClient },


    ClientSecrets =
    {
        new Secret(Common.Authorization.Settings.ServerApiAppClientSecret.Sha256())
    },

    AllowedScopes =
    {
        Common.Authorization.Settings.ServerApiName,
    }
}

身份资源

return new List<IdentityResource>
{
    new IdentityResources.OpenId(),
    new IdentityResources.Profile(),
    new IdentityResource(Common.Authorization.Settings.ServerApiScopeName, new []{
        "role",
        Common.Authorization.Settings.ServerApiSetupClientAdminRolePolicyName,
        Common.Authorization.Settings.ServerApiAppClientAdminRolePolicyName,
        Common.Authorization.Settings.ServerApiAppClientUserRolePolicyName,
}),
};

用户

var adminUser = new ApplicationUser
{
    UserName = "admin",
    Email = "admin@noreply",
};
adminUser.Claims = new List<IdentityUserClaim>
{
    new IdentityUserClaim(new Claim(JwtClaimTypes.PreferredUserName, adminUser.UserName)),
    new IdentityUserClaim(new Claim(JwtClaimTypes.Email, adminUser.Email)),
    new IdentityUserClaim(new Claim("role", Common.Authorization.Settings.ServerApiSetupClientAdminRolePolicyName)),
    new IdentityUserClaim(new Claim("role", Common.Authorization.Settings.ServerApiRoleBasePolicyName)),
    new IdentityUserClaim(new Claim("profileImage", $"https://robohash.org/{Convert.ToBase64String(System.Security.Cryptography.MD5.Create().ComputeHash(System.Text.Encoding.UTF8.GetBytes(adminUser.UserName)))}?set=set2"))
};
adminUser.AddRole(Common.Authorization.Settings.ServerApiSetupClientAdminRolePolicyName);

应用程序接口

new ApiResource(Common.Authorization.Settings.ServerApiName, "Server API"){
    ApiSecrets =
    {
        new Secret(Common.Authorization.Settings.ServerApiAppClientSecret.Sha256())
    },
}, 

在此处查找https://github.com/IdentityServer/IdentityServer4.Samples

看起来应该是这样的:

验证:

services.AddAuthentication("Bearer")
            .AddIdentityServerAuthentication(options =>
            {
                options.Authority = config.Authentication.Authority;

                options.RequireHttpsMetadata = false;

                options.ApiName = ServerApiName;
                options.ApiSecret = ServerApiAppClientSecret;
            });

或者使用 JWT,您可以尝试:

services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(options =>
        {
            options.Authority = config.Authentication.Authority;
            options.RequireHttpsMetadata = false;
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateAudience = true,
                ValidAudiences = new[]
                {
                    $"{config.Authentication.Authority}/resources",
                    ServerApiName
                },
            };
        });

此外,您还可以添加授权策略,例如:

授权:

services.AddMvc(opt =>
            {
                var policy = new AuthorizationPolicyBuilder()
                       .RequireAuthenticatedUser()
                       .RequireScope("api").Build();
                opt.Filters.Add(new AuthorizeFilter(policy));
            })

有一个 MS 开箱即用的服务,旨在添加对本地 API 的支持

首先在IDS4 startup.cs, ConfigureServices 添加

services.AddLocalApiAuthentication();

然后在您的客户端声明中的 IDS4 config.cs

AllowedScopes = {
     IdentityServerConstants.LocalApi.ScopeName,  <<<< ---- This is for IDS4 Api access
     IdentityServerConstants.StandardScopes.OpenId,
     IdentityServerConstants.StandardScopes.Profile,
     IdentityServerConstants.StandardScopes.Email
     ...

仍在配置中将新范围添加到 ApiScopes

new ApiScope(IdentityServerConstants.LocalApi.ScopeName)

笔记

IdentityServerConstants.LocalApi.ScopeName resolves to 'IdentityServerApi'

现在,在位于 IDS4 项目中的闪亮新 Api 中,将授权标记添加到你的 api 端点

[Authorize(IdentityServerConstants.LocalApi.PolicyName)]
[HttpGet]
public IEnumerable<string> Get()
{
    return new string[] { "value1", "value2" };
}

最后,您需要在您的客户端中请求这个新范围

Scope = "openid sig1 api1 profile email offline_access company IdentityServerApi",

而已

我认为会有所帮助,它包含在社区示例中

暂无
暂无

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

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