Я создал ASP.NET Core WebApi, защищенный IdentityServer4, используя поток ROPC (используя этот пример: https://github.com/robisim74/AngularSPAWebAPI).
Как вручную сгенерировать access_token с сервера без пароля?
Я создал ASP.NET Core WebApi, защищенный IdentityServer4, используя поток ROPC (используя этот пример: 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);
}
В дополнение к моему комментарию к вашему оригинальному вопросу. Внедрить функцию олицетворения в неявном/гибридном потоке. Если пользователь определен как "супер-администратор", то после их представления им предоставляется дополнительный шаг после проверки подлинности, который позволяет им вводить/выбирать учетную запись, которую они хотят выдавать. Как только это будет сделано, просто установите сеанс на сервере идентификации как выбранный пользователь (и, возможно, сохраните дополнительные требования, обозначающие, что он является олицетворением сеанса и кто выполняет олицетворение). Любые жетоны будут выдаваться так, как если бы вы были этим пользователем и все без необходимости знать пароль.
Кроме того, если вы хотите сами создавать маркеры, посмотрите на ITokenCreationService, предоставленный IdSrv4. Вы можете ввести это в свой собственный контроллер/службу/что угодно и использовать CreateTokenAsync (токен токена) для создания подписанного JWT с любыми претензиями, которые вам нравятся.
Вот еще один способ добиться этого:
сначала создайте пользовательский грант с именем 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));
}
}
затем добавьте это пользовательское разрешение в класс запуска идентификации
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
Используйте этот инструмент, поставляемый с сервером идентификации:
Объявите это в конструкторе, чтобы получить путем внедрения зависимости.
IdentityServer4.IdentityServerTools _identityServerTools
var issuer = "http://" + httpRequest.Host.Value; var token = await _identityServerTools.IssueJwtAsync( 30000, issuer, new System.Security.Claims.Claim[1] { new System.Security.Claims.Claim("cpf", cpf) } );