Search code examples
oauth-2.0oauthforgerock

ForgeRock - Invalid Token Exchange


I'm using ForgeRock v7.1.0, running in Docker v3.6.0 on MacOS 11.5.2 (Big Sur).

I'm trying to exchange an OAuth 2.0 access token (subject token) I've already retrieved to be an ID Token (with a JWT Payload) and it's giving me an error every time I call it, specifically related I believe to the subject_token_type parameter.

The steps I am following are as follows:

  1. Generate an OAuth2 access token:
curl --location --request POST 'http://am.example.com:8080/am/oauth2/realms/root/access_token' \
--header 'Authorization: Basic c3RldmU6cGFzc3dvcmQ=' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=user1' \
--data-urlencode 'password=7fYCi0Frhcq5p3gCXGxJ2B' \
--data-urlencode 'scope=cn'

which returns the following:

{
    "access_token": "BS8vVbJ4EEygzdEE3jQH-xsKW9w",
    "scope": "cn",
    "token_type": "Bearer",
    "expires_in": 3599
}
  1. Introspect the token returned to check it's valid:
curl --location --request POST 'http://am.example.com:8080/am/oauth2/realms/root/introspect?token=BS8vVbJ4EEygzdEE3jQH-xsKW9w' \
--header 'Authorization: Basic c3RldmU6cGFzc3dvcmQ='

which returns the following:

{
    "active": true,
    "scope": "cn",
    "realm": "/",
    "client_id": "steve",
    "user_id": "user1",
    "token_type": "Bearer",
    "exp": 1629990663,
    "sub": "(usr!user1)",
    "subname": "user1",
    "iss": "http://am.example.com:8080/am/oauth2",
    "auth_level": 0,
    "authGrantId": "whjnenzHCH96TyaxfuefiOcBfm8",
    "auditTrackingId": "4d353b7e-6cd5-4289-884a-39c50396ed0c-116027"
}
  1. Now this is where I get the error, when I try to exchange the token:
curl --location --request POST 'http://am.example.com:8080/am/oauth2/realms/root/access_token' \
--header 'Authorization: Basic c3RldmU6cGFzc3dvcmQ=' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'subject_token_type=urn:ietf:params:oauth:token-type:access_token' \
--data-urlencode 'subject_token=BS8vVbJ4EEygzdEE3jQH-xsKW9w' \
--data-urlencode 'scope=cn' \
--data-urlencode 'requested_token_type=urn:ietf:params:oauth:token-type:id_token'

which gives me the error:

{
    "error_description": "Invalid token exchange.",
    "error": "invalid_request"
}

If I don't specify the subject_token_type it instead gives me the error:

{
    "error_description": "Subject token type is required.",
    "error": "invalid_request"
}

which leads me to believe either I'm using the wrong type, or something isn't setup properly in my local instance of ForgeRock.

I've looked at the error response possibilities described here: https://backstage.forgerock.com/docs/am/7.1/oauth2-guide/token-exchange-flows.html but it's not that helpful.

Any help gratefully received! Thanks Steve


Solution

  • Doh! Always the way, after posting a question you manage to work it out!

    OK, this is what I needed to do:

    1. Navigate to Realm > [RealmName] > Scripts

    2. Modify the "OAuth 2.0 May Act" Groovy script to be something like this (alter as appropriate):

    import org.forgerock.json.JsonValue
    
    token.setMayAct(
        JsonValue.json(JsonValue.object(
            JsonValue.field("client_id", "steve"), 
            JsonValue.field("sub", "(usr!user1)"))))
    
    1. Validate and then Save the changes

    2. Navigate to Realm > [RealmName] > Services > OAuth 2.0 Provider

    3. Set the two ".. Token May Act Script" dropdowns at the bottom of the "Core" tab to the newly modified "OAuth2 May Act" script

    4. Regenerate access tokens and repeat the Token Exchange call and it should work OK