I am using Duende Identity server and I have an external authentication provider lets say google. While logging into google we get tokens from google which we can make use of calling some google API's.

I need to return the google token also to the client side(Angular/WPF/MVC etc) through Duende token endpoint.

I can see from the code that Duende token endpoint response has a Custom property, but I have no clue how or from where I can insert my values.

From Duende Source Code

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; }
}

I would like to see some code snippets or direction on how to add values to this Custom property by existing Duende functionality.

2

There are 2 answers

0
Kiran B On BEST ANSWER

The answer from MD Zand was helpful and it helped me to solve the issue, but it was related to Identity server and not Duende. In the case of Duende the interfaces and classes to inherit are different.

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;
    }
}

Once we have defined the above implementation we can register to DI using below code

builder.Services.AddTransient<ITokenResponseGenerator, CustomTokenResponseGenerator>();

The above will override the default implementation of Duende.

4
MD Zand On

If you need to customize token response you can ICustomTokenResponseGenerator (It is for identity server 3, if you are using version 4 and above I am not sure but it should be ITokenResponseGenerator):

class CustomTokenResponseGenerator : ICustomTokenRequestValidator
{
    public Task<TokenResponse> GenerateAsync(ValidatedTokenRequest request, TokenResponse response)
    {
        response.Custom.Add("custom_field", "custom data");      
        return Task.FromResult(response);
    }
}

and then add it with factory:

 factory.CustomTokenResponseGenerator = new Registration<ICustomTokenResponseGenerator, CustomTokenResponseGeneratorService>();