ADFS 2016 OAuth2 OBO with claims for a specific resource RRS feed

  • Question

  • Hi,

    We have build an application and unfortunately the claims required are so numerous that it cannot be contained for all the ecosystem in a single token without it being too big.

    To solve our issue, we wanted to use the OAuth2 OBO pattern and request access-token for a specific resource that would generate claims specific for this resource.

    We added custom claims to our token using the following example: https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/development/custom-id-tokens-in-ad-fs

    It works fine but when we use the resulting access token to "Acquire Token" (manually or with ADAL), the access token don't contain any useful claims.

    We tried to use a Real Relying Party Trust to do this and added DelegationAuthorizationRule using powershell but the access token is not containing any of the claims desired.

    Is there a way in the OBO pattern to get a new access token with custom claims that were not existing in the assertion access token?

    If yes, how is it done?


    Here is the code to retrive the OBO Token we are using..

    public static async Task<TokenResponse> RequestOnBehalfOfToken(string token_endpoint, 
    string resource = null, 
    string client_id = null, 
    string client_secret = null, 
                string access_token = null,
                string scope = null)
    using (HttpClient client = new HttpClient())
    var tokenEndpoint = token_endpoint;
    var accept = "application/json";

    client.DefaultRequestHeaders.Add("Accept", accept);

                    string postBody = string.Empty;
                    if (!string.IsNullOrEmpty(resource)) postBody += string.Format("resource={0}&", resource);
                    if (!string.IsNullOrEmpty(client_id)) postBody += string.Format("client_id={0}&", client_id);
                    if (!string.IsNullOrEmpty(client_secret)) postBody += string.Format("client_secret={0}&", client_secret);
                    if (!string.IsNullOrEmpty(access_token)) postBody += string.Format("assertion={0}&", access_token);
                    postBody += string.Format("grant_type={0}&", "urn:ietf:params:oauth:grant-type:jwt-bearer");
                    postBody += string.Format("requested_token_use={0}&", "on_behalf_of");
                    if (!string.IsNullOrEmpty(scope)) postBody += string.Format("scope={0}&", scope);

                    using (var response = await client.PostAsync(tokenEndpoint, new StringContent(postBody, Encoding.UTF8, "application/x-www-form-urlencoded")))
    if (response.IsSuccessStatusCode)
                            TokenResponse tokenResponse = new TokenResponse();
    var jsonresult = JObject.Parse(response.Content.ReadAsStringAsync().Result);
                            tokenResponse.AccessToken = jsonresult["access_token"]?.ToString();
                            tokenResponse.IdToken = jsonresult["id_token"]?.ToString();
                            tokenResponse.RefreshToken = jsonresult["refresh_token"]?.ToString();
                            tokenResponse.ExpiresIn = jsonresult["expires_in"]?.ToString();
                            tokenResponse.RefrechTokenExpiresIn = jsonresult["refresh_token_expires_in"]?.ToString();
                            tokenResponse.Resource = jsonresult["resource"]?.ToString();
                            tokenResponse.Scope = jsonresult["scope"]?.ToString();
                            tokenResponse.TokenType = jsonresult["token_type"]?.ToString();

                            return tokenResponse;

    return null;

    Friday, April 27, 2018 2:20 PM