openiddict token expires_in
How can I add custom claims to be returned when requesting a token using OpenIddict?
I'm building ASP.NET Core 1.1 app (cross platform) and trying (using this sample) to add custom claims to the returned access_token
when requesting /connect/token
endpoint.
What I need is to not only return the claims serialized in the access_token
but to return them in the response like this:
{
"token_type": "Bearer",
"access_token": "...",
"expires_in": 1799,
"custom_claim": "..."
}
What I found on internet that I have to use AspNet.Security.OpenIdConnect.Server
and write my provider in order to be able to do what I want.
Isn't there a simple way using the first sample ?
I'm using OAUth 2.0, grant type Password
and no JWT.
Not a requirement to not use JWT, it's just I used to OAuth in ASP.NET 4.5
-
Is there a specific reason you need it in that format? Deserializing the payload portion of the returned token is very simple even in javascript? Just curios as to why you would want them like in your example.– Louis LewisNov 9, 2016 at 9:47
-
@LouisLewis I'm not using JWT, so deserializing is not applicable as I think, even if I used JWT i'm not able to return the custom claims in the token.– DabbasNov 9, 2016 at 10:00
3 Answers
What I need is to not only return the claims serialized in the access_token but to return them in the response like this:
While I encourage you to store these claims in identity tokens - so that they can be easily read by the client in a completely standard way, it's possible in OpenIddict 1.0 and 2.0 RTM. For that, you have 2 options:
Using a special "public" property (in your authorization controller, where authentication tickets are created):
ticket.SetProperty("custom_claim" + OpenIddictConstants.PropertyTypes.String, user.Id);
Note: OpenIddictConstants.PropertyTypes.String
is a special suffix indicating the authentication property added to the ticket can be exposed as part of the token response. Other constants are available if you prefer returning your claim as a JSON number or a more complex JSON structure.
Using the events model (in Startup.cs):
services.AddOpenIddict()
// Register the OpenIddict core services.
.AddCore(options =>
{
// ...
})
// Register the OpenIddict server handler.
.AddServer(options =>
{
// ...
options.AddEventHandler<OpenIddictServerEvents.ApplyTokenResponse>(
notification =>
{
if (string.IsNullOrEmpty(notification.Context.Error))
{
var principal = notification.Context.Ticket.Principal;
var response = notification.Context.Response;
response["custom_claim"] = principal.FindFirst("your_claim_attached_to_the_principal").Value;
}
return Task.FromResult(OpenIddictServerEventState.Unhandled);
});
})
// Register the OpenIddict validation handler.
.AddValidation();
-
Hello Kevin, I am new to oppeniddict, In the latest version 3.0.1 of oppeniddict this code is obsolete, can you please, show us how to pass custom claims in the current version. I have tried this but it doesn't work: options.AddEventHandler<ApplyTokenResponseContext>(builder => { builder.UseInlineHandler(context => { if (string.IsNullOrEmpty(context.Error)) { var principal = context.Principal; var response = context.Response; response.AddParameter("custom_claim", "test"); } return default; }); }); The custom claim is not recieved by the client app. Feb 10, 2021 at 23:04
-
@user2507201 hi. What you have is fine and should work (and works on my machine). Not sure what's going on. Feb 10, 2021 at 23:20
-
Well, we did it by using the Events property of the OpenIdConnectOptions in the Configure method of the Startup class when you add the Open Id Connect middleware, like this for instance:
Events = new OpenIdConnectEvents
{
OnTicketReceived = n =>
{
//TODO Your logic here to add custom claims via n.Principal.Identities.First().AddClaims();
return Task.CompletedTask;
}
}
Is that an option for your use case?
As an answer from @Pinpoint in his repository of openiddict-samples
I followed this article (in the Implementing the Connect/Token Endpoint
section)..
I figured out from his answer that what I'm trying to do is not standard, that's why it's not so obvious and easy to do.
You need to use JWT and add the custom claims to it so that the client can decode it and get the claims, not send them through the response it self.
-
1Note: don't use JWT as the access token format if you only want to share claims between your authorization server and your client application. Instead, attach the
OpenIdConnectConstants.Destinations.IdentityToken
destination to your claims and addscope=openid
to retrieve an identity token (necessarily a JWT by definition) you'll be able to introspect to retrieve the claims you need. Nov 9, 2016 at 13:19 -
-
-
@Pinpoint sorry I'm not expert in JWT and OAuth, but what's wrong with using JWT ?– DabbasNov 9, 2016 at 13:26
-
1There's nothing wrong. What's wrong is trying to read an access token from the client code (which is not supposed to do that, because it's not the intended audience of the token). Nov 9, 2016 at 13:27