Search code examples
authenticationidentityserver4acr

Setting the `acr_values` does not return acr value in `id_token` after authentication


I want to send an acr value to Identity Server 4 during the authentication challenge, and have it returned inside the id_token on the redirect back after login.

From what I have read online, I got the impression that this is a usual way to use acr values.

There is nothing special IS4 needs to do with this acr value, only return it back, so I can use it on the site using the authentication provider.

I do send it successfully by setting thecontext.ProtocolMessage.AcrValues during the call of the RedirectToIdentityProvider callback, and IS4 does get it, but I don't get anything returned inside the id_token.

Do I need to do something special for the acr to be included in the id_token? Should I add it manually somehow? Any code samples would be appreciated.


Solution

  • I would say, you've got a too optimistic impression :)
    Up to date this is rather experimental and optional for the implementation by the particular IdPs. According to the spec: The acr Claim is requested as a Voluntary Claim by this parameter.
    What Identityserver does is the acr_values parameter parsing and limited handling.
    According to their docs:

    Allows passing in additional authentication related information
    IdentityServer special cases the following proprietary acr_values:
    idp:name_of_idp bypasses the login/home realm screen and forwards the user directly to the selected identity provider (if allowed per client configuration)
    tenant:name_of_tenant can be used to pass a tenant name to the login UI

    You can send as many space separated values as you want the following way:
    &acr_values=param1:value1 param2:value2 tenant:name_of_tenant idp:name_of_idp
    and then perform any custom handling on Identityserver side with the following accessor:

    var ctx = _IIdentityServerInteractionService.GetAuthorizationContextAsync(returnUrl);
    IEnumerable<string> acrs = ctx.AcrValues;
    string tenant = ctx.Tenant;
    string idp = ctx.IdP;
    

    When you like to inform the client that their acr_values have been handled, you can add acr like any other user claim:
    First add it to the session in Identityserver when calling

    await HttpContext.SignInAsync(identityServerUser, props);
    // Where identityServerUser can take additional claims. 
    

    After that your custom claim is within the Subject.
    One way to add it to id_token is implementing the IProfileService as described here.

    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        context.AddRequestedClaims(context.Subject.Claims);
        if (context.Caller == "ClaimsProviderIdentityToken")
        {
            var acr = context.Subject.Claims.FirstOrDefault(c=>c.Type=="acr");
            if(acr != null)
                context.IssuedClaims.Add(acr);
        }
        return Task.CompletedTask;
    }
    

    An alternative is to add the claim to the IdentityResources.OpenId scope in the GetIdentityResources() method in startup. openid is the only mandatory scope, so the claim will jump into the token with the default AddRequestedClaims() implementation.