Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Receive custom parameter in token endpoint and add to access token #1448

Open
OskarKlintrot opened this issue Oct 17, 2024 · 0 comments
Open

Comments

@OskarKlintrot
Copy link

OskarKlintrot commented Oct 17, 2024

Which version of Duende IdentityServer are you using?

v7.0.7

Which version of .NET are you using?

.NET 8

Question

I want to receive a custom parameter in the token endpoint that I then add to the access token. It has nothing to do with the actual authentication so acr seems to be the wrong place as well as parameterized scopes (but I might be wrong), hence why I just want to add a parameter, just like IdentityModel lets me; client.Parameters.Add("device_id", "1234abc");.

Everything looks right in the request:

info: Duende.IdentityServer.Validation.TokenRequestValidator[0]
      Token request validation success, {
        "ClientId": "5NexyxUEWSix1amW2lZ_EpheKPYnI85ziFa8iQ2dYps",
        "ClientName": "no backend",
        "GrantType": "authorization_code",
        "AuthorizationCode": "****B3-1",
        "RefreshToken": "********",
        "Raw": {
          "grant_type": "authorization_code",
          "code": "***REDACTED***",
          "redirect_uri": "https://oauth.pstmn.io/v1/callback",
          "code_verifier": "8XuF_MOggYuW0clIeRamDQANPC1ogdZiAKMRb00mA8Q",
          "device_id": "1234abc"
        }
      }

Then I tried to follow Dynamic Request Validation and Customization like this:

using System.Security.Claims;
using Duende.IdentityServer.Validation;

namespace Identity.Web;

public sealed class DefaultCustomTokenRequestValidator : ICustomTokenRequestValidator
{
    public Task ValidateAsync(CustomTokenRequestValidationContext context)
    {
        if (context.Result.ValidatedRequest.Raw?.Get("device_id") is string deviceId)
        {
            context.Result.ValidatedRequest.ClientClaims.Add(new Claim("device_id", deviceId));
        }

        return Task.CompletedTask;
    }
}

Which does add the claim to the client (might be the wrong place, the device id belongs to a user and not a client) before exiting the method but then it disappears. I can't find it later in my custom IProfileService. Doesn't seem to matter if I request the scope device_id or not either (I added the scope to the client). I assume I'm doing something wrong but I'm out of ideas by now...


Update

If I create a new ClaimsPrincipal and add the claim there I can find it later in the profile service:

public sealed class DefaultCustomTokenRequestValidator : ICustomTokenRequestValidator
{
    public Task ValidateAsync(CustomTokenRequestValidationContext context)
    {
        if (context.Result.ValidatedRequest.GrantType == GrantType.AuthorizationCode
            && context.Result.ValidatedRequest.Raw?.Get("device_id") is string deviceId)
        {
            context.Result.ValidatedRequest.Subject.AddIdentity(new ClaimsIdentity([new Claim("device_id", deviceId)]));
        }

        return Task.CompletedTask;
    }
}

Maybe this is more correct? I can also add it directly to the client (context.Result.ValidatedRequest.Client.Claims.Add(new ClientClaim("device_id", deviceId));) to work with it later in the profile service. Not sure what is most correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants