Authorization Code Grant Flow

Summary

When a client application wants access to the resources of a resource owner, hosted on a resource server, the client application must first obtain an authorization code grant from the authorization server (Agate). The following explains how such a grant is obtained.

Step 1. Authorization

Request

The client application must redirect the user to the Agate authorization page which is:

GET https://agate.example.org/ws/oauth2/authorize?<PARAMETERS>

The following values should/could be passed as parameters:

Parameter

Description

client_id

Client application that will be granted the authorization (required).

response_type

The expected value is: code (required).

scope

Space separated application names (required).

redirect_uri

URL to redirect back to (optional, if not specified default client application redirect URI will be used).

state

Unique string to be passed back upon completion (optional, recommended).

Agate will redirect the “user-agent” (usually a web browser) to a web page where the resource owner can grant or deny the requested authorizations.

Response

If the resource owner accepts to grant the requested authorizations to the client application, then the response will consist of a redirect to the provided redirect_uri with the following request parameters:

Parameter

Description

code

The authorization code.

state

The state parameter value that was provided in the request (if any).

expires_in

Information about the expiration time (in seconds) before the authorization expires.

The redirect request will then look like:

GET https://client.example.org/redirect?code=AUTHORIZATION_CODE&state=STATE&expires_in=7775999

From then, it is the responsibility of the client application to response to this request with a redirect to the relevant client application page.

Errors

The following response errors can be encountered during this step.

GET https://client.example.org/redirect?error=ERROR_CODE&error_description=ERROR_MESSAGE

Parameter

Description

access_denied

When the user refuses to grant the requested authorization.

invalid_scope

The requested scope is not one of the declared resource application scopes.

missing_application_redirect_uri

The client application does not have a default redirect URI. This is a client application definition issue.

invalid_redirect_uri

The provided redirect URI does not starts with the client application’s default redirect URI.

server_error

Other errors.

Step 2. Access Token Issuing

Request

The REST endpoint to be used is:

POST https://agate.example.org/ws/oauth2/token

The form parameters to be sent within the body of the request are:

Parameter

Description

client_id

Client application name (required).

client_secret

Client application secret key (required).

grant_type

The expected value is: authorization_code (required).

code

The authorization code from the Step 1 (required).

redirect_uri

Must match the originally submitted URI (if one was sent).

Response

The response is a JSON object with the following properties:

Property

Description

access_token

The access token. Agate provides signed tokens that implement the JSON Web Token specification.

token_type

What you can do with this token; in the case of Agate the value for this property is bearer.

expires_in

Information about the expiration time (in seconds) before the token expires.

An example of response would be:

{
    "access_token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJlZGl0b3IiLCJpc3MiOiJhZ2F0ZTo1NmZjMzg0MmNjZjJjMWM3ZWM1YzVkMTQiLCJpYXQiOjE0NTk0NTg0NTgsImV4cCI6MTQ1OTQ4NzI1OCwianRpIjoiNTZmZDkxOWFjY2YyYzFjN2VjNWM1ZDE2IiwiYXVkIjpbIm1pY2EiLCJ0b3RvIl0sImNvbnRleHQiOnsic2NvcGVzIjpbIm1pY2EiXSwidXNlciI6eyJuYW1lIjoiSnVsaWUiLCJncm91cHMiOlsibWljYS1lZGl0b3IiXSwiZmlyc3RfbmFtZSI6Ikp1bGllIn19fQ.PqlLSZegdPLM2byp0jsgWV-XM3Xed8DP4I03kbUUEeo",
    "token_type": "bearer",
    "expires_in": 28799
}

Being a JSON Web Token (JWT), the access token can be decoded. There are three parts in a JWT: the header, the payload and the signature. This could give for example:

{
    "alg": "HS256"
}
.
{
    "sub": "editor",
    "iss": "agate:56fc3842ccf2c1c7ec5c5d14",
    "iat": 1459458458,
    "exp": 1459487258,
    "jti": "56fd919accf2c1c7ec5c5d16",
    "aud": [
        "mica",
        "client_app"
    ],
    "context": {
        "scopes": [
            "mica"
        ],
        "user": {
            "name": "Julie LaTendresse",
            "groups": [
                "mica-editor"
            ],
            "first_name": "Julie",
            "last_name": "Latendresse"
        }
    }
}
.
[signature]

The JWT payload contains some basic details on the subject (in addition to the standard claims). These are available in the context object (which is a claim specific to Agate). The properties of the context are:

Property

Description

user.name

The user full name for display.

user.first_name

The user first name (if any).

user.last_name

The user last name (if any).

user.groups

The user groups.

scopes

Reminder of the scopes associated to the authorization code grant.

Note that this step can be repeated as many times as necessary, using the same authorization code that was granted at step 1.

Errors

When an error is encountered during this step, the JSON object returned contains the description of the error, for example:

{
    "error_description":"Authorization with code '3b1d664fb09407972d4c212081789c6f' does not exist",
    "error":"NoSuchAuthorizationException"
}

Step 3. Resource Access

The client application will use the access token as a bearer of resource owner identity to get the resource from the resource server. How the access token should be passed to the resource application is out of the concern of Agate.

Most common practice (this is the case for Opal and Mica) is that the access token is placed in the headers of the HTTP request issued by the client application on the resource server. This can be expressed as a curl command:

curl -X GET --header "Authorization: Bearer ACCESS_TOKEN" http://resource.example.org/some/path

Step 4. Access Token Validation

The resource server has received an access token from a client application. Although the access token delivered by Agate is a JWT that contains in its payload all the basic information (subject identification, authorized scopes), it is the responsibility of the resource application to validate this token.

This can be achieved by requesting the REST end point:

GET https://agate.example.org/ws/ticket/ACCESS_TOKEN/_validate

Note that the resource application must identifies itself in this request. This can be expressed as a curl command:

curl -X GET --header "X-App-Auth: Basic `echo -n "APPLICATION_NAME:APPLICATION_KEY" | base64`" https://agate.example.org/ws/ticket/ACCESS_TOKEN/_validate

The expected response code is 200 (OK), without a response body.

Possible validation errors are:

  • application could not be identified,

  • access token signature verification has failed,

  • access token issuer is not the current Agate instance,

  • application is not part of the audience of the access token,

  • access token has expired,

  • user is not active any more.