更新-IdentityServer4が変更され、IUserServiceがIResourceOwnerPasswordValidatorおよびIProfileServiceに置き換えられました
UserRepositoryを使用して、データベースからすべてのユーザーデータを取得しました。これはコンストラクターに注入(DI)され、で定義されます。Startup.cs
ます。また、IDサーバー用に次のクラスを作成しました(これも挿入されます)。
最初に定義するResourceOwnerPasswordValidator.cs
:
public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
private readonly IUserRepository _userRepository;
public ResourceOwnerPasswordValidator(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
try
{
var user = await _userRepository.FindAsync(context.UserName);
if (user != null)
{
if (user.Password == context.Password) {
context.Result = new GrantValidationResult(
subject: user.UserId.ToString(),
authenticationMethod: "custom",
claims: GetUserClaims(user));
return;
}
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Incorrect password");
return;
}
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "User does not exist.");
return;
}
catch (Exception ex)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Invalid username or password");
}
}
public static Claim[] GetUserClaims(User user)
{
return new Claim[]
{
new Claim("user_id", user.UserId.ToString() ?? ""),
new Claim(JwtClaimTypes.Name, (!string.IsNullOrEmpty(user.Firstname) && !string.IsNullOrEmpty(user.Lastname)) ? (user.Firstname + " " + user.Lastname) : ""),
new Claim(JwtClaimTypes.GivenName, user.Firstname ?? ""),
new Claim(JwtClaimTypes.FamilyName, user.Lastname ?? ""),
new Claim(JwtClaimTypes.Email, user.Email ?? ""),
new Claim("some_claim_you_want_to_see", user.Some_Data_From_User ?? ""),
new Claim(JwtClaimTypes.Role, user.Role)
};
}
そしてProfileService.cs
:
public class ProfileService : IProfileService
{
private readonly IUserRepository _userRepository;
public ProfileService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
try
{
if (!string.IsNullOrEmpty(context.Subject.Identity.Name))
{
var user = await _userRepository.FindAsync(context.Subject.Identity.Name);
if (user != null)
{
var claims = GetUserClaims(user);
context.IssuedClaims = claims.Where(x => context.RequestedClaimTypes.Contains(x.Type)).ToList();
}
}
else
{
var userId = context.Subject.Claims.FirstOrDefault(x => x.Type == "sub");
if (!string.IsNullOrEmpty(userId?.Value) && long.Parse(userId.Value) > 0)
{
var user = await _userRepository.FindAsync(long.Parse(userId.Value));
if (user != null)
{
var claims = ResourceOwnerPasswordValidator.GetUserClaims(user);
context.IssuedClaims = claims.Where(x => context.RequestedClaimTypes.Contains(x.Type)).ToList();
}
}
}
}
catch (Exception ex)
{
}
}
public async Task IsActiveAsync(IsActiveContext context)
{
try
{
var userId = context.Subject.Claims.FirstOrDefault(x => x.Type == "user_id");
if (!string.IsNullOrEmpty(userId?.Value) && long.Parse(userId.Value) > 0)
{
var user = await _userRepository.FindAsync(long.Parse(userId.Value));
if (user != null)
{
if (user.IsActive)
{
context.IsActive = user.IsActive;
}
}
}
}
catch (Exception ex)
{
}
}
}
それからStartup.cs
私は次のことをしました:
public void ConfigureServices(IServiceCollection services)
{
var cert = new X509Certificate2(Path.Combine(_environment.ContentRootPath, "idsrv4test.pfx"), "your_cert_password");
services.AddScoped(_ => new YourDbContext(Configuration.GetConnectionString("DefaultConnection")));
services.AddScoped<IUserRepository, UserRepository>();
services.AddIdentityServer()
.AddSigningCredential(cert)
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddProfileService<ProfileService>();
services.AddTransient<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>();
services.AddTransient<IProfileService, ProfileService>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseIdentityServer();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
IdentityServerAuthenticationOptions identityServerValidationOptions = new IdentityServerAuthenticationOptions
{
Authority = "http://localhost:50000/",
ApiSecret = "secret",
ApiName = "my.api.resource",
AutomaticAuthenticate = true,
SupportedTokens = SupportedTokens.Both,
AutomaticChallenge = true,
RequireHttpsMetadata = false
};
app.UseIdentityServerAuthentication(identityServerValidationOptions);
}
またConfig.cs
、クライアント、API、およびリソースを定義するものも必要になります。ここで例を見つけることができます:https://github.com/IdentityServer/IdentityServer4.Demo/blob/master/src/IdentityServer4Demo/Config.cs
これで、IdentityServer / connect / tokenを呼び出すことができるはずです。
詳細については、ドキュメントを確認してください:https://media.readthedocs.org/pdf/identityserver4/release/identityserver4.pdf
古い答え(これは新しいIdentityServer4では機能しなくなりました)
物事の流れを理解すれば、とても簡単です。
IdentityServiceを次のように構成します(Startup.cs- ConfigureServices()
):
var builder = services.AddIdentityServer(options =>
{
options.SigningCertificate = cert;
});
builder.AddInMemoryClients(Clients.Get());
builder.AddInMemoryScopes(Scopes.Get());
builder.Services.AddTransient<IUserService, UserService>();
services.AddTransient<IUserRepository, UserRepository>();
次に、UserServiceを設定します
public class UserService : IUserService
{
private IUserRepository _userRepository;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public Task AuthenticateLocalAsync(LocalAuthenticationContext context)
{
var user = _userRepository.Find(context.UserName);
if (user.Password == context.Password)
{
context.AuthenticateResult = new AuthenticateResult(
user.UserId.ToString(),
user.Email,
new Claim[]
{
new Claim(Constants.ClaimTypes.Name, user.Firstname + " " + user.Surname),
new Claim(Constants.ClaimTypes.Email, user.Email),
new Claim(Constants.ClaimTypes.Role, user.Role.ToString()),
new Claim("company", user.Company)
}
);
}
return Task.FromResult(0);
}
public Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var user = _userRepository.Find(context.Subject.Identity.Name);
if (user != null)
{
var claims = new Claim[]
{
new Claim(Constants.ClaimTypes.Name, user.Firstname + " " + user.Surname),
new Claim(Constants.ClaimTypes.Email, user.Email),
new Claim(Constants.ClaimTypes.Role, user.Role.ToString(), ClaimValueTypes.Integer),
new Claim("company", user.Company)
};
context.IssuedClaims = claims.Where(x => context.RequestedClaimTypes.Contains(x.Type));
}
return Task.FromResult(0);
}
public Task IsActiveAsync(IsActiveContext context)
{
var user = _userRepository.Find(context.Subject.Identity.Name);
return Task.FromResult(user != null);
}
}
基本的UserService
にbuilder
(タイプのIdentityServerBuilder
)に注入することによりServices
、authでUserServiceを呼び出すことができます。
これを実行するのに数時間かかったので、これが他の人に役立つことを願っています。
IUserService
うーん、私が見ることができることから、IdSvr4(ASP.NET Core 1.0の場合)はもう存在しません。これは、2つのインターフェース/サービスIProfileService
とに置き換えられましたIResourceOwnerPasswordValidator
。