The ABB scheme is responsible for handling the third-party login and will return the following values:
access_token, id_token (also known as jwt_token), token_type = "Bearer" ,expire_in
The JWT scheme handles the frontend login to the ASP.NET Core Web API. In this flow, the API returns only the id_token (JWT token) to the frontend. However, in order to fetch additional claims (such as user information) via the user API on OnTokenValidated
we need access to the access_token
which is not available in JWT scheme, how to access this?
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "Bearer";
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer("Bearer", async options =>
options.Authority = ""; // e.g., IdentityServer 3rd party
options.Audience = "";
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
};// Set to true if using HTTPS
options.Events = new JwtBearerEvents
{
OnTokenValidated = async context =>
{
var principal = context.Principal;
var identity = context.HttpContext.User.Identity;
var access_token = context.Request.Headers["access_token"].ToString();
if (!string.IsNullOrEmpty(access_token))
{
//Needs to call userInfo fot that access_token needed, but for FE jwt token Id_token only passed.
var userInfo = await GetUserInfoFromThirdParty(access_token);
var claimsIdentity = (ClaimsIdentity)context.Principal.Identity;
}
// Custom logic after successful token validation (e.g., logging)
await Task.CompletedTask;
}
};
})
.AddCookie("default")
//Token endpoint here will return Id_token (jwt token) and access_token which is used to get userinfo and claims
.AddOAuth("ABB", o =>
{
o.SignInScheme = "default";
o.ClientId = "";
o.ClientSecret = "";
o.AuthorizationEndpoint = "";
o.TokenEndpoint = "";
o.CallbackPath = "/userinfo";
o.SaveTokens = true;
o.UserInformationEndpoint = "";
o.Scope.Add("openid");
o.Scope.Add("entitlement_group");
o.Scope.Add("profile");
o.ClaimActions.MapJsonKey("Permissions", "entitlement_group");
o.Events = new OAuthEvents
{
OnCreatingTicket = async ctx =>
{
using var request = new HttpRequestMessage(HttpMethod.Get, ctx.Options.UserInformationEndpoint);
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", ctx.AccessToken);
using var result = await ctx.Backchannel.SendAsync(request);
var user = await result.Content.ReadFromJsonAsync<JsonElement>();
var identity = (ClaimsIdentity)ctx.Principal.Identity;
// Manually adding claims based on user data
identity.AddClaim(new Claim("entitlement_group", user.GetProperty("entitlement_group").ToString()));
ctx.RunClaimActions(user);
JObject response = JObject.Parse(ctx.TokenResponse.Response.RootElement.ToString());
var idToken = response.Value<string>("id_token");
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadJwtToken(idToken);
if (jwtToken != null)
{
// Passing jwt token for FE
identity = new ClaimsIdentity(jwtToken?.Claims, "Bearer", ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType);
identity.AddClaim(new Claim("idToken", idToken));
ctx.Principal = new ClaimsPrincipal(identity);
}
}
};
});