##OAuth2 Flow
Definitions:
Resource Owner: A
User
with access to a desired resource Client: Entity (3rd party) desiring access to a resource held by theResource 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).
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": "[email protected]"
}
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:
- A user clicks a Logout button on a 3rd-party site
- The user is redirected to
https://oauth.deseretdigital.com/{{ site_name }}/logout?continue=https://www.3rdparty.com/user/logout
- 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).