ASP.NET样板+ IdentityServer [英] ASP.NET Boilerplate + IdentityServer

查看:79
本文介绍了ASP.NET样板+ IdentityServer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试实现IdentityServer,如 https://aspnetboilerplate.com上所述/Pages/Documents/Zero/Identity-Server

I tried to implement IdentityServer as it is explained at https://aspnetboilerplate.com/Pages/Documents/Zero/Identity-Server

但是该示例不起作用.

我从ASP.NET Boilerplate开始了一个Core 2.0 Angular项目.是否有基于文档的更新的工作示例?

I started a Core 2.0 Angular project from ASP.NET Boilerplate. Is there any updated working sample based on the documentation?

存在多个问题,但其中一个问题是 AuthConfigurer.cs .

There is more than one problem, but one of them is with AuthConfigurer.cs.

API调用者(客户端)无法通过令牌验证.

The API caller (client) cannot pass the token validation.

实际上, TokenAuthController.cs 中有一个令牌生成代码:

Actually, there is a token generation code in TokenAuthController.cs:

private string CreateAccessToken(IEnumerable<Claim> claims, TimeSpan? expiration = null)
{
    var now = DateTime.UtcNow;
    var jwtSecurityToken = new JwtSecurityToken(
        issuer: _configuration.Issuer,
        audience: _configuration.Audience,
        claims: claims,
        notBefore: now,
        expires: now.Add(expiration ?? _configuration.Expiration),
        signingCredentials: _configuration.SigningCredentials
    );
    return new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
}

但是在Startup类中,AddIdentityAddAuthentication创建不同的令牌值和验证规则.

But in the Startup class, AddIdentity and AddAuthentication create different token values and validation rules.

services.AddIdentityServer()
        .AddDeveloperSigningCredential()
        .AddInMemoryIdentityResources(IdentityServerConfig.GetIdentityResources())
        .AddInMemoryApiResources(IdentityServerConfig.GetApiResources())
        .AddInMemoryClients(IdentityServerConfig.GetClients())
        .AddAbpPersistedGrants<IAbpPersistedGrantDbContext>()
        .AddAbpIdentityServer<User>(); ;

services.AddAuthentication().AddIdentityServerAuthentication("IdentityBearer", options =>
{
    options.Authority = "http://localhost:62114/";
    options.RequireHttpsMetadata = false;
});

令牌可以由双方生成. CreateAccessToken由Angular客户端和API客户端调用,如下所示:

The token can be generated by both sides. CreateAccessToken is called by the Angular client and by the API client as shown below:

var disco = await DiscoveryClient.GetAsync("http://localhost:21021");

var httpHandler = new HttpClientHandler();
httpHandler.CookieContainer.Add(new Uri("http://localhost:21021/"), new Cookie(MultiTenancyConsts.TenantIdResolveKey, "1")); //Set TenantId
var tokenClient = new TokenClient(disco.TokenEndpoint, "AngularSPA", "secret", httpHandler);
var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync("admin", "123qwe", "default-api"); //RequestClientCredentialsAsync("default-api");

但是其中只有一个(根据身份验证"部分)无法通过身份验证.

But just one of them (according to the Authentication part) cannot pass authentication.

我需要API客户端身份验证和Angular客户端身份验证才能工作.

I need both the API client authentication and the Angular client authentication to work.

我从有关双重身份验证的链接中获得了一些线索:
https://wildermuth.com/2017/08/19/Two-AuthorizationSchemes-in-ASP-NET-Core-2

I have some clue from a link about dual authentication:
https://wildermuth.com/2017/08/19/Two-AuthorizationSchemes-in-ASP-NET-Core-2

但是我无法解决这个问题.任何评论对于解决问题都是非常有价值的.

But I could not solve this. Any comment is very valuable to solve the problem.

推荐答案

在和我设法解决问题的地方,这里是需要的修改;

At the and I managed to solve problem here are the needed modifications;

1-在TokenAuthController中,有一个令牌创建代码,如下所示;

1- in the TokenAuthController there is a token creation code as shown below;

private static List<Claim> CreateJwtClaims(ClaimsIdentity identity)
        {
            var claims = identity.Claims.ToList();
            var nameIdClaim = claims.First(c => c.Type == ClaimTypes.NameIdentifier);

            // Specifically add the jti (random nonce), iat (issued timestamp), and sub (subject/user) claims.
            claims.AddRange(new[]
            {
                new Claim(JwtRegisteredClaimNames.Sub, nameIdClaim.Value),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.Now.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)
            });

            return claims;
        }

