ROPCフローを使用してIdentityServer4で保護されたASP.NET Core WebApiを作成しました(この例を使用: https://github.com/robisim74/AngularSPAWebAPI )。
パスワードなしでサーバーからaccess_tokenを手動で生成する方法は?
[HttpPost("loginas/{id}")]
[Authorize(Roles = "admin")]
public async Task<IActionResult> LoginAs(int id, [FromServices] ITokenService TS,
[FromServices] IUserClaimsPrincipalFactory<ApplicationUser> principalFactory,
[FromServices] IdentityServerOptions options)
{
var Request = new TokenCreationRequest();
var User = await userManager.FindByIdAsync(id.ToString());
var IdentityPricipal = await principalFactory.CreateAsync(User);
var IdServerPrincipal = IdentityServerPrincipal.Create(User.Id.ToString(), User.UserName, IdentityPricipal.Claims.ToArray());
Request.Subject = IdServerPrincipal;
Request.IncludeAllIdentityClaims = true;
Request.ValidatedRequest = new ValidatedRequest();
Request.ValidatedRequest.Subject = Request.Subject;
Request.ValidatedRequest.SetClient(Config.GetClients().First());
Request.Resources = new Resources(Config.GetIdentityResources(), Config.GetApiResources());
Request.ValidatedRequest.Options = options;
Request.ValidatedRequest.ClientClaims = IdServerPrincipal.Claims.ToArray();
var Token = await TS.CreateAccessTokenAsync(Request);
Token.Issuer = "http://" + HttpContext.Request.Host.Value;
var TokenValue = await TS.CreateSecurityTokenAsync(Token);
return Ok(TokenValue);
}
新しくリリースされたIdentityServer 2.0.0の場合、コードにいくつかの変更が必要です。
[HttpPost("loginas/{id}")]
[Authorize(Roles = "admin")]
public async Task<IActionResult> LoginAs(int id, [FromServices] ITokenService TS,
[FromServices] IUserClaimsPrincipalFactory<ApplicationUser> principalFactory,
[FromServices] IdentityServerOptions options)
{
var Request = new TokenCreationRequest();
var User = await userManager.FindByIdAsync(id.ToString());
var IdentityPricipal = await principalFactory.CreateAsync(User);
var IdentityUser = new IdentityServerUser(User.Id.ToString());
IdentityUser.AdditionalClaims = IdentityPricipal.Claims.ToArray();
IdentityUser.DisplayName = User.UserName;
IdentityUser.AuthenticationTime = System.DateTime.UtcNow;
IdentityUser.IdentityProvider = IdentityServerConstants.LocalIdentityProvider;
Request.Subject = IdentityUser.CreatePrincipal();
Request.IncludeAllIdentityClaims = true;
Request.ValidatedRequest = new ValidatedRequest();
Request.ValidatedRequest.Subject = Request.Subject;
Request.ValidatedRequest.SetClient(Config.GetClients().First());
Request.Resources = new Resources(Config.GetIdentityResources(), Config.GetApiResources());
Request.ValidatedRequest.Options = options;
Request.ValidatedRequest.ClientClaims = IdentityUser.AdditionalClaims;
var Token = await TS.CreateAccessTokenAsync(Request);
Token.Issuer = HttpContext.Request.Scheme + "://" + HttpContext.Request.Host.Value;
var TokenValue = await TS.CreateSecurityTokenAsync(Token);
return Ok(TokenValue);
}
これを実現する別の方法を次に示します。
最初に、loginByという名前のカスタム許可を作成します
public class LoginByGrant : ICustomGrantValidator
{
private readonly ApplicationUserManager _userManager;
public string GrantType => "loginBy";
public LoginByGrant(ApplicationUserManager userManager)
{
_userManager = userManager;
}
public async Task<CustomGrantValidationResult> ValidateAsync(ValidatedTokenRequest request)
{
var userId = Guid.Parse(request.Raw.Get("user_id"));
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
return await Task.FromResult<CustomGrantValidationResult>(new CustomGrantValidationResult("user not exist"));
var userClaims = await _userManager.GetClaimsAsync(user.Id);
return
await Task.FromResult<CustomGrantValidationResult>(new CustomGrantValidationResult(user.Id.ToString(), "custom", userClaims));
}
}
次に、このカスタム許可をIDスタートアップクラスに追加します
factory.CustomGrantValidators.Add(
new Registration<ICustomGrantValidator>(resolver => new LoginByGrant(ApplicaionUserManager)));
そして最後にあなたのAPIで
public async Task<IHttpActionResult> LoginBy(Guid userId)
{
var tokenClient = new TokenClient(Constants.TokenEndPoint, Constants.ClientId, Constants.Secret);
var payload = new { user_id = userId.ToString() };
var result = await tokenClient.RequestCustomGrantAsync("loginBy", "customScope", payload);
if (result.IsError)
return Ok(result.Json);
return Ok(new { access_token = result.AccessToken, expires_in = result.ExpiresIn});
}
これを使って:
http://docs.identityserver.io/en/latest/topics/tools.html
IDサーバーに付属のこのツールを使用します。
ディペンデンシーインジェクションで受け取るには、コンストラクターで宣言します。
IdentityServer4.IdentityServerTools_identityServerTools
var issuer = "http://" + httpRequest.Host.Value; var token = await _identityServerTools.IssueJwtAsync( 30000、 issuer、 new System.Security.Claims.Claim [1] { 新しいSystem.Security.Claims.Claim( "cpf"、cpf) } );
元の質問に対する私のコメントに加えて。暗黙的/ハイブリッドフロー内に偽装機能を実装します。ユーザーが「特権管理者」であると判断された場合は、認証後に、なりすましたいアカウントを入力/選択できる追加のステップを提示します。それが完了したら、IDサーバーで選択したユーザーとしてセッションを確立するだけです(また、偽装されたセッションであり、だれが偽装を行っているかを示す追加のクレームを保存することもできます)。トークンは、パスワードを知らなくても、あたかもそのユーザーであるかのように発行されます。
さらに、自分でトークンを作成する場合は、IdSrv4によって提供されるITokenCreationServiceを確認してください。これを独自のコントローラー/サービス/何にでも挿入し、CreateTokenAsync(Token token)を使用して、任意のクレームを持つ署名付きJWTを生成できます。