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:

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.