如果您开始使用Identityserver,则登录产生的声明与当前实现完全不同,并且"sub"声明已添加到声明中.因此,没有必要单独添加.因此,请如下所示进行更新

If you start using Identityserver Claims coming from login is totally different from current implementation and "sub" claim is already added to claims. So it is not necessary to add seperately. So please update this as shown below

 private static List<Claim> CreateJwtClaims(ClaimsIdentity identity)
        {
            var claims = identity.Claims.ToList();

            // Specifically add the jti (random nonce), iat (issued timestamp), and sub (subject/user) claims.
            claims.AddRange(new[]
            {
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.Now.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)
            });

            return claims;
        }

2-将身份验证添加到启动类,如下所示;最重要的部分是authenticationSchemaName"IdentityBearer",请不要忘记添加它.

2- Add Authentcation to startup class as shown below; The most important part is authenticationSchemaName "IdentityBearer" do not forget adding it.

services.AddAuthentication().AddIdentityServerAuthentication("IdentityBearer", options =>
            {
                options.Authority = "http://localhost:21021/";
                options.RequireHttpsMetadata = false;
            });

3-但这还不够.因为如果您在启动身份验证中查看configure methon会被注册为

3- But this is not enough. because if you look at configure methon in startup authontication is registered as

app.UseJwtTokenMiddleware(); 

如果您选中它,它使用的是"bearer"架构,而不是我们上面添加的IdentityBearer.因此,我们还需要另外的身份验证注册.也添加此行(两者都有)

if you check it it uses "bearer" schema not IdentityBearer as we added above. So we also need anpther authenticaiton registration. Add this line too (have both of them)

    app.UseJwtTokenMiddleware("IdentityBearer");

4-但是您可以看到,没有使用字符串参数的方法来添加UseJwtTokenMiddleware的方法,因此需要将其更新为该类.请按如下所示更改课程;

4- But as you can see there is no method taking string parameter to add UseJwtTokenMiddleware so it is needed to update that class to. please change your class as shown below;

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;

namespace MyProject.Authentication.JwtBearer
{
    public static class JwtTokenMiddleware
    {
        public static IApplicationBuilder UseJwtTokenMiddleware(this IApplicationBuilder app)
        {
            return UseJwtTokenMiddleware(app, JwtBearerDefaults.AuthenticationScheme);
        }

        public static IApplicationBuilder UseJwtTokenMiddleware(this IApplicationBuilder app, string authenticationScheme)
        {
            return app.Use(async (ctx, next) =>
            {
                if (ctx.User.Identity?.IsAuthenticated != true)
                {
                    var result = await ctx.AuthenticateAsync(authenticationScheme);
                    if (result.Succeeded && result.Principal != null)
                    {
                        ctx.User = result.Principal;
                    }
                }

                await next();
            });
        }        
    }
}

现在,您现在拥有两种不同的令牌类型和两种不同的验证器.您可以让API客户端使用基本令牌信息,而JWT令牌是通过从角度客户端登录创建的.如果您调试每个请求,则尝试传递两个请求,但只有其中一个成功,这对您就足够了.

Now you have now two different token type and two different validator. YOu can have API client using basic token info and JWT tokens are created by login from angular client. if you debug each request tries to pass two of them but just one of them succeed which is enough for you.

如果aspnetboilerplate小组根据此要求更新样本,那就太好了.

if aspnetboilerplate team updates sample according to this requirement it would be great.

这篇关于ASP.NET样板+ IdentityServer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