1

To get an access_token via clientcredential flow, you call /connect/token like this

curl -X POST https://<identityserver>/connect/token 
-H 'Content-Type: application/x-www-form-urlencoded' 
-d 'grant_type=client_credentials&scope=myscope1'

It doesn't seem like I could customise /connect/token to take custom parameters? I would like to take the custom values from the api and add them to my custom claims via ICustomTokenRequestValidator (https://stackoverflow.com/a/43930786/103264)

001
  • 62,807
  • 94
  • 230
  • 350

2 Answers2

3

You can customize your call using acr_values parameter. For instance, below we take a tenantId value as a parameter, validate it and put into the token as a claim. The call looks like:

curl -d "grant_type=client_credentials&client_id=the-svc-client&client_secret=the-secret&acr_values=tenant:DevStable" https://login.my.site/connect/token

And the vlidator (partially copy&pasted from AuthRequestValidator):

public Task ValidateAsync(CustomTokenRequestValidationContext context)
{
    var request = context.Result.ValidatedRequest;

    if (request.GrantType == OidcConstants.GrantTypes.ClientCredentials)
    {
        //////////////////////////////////////////////////////////
        // check acr_values
        //////////////////////////////////////////////////////////
        var acrValues = request.Raw.Get(OidcConstants.AuthorizeRequest.AcrValues);
        if (acrValues.IsPresent())
        {
            if (acrValues.Length > context.Result.ValidatedRequest.Options
                    .InputLengthRestrictions.AcrValues)
            {
                _logger.LogError("Acr values too long", request);
                context.Result.Error = "Acr values too long";
                context.Result.ErrorDescription = "Invalid acr_values";
                context.Result.IsError = true;
                return Task.CompletedTask;
            }

            var acr = acrValues.FromSpaceSeparatedString().Distinct().ToList();


            //////////////////////////////////////////////////////////
            // check custom acr_values: tenant
            //////////////////////////////////////////////////////////

            string tenant = acr.FirstOrDefault(x => x.StartsWith(nameof(tenant)));

            tenant = tenant?.Substring(nameof(tenant).Length+1);

            if (!tenant.IsNullOrEmpty())
            {
                var tenantInfo = _tenantService.GetTenantInfoAsync(tenant).Result;
                // if tenant is present in request but not in the list, raise error!
                if (tenantInfo == null)
                {
                    _logger.LogError("Requested tenant not found", request);
                    context.Result.Error = "Requested tenant not found";
                    context.Result.ErrorDescription = "Invalid tenant";
                    context.Result.IsError = true;
                }

                context.Result.ValidatedRequest.ClientClaims.Add(
                    new Claim(Constants.TenantIdClaimType, tenant));            
            }
        }
    }
    return Task.CompletedTask;
}
d_f
  • 4,599
  • 2
  • 23
  • 34
  • I ended up adding additional input parameters, then I read the input parameters via context.Result.ValidatedRequest.Raw. But your way is the correct way to do it :) – 001 Jul 23 '19 at 15:56
  • how would you add 2 or more values to acr_values? – 001 Jul 23 '19 at 16:01
  • `var acr = acrValues.FromSpaceSeparatedString().Distinct().ToList();` so: `acr_values=tenant:DevStable nextParam:value` – d_f Jul 23 '19 at 16:10
  • [here](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest) is the spec. it's for auth request, but anyway – d_f Jul 23 '19 at 16:22
  • Would you happen to know how to pass an input parameter via grant type code via IProfileService , ProfileDataRequestContext? – 001 Jul 24 '19 at 16:57
  • never tried. but for code flow you set up all the sequence with the initial request to `Authorization endpoint` and the same `acr_values` can be used there as defined by the spec – d_f Jul 24 '19 at 17:09
0

This worked too using Raw.get(int index). Using index able to retrieve custom values from form-urlencoded parameters as raw

context.Result.ValidatedRequest.Raw.Get(4);
rajquest
  • 535
  • 1
  • 5
  • 10