Reputation: 87
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
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
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
Reputation: 81
I think you can inject the IAuthenticationHandlerProvider service and use following:
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