The UserClaims in the identity resource are some attributes of the user. By default, even if more attributes are written, only one sub will be returned in the token. We need to add them in the code
var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.Apis)
.AddInMemoryClients(Config.Clients)
.AddTestUsers(TestUsers.Users)
.AddProfileService<ProfileService>();
// not recommended for production - you need to store your key material somewhere secure
builder.AddDeveloperSigningCredential();
Then implement IProfileService
public class ProfileService : IProfileService { protected readonly TestUserStore Users; public ProfileService(TestUserStore users) { Users = users; } public virtual Task GetProfileDataAsync(ProfileDataRequestContext context) { var user = Users.FindBySubjectId(context.Subject.GetSubjectId()); if (user != null) { //context.IssuedClaims = user.Claims.ToList(); context.IssuedClaims.AddRange(user.Claims); } return Task.CompletedTask; } public async Task IsActiveAsync(IsActiveContext context) { context.IsActive = true; } }
This will return all claim s in the token
With the token containing claim, you can access the protected API. Different scope s and roles carried in the token can be used for different APIs in the same API server
Different access rights
Configuration in API
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddAuthorization(options => { options.AddPolicy("fullaccess", policy => policy.RequireClaim("scope", "api2.full_access")); options.AddPolicy("readonly", policy => policy.RequireClaim("scope", "api2.read_only")); }); services.AddAuthentication("Bearer") .AddJwtBearer("Bearer", options => { options.Authority = "http://localhost:5000"; options.RequireHttpsMetadata = false; options.Audience = "api1"; }); }
The policy here is to restrict different scope s from accessing different APIs, which can be configured in IDS service
public static IEnumerable<ApiResource> Apis => new List<ApiResource> { new ApiResource("api1", "My API"), new ApiResource { Name = "api2", Scopes = { new Scope() { Name = "api2.full_access", DisplayName = "Full access to API 2" }, new Scope { Name = "api2.read_only", DisplayName = "Read only access to API 2" } } } };
The Controller of API is configured as follows
namespace Api { [Route("identity")] [Authorize(Roles= "admin")] public class IdentityController : ControllerBase { [Authorize(Policy = "fullaccess")] [HttpGet] public IActionResult Get() { return new JsonResult(from c in User.Claims select new { c.Type, c.Value }); } [Authorize(Policy = "readonly")] [HttpGet] [Route("get1")] public IActionResult Get1() { return new JsonResult(from c in User.Claims select new { c.Type, c.Value }); } } }
[Authorize(Roles= "admin")] in this way, the Controller can be accessed only by admin
The first API can only be accessed if the scope is full access in token
The second API can only be accessed if the scope is read only in token
The main application scenario is for different clients, but after the client gets the token, it can't access all the API s inside, so as to isolate each other
Reference resources: http://docs.identityserver.io/en/latest/topics/resources.html
https://docs.microsoft.com/zh-cn/aspnet/core/security/authorization/roles?view=aspnetcore-3.1
There is also a Claims in the Client
Claims = new List<Claim>
{
new Claim(JwtClaimTypes.Role, "admin")
}
Official website description:
However, it is not included in access_token by default. The official website is described as follows:
Therefore, you need to set these two parameters. After the token is parsed, you will find that
Added client UU automatically, didn't think about the use scenario