Dom
Dom

Reputation: 87

Getting access token within Claims Transformer in ASP.NET Core

I'm developing a set of applications including an Identity Server using IdentityServer4, a .NET Core MVC app, a .NET Core WebAPI.

As part of a asp.net core mvc application I am using AddOpenIdConnect to do authentication and doing options.SaveTokens = true.

However, as part of Claims Transformation, in TransformAsync I would like to be able to have access to the access token provided by the identityserver. This is to be able to call a permissions endpoint on the api to populate the principal with claims that I can use to do authorization on my controllers etc.

If I call HttpContext.GetTokenAsync("access_token") I get a stackoverflowexception due to the infinite loop created by authenticate being called, which then calls TransformAsync again.

Is this a sound approach in the first place? Typically, TransformAsync is where I would populate application permissions. Is there any way of accessing the token without triggering the authenticate again?

Would appreciate any help as we're a bit stumped! Thanks

Edit: I've seen suggestions around doing transformations in the OnTicketReceived event. It looks like I'd have access to the token through the properties in there. Is this a better place to do it?

Upvotes: 3

Views: 2977

Answers (3)

Vivek Sharma
Vivek Sharma

Reputation: 2072

It has been many years since this question was posted, but if you are still looking for a solution to the issue, you can get the access token in the OnTokenValidated event.

OnTokenValidated = tokenValidatedContext =>
{
    var handler = new JwtSecurityTokenHandler();
    // get access token
    var jsonToken = handler.ReadJwtToken(tokenValidatedContext.TokenEndpointResponse.AccessToken); 

    var claims = new List<Claim>();

    claims.Add(new Claim("customClaimType", "customClaimValue"));

    var appIdentity = new ClaimsIdentity(claims);

    tokenValidatedContext.Principal.AddIdentity(appIdentity);
    return Task.CompletedTask;

}

Reference : Adding Custom Claims During Authentication

Upvotes: 1

tha4
tha4

Reputation: 400

I came across the same problem. My solution was,

Override JwtBearerEvents.TokenValidated event called by IdentityServer4.AccessTokenValidation middleware.

private Task OnTokenValidated(TokenValidatedContext tokenValidatedContext)
    {
        tokenValidatedContext.HttpContext.Items["access_token"] = (tokenValidatedContext.SecurityToken as JwtSecurityToken).RawData;
        return Task.CompletedTask;
    }

This will utilize HttpContext.Items collection which is request scoped. Now you can retreive this access token in TransformAsync method, like below.

var access_token = _httpContextAccessor.HttpContext.Items["access_token"] as string;

Please note that you need to inject IHttpContextAccessor to access HttpContext in ClaimsTransformer.

Upvotes: 3

Almogo
Almogo

Reputation: 81

I think you can inject the IAuthenticationHandlerProvider service and use following:

  1. Get the authentication handler by scheme name.
  2. get the AuthenticateResult by invoking AuthenticateAsync
  3. get the token from the authentication properties

    var token = string.Empty;
    var handler = await Handlers.GetHandlerAsync(context, scheme); // i.e. "OIDC"
    var result = await handler.AuthenticateAsync();
    if(result?.Succeeded == true) {
        token = result?.Properties?.GetTokenValue(tokenName);
    }
    

haven't tested it but i think it should work

Upvotes: 0

Related Questions