token-endpoint

From IndieWeb
Jump to: navigation, search

A token endpoint is an HTTP endpoint that micropub clients can use to obtain an access token given an authorization code.

Contents

Using a token endpoint service

tokens.indieauth.com is a service you can use if you don't want to immediately build your own token endpoint. You can use this token endpoint in production in order to jump-start the development of your own micropub endpoint.

If you later want to switch to hosting your own token endpoint, you can do so without needing to make any changes to micropub clients since they will re-discover your token endpoint each time you sign in.

Creating a token endpoint

Requests will be made to the token endpoint after the client finishes communicating with the authorization server and obtains an auth code.

A token endpoint must be able to both grant an access token as well as verify an access token.

Granting an Access Token

Access Token Request

Requests to the token endpoint will use the method POST and contain the following parameters:

  • code - The authorization code previously obtained.
  • me - The user's domain name (e.g. http://example.com)
  • redirect_uri - the redirect URI used in the request to obtain the authorization code.
  • client_id - The client ID used in the authorization request.

The token endpoint needs to verify these values and then issue an access token in response. If the token endpoint and authorization endpoint are part of the same system, they can use any proprietary method to communicate.

if the token endpoint and authorization endpoint are different systems, the following method can be used to verify the values. However you will first need to determine which authorization server this user delegates to.

Once you know the authorization endpoint, you can make a x-www-form-encoded POST request with the parameters of this request:

  • code
  • me
  • redirect_uri
  • client_id

If the request is valid (the state, client_id, redirect_uri and code all correspond to the authorization made by the user), the authorization endpoint will return a successful reply in form-encoded or JSON format depending on the HTTP Accept header:

me=https%3A%2F%2Faaronparecki.com&scope=post
{"me": "https://aaronparecki.com", "scope": "post"}

This is how the token endpoint knows which scopes the user authorized

See #Generating an Access Token for implementation notes.

Access Token Response

However you generate an access token, you now have a string ready to reply to the client.

The token response must include three parameters:

  • access_token - The actual access token string.
  • me - The URL of the user.
  • scope - The list of scopes that the token represents.

These should be returned as a www-form-encoded or JSON string in the response body, depending on the HTTP Accept header.

HTTP/1.1 200 OK
Content-Type: application/x-www-form-urlencoded

access_token=XXXXXX&scope=post&me=https%3A%2F%2Faaronparecki.com%2F
HTTP/1.1 200 OK
Content-Type: application/json

{
  "access_token": "XXXXXX",
  "scope": "post",
  "me": https://aaronparecki.com/
}

The reason for returning the "me" value is that the app does not yet know which user the authorization is for, and will use this value to discover the Micropub endpoint to make a request with the access token.

Verifying an Access Token

A micropub endpoint will make a request to the token endpoint to verify that an incoming access token is valid.

The URL of the token server must be known to the micropub endpoint in advance. The bearer token does not contain any information about the server address.
This means that the micropub endpoint dictates the token endpoint that the user links to on his homepage.

The micropub endpoint will make a request like the following:

GET https://tokens.indieauth.com/token
Authorization: Bearer xxxxxxxx

The token endpoint looks at the token in the authorization header and verifies it. How exactly it does this is up to the implementation, such as in the example below of using either a self-encoded token or a database of tokens. After verifying the token is still valid, the token endpoint returns the information about the token such as the user and scope, in form-encoded or JSON format depending on the HTTP Accept header:

HTTP/1.1 200 OK
Content-Type: application/x-www-form-urlencoded

me=https://aaronparecki.com/&
client_id=https://ownyourgram.com&
scope=post
HTTP/1.1 200 OK
Content-Type: application/json

{
  "me": "https://aaronparecki.com/",
  "client_id": https://ownyourgram.com",
  "scope": "post"
}

The micropub endpoint will then inspect these values and determine whether to proceed with the request.

Token-endpoints like https://tokens.indieauth.com that aim to interoperate with different micropub endpoint implementations MUST support this standard mechanism for verifying the token. However, if the token and micropub endpoints are tightly coupled (i.e. you control both implementations and expect them only to talk to each other), this verification can be done internally.


Implementation notes

Generating an Access Token

At this point, your token endpoint is ready to issue an access token to the app.

How exactly you do this is entirely up to you, and depends on which language/framework you are using. There are multiple ways to generate and later verify an access token.

Since your token endpoint will be issuing the token, and your Micropub endpoint will be the only thing that needs to validate tokens, how that works is entirely up to you, and can even be changed later without any ill effects.

Token Database

A trivial way of creating access tokens is to use a database such as MySQL, Postgres, or Redis. Using this method, you would simply generate a long random string, and use that as a unique key, adding in the rest of the information about the token.

At a minimum, you would store the following data along with the token:

  • me
  • client_id
  • scope

While this is a simple way of handling access tokens, you will quickly realize the limitations. Unless you have a way of expiring and re-issuing tokens, your token database will quickly grow in size and may eventually become unwieldy. Of course this also assumes that your website has a database to begin with, which is not necessarily a safe assumption.

Self-Encoded Tokens

Self-encoded tokens are a way to create access tokens that doesn't require storing a string in a database in order to look it up later. By encoding all of the token information into the token itself, the server can verify the token just by inspecting it later. There are many ways to self-encode tokens, again this depends on your preferences.

One way to create self-encoded tokens is to create a JSON-serialized representation of all the data you want to include in the token, and sign the resulting string with a key known only to your server.

The example below is written in PHP, but the idea applies to any language.

  $token_data = array(
    'me' => $_POST['me'],
    'client_id' => $_POST['client_id'],
    'scope' => $auth['scope'],  // Returned by the auth code verification step
    'date_issued' => date('Y-m-d H:i:s'),
    'nonce' => mt_rand(1000000,pow(2,31))
  );

In the example above, we've included a few pieces of information that will be useful when decrypting and verifying the token later.

  • me - Naturally we need to know which user this token corresponds to.
  • client_id - Indicates the app that generated the token.
  • scope - The Micropub endpoint must be able to know what scope the token includes, so it can allow or deny specific requests.
  • date_issued - Included so that we can selectively invalidate tokens created before a certain date if needed. Also servers to add more entropy to the encrypted string.
  • nonce - Adds some extra entropy to the encrypted string.

All of this data is then JSON-encoded and encrypted using the "JWT" package, which results in a string that is the access token.

$token = JWT::encode($token_data, $encryption_key);


IndieWeb Examples

  • Skein provides a token endpoint that issues JWT tokens. [3]
  • silo.pub creates JWT encoded tokens based on authorization from its own auth service.

See Also

Personal tools
Namespaces
Variants
Actions
Recent & Upcoming
Resources
Toolbox