OpenIdDict custom value in exchange response

265 Views Asked by At

Previously I was using OpenIddict Version 3.1.1. Suddenly faced issue in token validation at API side. Though it was a preview version, I decided to move to latest OpenIddict 4.3.0. Point is in previous version I am getting some custom value like logged in userid, tenentid etc from database when Exchange method is called after login.

[HttpPost("~/connect/token")]

...
...

  else if (request.IsAuthorizationCodeGrantType())
            {
                // Note: the client credentials are automatically validated by OpenIddict:
                // if client_id or client_secret are invalid, this action won't be invoked.

                claimsPrincipal = (await HttpContext.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)).Principal;

                var identity = new ClaimsIdentity(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);

                // Retrieve the user profile corresponding to the authorization code/refresh token.
                var user = await _UserManager.FindByNameAsync(claimsPrincipal.GetClaim(Claims.Subject));

                if (user is null)
                {
                    return Forbid(
                        authenticationSchemes:        OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
                        properties: new AuthenticationProperties(new Dictionary<string, string>
                        {
                            [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
                            [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The token is no longer valid."
                        }));
                }

                // Ensure the user is still allowed to sign in.
                if (!await _SignInManager.CanSignInAsync(user))
                {
                    return Forbid(
                        authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
                        properties: new AuthenticationProperties(new Dictionary<string, string>
                        {
                            [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
                            [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in."
                        }));
                }


                // Subject (sub) is a required field, we use the client id as the subject identifier here.
             
identity.AddClaim(OpenIddictConstants.Claims.Subject, request.ClientId ?? throw new InvalidOperationException());

    **identity.AddClaim(OpenIddictConstants.Claims.Username, user.UserName);
    identity.AddClaim("userid", user.Id);
    identity.AddClaim(OpenIddictConstants.Claims.FamilyName, $"{user.FirstName} {user.LastName}");
    identity.AddClaim("tenant", $"{user.CustomerID}");**

                // Retrieve the claims principal stored in the authorization code
                claimsPrincipal = new ClaimsPrincipal(identity);

                claimsPrincipal.SetScopes(request.GetScopes());

...
...
   // Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens.
            return SignIn(claimsPrincipal, AuthProperties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);

Absolutly getting it at Front End (Front End using Angular OIDC-Client).

But after migrating to OpenIddict 4.3.0, I am not getting these custom claims. As per new changes in OpenIddict 4.3.0 I have also tried

 identity.SetDestinations(static claim => claim.Type switch
                {
                    // Allow the "name" claim to be stored in both the access and identity tokens
                    // when the "profile" scope was granted (by calling principal.SetScopes(...)).
                    Claims.Name when claim.Subject.HasScope(Scopes.Profile)
                        => new[] { Destinations.AccessToken, Destinations.IdentityToken },

                    // Otherwise, only store the claim in the access tokens.
                    _ => new[] { Destinations.AccessToken }
                });

How can I get those custom values in Exchange response?

Previously with OpenIdDict 3.1.1 preview, we were getting

{
    "isAuthenticated": true,
    "userData": {
        "sub": "admin_local", 
# **    "username": "Admin1",
#       "userid": "7bcea554-97d7-47c2-9227-d4a6a71e166b",
#       "family_name": "Admin One",
#       "tenant": "fea5b4d2-928a-4f3e-a218-0cdc31bc22b0",**
        "oi_au_id": "e496a220-2e9d-4cd4-8824-647e5d986505",
        "azp": "portal_clientadmin_local",
        "nonce": "66c5383d5242c179eb76505294a13b7aecxRMEZti",
        "at_hash": "DisPfF50gKQ3PoVh0xqr8Q",
        "oi_tkn_id": "21996ea9-f0a9-475b-81ed-d01d67890af5",
        "aud": "portal_clientadmin_local",
        "exp": 1683798041,
        "iss": "http://192.168.0.11:9004/",
        "iat": 1683796841
    },
    "accessToken": "<<SOME TOKEN VALUE>>",
    "idToken": "<<SOME ID TOKEN VALUE>>",
    "configId": "admin_local"
}

I am expecting same response with newer version OpenIDDict 4.3.0

1

There are 1 best solutions below

0
Kévin Chalet On

In recent versions of the OpenIddict server ASP.NET Core integration, you must use the strongly-typed AuthenticationProperties.Parameters bag. E.g:

var properties = new AuthenticationProperties();
properties.SetParameter("custom_json_object_parameter", new JsonObject
{
    ["property1"] = 42
});

return SignIn(new ClaimsPrincipal(identity), properties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);