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 по умолчанию.

Другие вопросы по тегам