Duende Identity Server: как вернуть токены внешнего провайдера клиенту Angular/WPF/MVC вместе с токенами Duende
Я использую сервер Duende Identity, и у меня есть внешний поставщик аутентификации, скажем, Google. При входе в Google мы получаем токены от Google, которые мы можем использовать для вызова некоторых API Google.
Мне нужно вернуть токен Google также на сторону клиента (Angular/WPF/MVC и т. д.) через конечную точку токена Duende.
Из кода я вижу, что ответ конечной точки токена Duende имеет свойство Custom, но я понятия не имею, как и откуда я могу вставить свои значения.
internal class ResultDto
{
public string id_token { get; set; }
public string access_token { get; set; }
public int expires_in { get; set; }
public string token_type { get; set; }
public string refresh_token { get; set; }
public string scope { get; set; }
[JsonExtensionData]
public Dictionary<string, object> Custom { get; set; }
}
Я хотел бы увидеть некоторые фрагменты кода или указания о том, как добавить значения в это пользовательское свойство с помощью существующих функций Duende.
2 ответа
Если вам нужно настроить ответ токена, вы можетеICustomTokenResponseGenerator
(Это для сервера идентификации 3, если вы используете версию 4 и выше, я не уверен, но это должен быть ITokenResponseGenerator):
class CustomTokenResponseGenerator : ICustomTokenRequestValidator
{
public Task<TokenResponse> GenerateAsync(ValidatedTokenRequest request, TokenResponse response)
{
response.Custom.Add("custom_field", "custom data");
return Task.FromResult(response);
}
}
а затем добавьте его с фабрикой:
factory.CustomTokenResponseGenerator = new Registration<ICustomTokenResponseGenerator, CustomTokenResponseGeneratorService>();
Ответ от доктора Занда был полезен и помог мне решить проблему, но он был связан с сервером идентификации, а не с Duende. В случае с Duende наследуемые интерфейсы и классы другие.
internal class CustomTokenResponseGenerator : TokenResponseGenerator
{
public CustomTokenResponseGenerator(ISystemClock clock, ITokenService tokenService, IRefreshTokenService refreshTokenService, IScopeParser scopeParser, IResourceStore resources, IClientStore clients, ILogger<TokenResponseGenerator> logger) : base(clock, tokenService, refreshTokenService, scopeParser, resources, clients, logger)
{
}
protected override async Task<TokenResponse> ProcessAuthorizationCodeRequestAsync(TokenRequestValidationResult request)
{
var result = await base.ProcessAuthorizationCodeRequestAsync(request);
if (result != null)
{
//using this user we can get the external token form google, facebook etc
var user = request.ValidatedRequest.Subject;
//I have added google token to the user claims when I got the token from google.
//Instead we can add it to database and make a DB call here if you want to persist
var externalTokenResponse = user.Claims.FirstOrDefault(s => s.Type == "ExternalToken")?.Value;
if (!string.IsNullOrEmpty(externalTokenResponse))
{
if (result.Custom == null)
{
result.Custom = new Dictionary<string, object>();
}
result.Custom.Add("ExternalToken", JsonDocument.Parse(externalTokenResponse));
}
}
return result;
}
}
После того, как мы определили вышеуказанную реализацию, мы можем зарегистрироваться в DI, используя приведенный ниже код.
builder.Services.AddTransient<ITokenResponseGenerator, CustomTokenResponseGenerator>();
Вышеупомянутое переопределит реализацию Duende по умолчанию.