回答有点晚了。
在我的Generating Access Token Without Password 的情况下,还有另一个identity server 作为组织sso,我们的实现已经使用IdentityServer,所以我们需要从第二个IdentityServer 获取用户令牌(在用户登录并重定向到我们的app),提取sub,检查它是否已经存在(如果没有插入我们本地的IdentityServer),最后选择用户并使用新授权为用户获取令牌。
您的客户应该将此granttype 作为允许的授予类型(此处为userexchange):
请参阅:identity server docs 或 duende docs 了解更多信息
public class TokenExchangeGrantValidator : IExtensionGrantValidator {
protected readonly UserManager<ToranjApplicationUser> _userManager;
private readonly IEventService _events;
public TokenExchangeGrantValidator(ITokenValidator validator, IHttpContextAccessor httpContextAccessor, UserManager<ToranjApplicationUser> userManager
, IEventService events) {
_userManager = userManager;
_events = events;
}
public async Task ValidateAsync(ExtensionGrantValidationContext context) {
var userName = context.Request.Raw.Get("uname");
if (string.IsNullOrEmpty(userName)) {
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
return;
}
var user = await _userManager.FindByNameAsync(userName);
// or use this one, if you are sending userId
//var user = await _userManager.FindByIdAsync(userId);
if (null == user) {
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
return;
}
await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id.ToString(), user.UserName, false, context.Request.ClientId));
var customResponse = new Dictionary<string, object>
{
{OidcConstants.TokenResponse.IssuedTokenType, OidcConstants.TokenTypeIdentifiers.AccessToken}
};
context.Result = new GrantValidationResult(
subject: user.Id.ToString(),
authenticationMethod: GrantType,
customResponse: customResponse);
}
public string GrantType => "userexchange";
}
在startup 的ConfigureServices 之后var builder = services.AddIdentityServer(...) 添加您新创建的类。
builder.AddExtensionGrantValidator<TokenExchangeGrantValidator>();
调用它来获取令牌很简单:
POST /connect/token
grant_type=userexchange&
scope=yourapi&
uname=yourusername&
client_id=yourClientId
client_secret=secret