Skip to content

Instantly share code, notes, and snippets.

@ev0rtex
Last active January 21, 2016 16:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ev0rtex/e12195940b766726701f to your computer and use it in GitHub Desktop.
Save ev0rtex/e12195940b766726701f to your computer and use it in GitHub Desktop.
DDM OAuth2 API

DDM OAuth2 API

##OAuth2 Flow

Definitions:

Resource Owner: A User with access to a desired resource Client: Entity (3rd party) desiring access to a resource held by the Resource Owner Authorization Server: OAuth2 API server capable of granting access to resources Resource Server: The server with the desired resource(s) for which access is desired

Sequence:

participant Resource Owner (User) as RO
participant Client as C
participant Authorization Server as AS
participant Resource Server as RS

RO->C: User action\n(e.g. click "Sign in with...")
C-->RO: Send to Authorization Server\n(popup, link, redirect)
RO->AS: Login & Consent
AS-->RO: Redirect to Client's "redirect_url"
RO-->C: Authorization Code Response
C->AS: Exchange Code for Access Token
AS-->C: Access Token (+Refresh Token)
C->RS: Call API with Access Token
RS-->C: Response with Data

##API

API URL: https://oauth.deseretdigital.com/{{ site_name }}

Endpoint Description
/authorize The OAuth authorization endpoint - you will direct the user here initially
/token The Token endpoint used by your server to get access tokens

###/authorize

Parameter Explanation
response_type This should always be the value code. We only support the Authorization Code grant type as it is the most secure.
client_id This will be given to you when we set you up in our system.
redirect_uri You must provide this to us. It is the URI where the user will be redirected after authorization. You will get the Authorization Code as a URL parameter.
scope (Not Yet Implemented) The scope(s) you wish to have access to. To be implemented in a future release.
state This is a random code that you should generate for the request. You should save this temporarily and verify the state parameter given in the URL when the user is sent back to your redirect_uri. This is to prevent CSRF (Cross-Site Request Forgery).

If the user authorizes access they will be redirected to the redirect_uri endpoint with a code parameter and (if given in the /authorize request) the state parameter you passed so you can verify that no CSRF has occurred. The code parameter is an authorization code that can be exchanged for an access token by calling the /token endpoint documented below. It is a one-time use code with a short expiry time of 30 seconds which should be more than adequate for a server-side implementation to make the /token request.

###/token

Parameter Explanation
grant_type Use the value authorization_code here.
code This is the Authorization Code you got in the code parameter at your callback URL (redirect_uri).
client_id The client ID given to you when we set you up in our system.
client_secret Given to you when we set you up. This is akin to a password and should be heavily guarded as any password would be.

NOTE: In a future release I will be removing this requirement in favor of a signature only for much better security.

This endpoint currently requires a Signature header to be given with the request that signs the request body using the separate client_key value that I have given you at the time we set you up in our system. In a future release the client_key value will no longer be needed as I am planning to remove the client_secret parameter from the above list and instead have you sign the request using the single client_secret value. The Signature header can be obtained like this (PHP):

$params = [
    'grant_type' => 'authorization_code',
    'code' => $code,
    'client_id' => CLIENT_ID,
    'client_secret' => CLIENT_SECRET,
];
$req = http_build_query($params);
$sig = hash_hmac('sha256', $req, CLIENT_KEY);

and then (if using cURL):

curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/x-www-form-urlencoded',
    'Signature: ' . $sig,
));

I have built my OAuth2 implementation using JavaScript. If you have also used JavaScript you may find it useful to see how I do the signature using JS and Node.js with the crypto library:

response.set(
    'Signature',
    crypto.createHmac('sha256', clientKey).update(body).digest('hex')
);

The response to your request will contain the following parameters:

Parameter Description
token_type This will always be bearer
access_token This is the access token you will need for any API requests you make (currently the only API endpoint is /api/users). It expires after 24 hours and will thereafter need to be refreshed with the refreshToken.
expires_in Time until the access token will expire (seconds).
refresh_token This token is used to obtain a new accessToken when the one you last used has expired. This will expire after 14 days and then you'll have to direct the user through the OAuth flow (/authorize) again to obtain new credentials.
access_secret Not currently used.

####Refreshing the token

In order to obtain a new accessToken using the refreshToken you were given you need to make another call to the /token endpoint but with parameters set as below:

Parameter Description
grant_type Use the value refresh_token here.
client_id See above.
client_secret See above.
refresh_token The refreshToken you were given previously.

The response you get from the API will have the same parameters as shown above when you make a /token request (including a new refreshToken that you should save for the next time you need to refresh).

Other Endpoints

There are some useful API endpoints implemented on the DDM OAuth2 server that reside outside the OAuth2 protocol flow.

API URL (same as above): https://oauth.deseretdigital.com/{{ site_name }}

###/api/users For now this simply serves up the email address of the user who has authorized access to their account. In order to access this API endpoint you need to pass the access_token you obtained through the OAuth2 flow in an Authorization header. This header would need to include the bearer keyword to indicate that it is an OAuth bearer token. An example might look like this:

Authorization: bearer e09afbd5a5da5c955a90de627ce8948a45d632a6

A corresponding response body would look like this:

{
  "email": "user@example.tld"
}

NOTE: I have received requests for more information to be provided in the response here. We have some challenges with that due to the way our servers communicate internally so we can't provide more than the email address for the time being but we do plan to support more in the future.

###/logout This is a client-facing endpoint that can be used to destroy a user's login session with our OAuth server. When a user clicks on a logout button it would be advisable to do a quick redirect to this endpoint to log them out of their account on the OAuth server as well so that when they return they will need to sign in again. This endpoint will accept a parameter as follows:

Parameter Description
continue This is a URL to redirect the user to once their session has been destroyed.

An implementation of this logout flow might work like this:

  1. A user clicks a Logout button on a 3rd-party site
  2. The user is redirected to https://oauth.deseretdigital.com/{{ site_name }}/logout?continue=https://www.3rdparty.com/user/logout
  3. The user's session gets destroyed on the DDM OAuth2 server and the user is then redirected to the URL in the continue parameter (https://www.3rdparty.com/user/logout in this example).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment