OAuth 2.0

const createOAuth2Client = require('@arangodb/foxx/oauth2');

The OAuth2 module provides abstractions over OAuth 2.0 providers likeFacebook, GitHub and Google.

Examples

  1. const crypto = require('@arangodb/crypto');
  2. const router = createRouter();
  3. const oauth2 = createOAuth2Client({
  4. // We'll use Facebook for this example
  5. authEndpoint: 'https://www.facebook.com/dialog/oauth',
  6. tokenEndpoint: 'https://graph.facebook.com/oauth/access_token',
  7. activeUserEndpoint: 'https://graph.facebook.com/v2.0/me',
  8. clientId: 'keyboardcat',
  9. clientSecret: 'keyboardcat'
  10. });
  11. module.context.use('/oauth2', router);
  12. // See the user management example for setting up the
  13. // sessions and users objects used in this example
  14. router.use(sessions);
  15. router.post('/auth', function (req, res) {
  16. const csrfToken = crypto.genRandomAlphaNumbers(32);
  17. const url = req.reverse('oauth2_callback', {csrfToken});
  18. const redirect_uri = req.makeAbsolute(url);
  19. // Set CSRF cookie for five minutes
  20. res.cookie('oauth2_csrf_token', csrfToken, {ttl: 60 * 5});
  21. // Redirect to the provider's authorization URL
  22. res.redirect(303, oauth2.getAuthUrl(redirect_uri));
  23. });
  24. router.get('/auth', function (req, res) {
  25. // Some providers pass errors as query parameter
  26. if (req.queryParams.error) {
  27. res.throw(500, `Provider error: ${req.queryParams.error}`)
  28. }
  29. // Make sure CSRF cookie matches the URL
  30. const expectedToken = req.cookie('oauth2_csrf_token');
  31. if (!expectedToken || req.queryParams.csrfToken !== expectedToken) {
  32. res.throw(400, 'CSRF mismatch.');
  33. }
  34. // Make sure the URL contains a grant token
  35. if (!req.queryParams.code) {
  36. res.throw(400, 'Provider did not pass grant token.');
  37. }
  38. // Reconstruct the redirect_uri used for the grant token
  39. const url = req.reverse('oauth2_callback');
  40. const redirect_uri = req.makeAbsolute(url);
  41. // Fetch an access token from the provider
  42. const authData = oauth2.exchangeGrantToken(
  43. req.queryParams.code,
  44. redirect_uri
  45. );
  46. const facebookToken = authData.access_token;
  47. // Fetch the active user's profile info
  48. const profile = oauth2.fetchActiveUser(facebookToken);
  49. const facebookId = profile.id;
  50. // Try to find an existing user with the user ID
  51. // (this requires the users collection)
  52. let user = users.firstExample({facebookId});
  53. if (user) {
  54. // Update the facebookToken if it has changed
  55. if (user.facebookToken !== facebookToken) {
  56. users.update(user, {facebookToken});
  57. }
  58. } else {
  59. // Create a new user document
  60. user = {
  61. username: `fb:${facebookId}`,
  62. facebookId,
  63. facebookToken
  64. }
  65. const meta = users.save(user);
  66. Object.assign(user, meta);
  67. }
  68. // Log the user in (this requires the session middleware)
  69. req.session.uid = user._key;
  70. req.session.facebookToken = authData.facebookToken;
  71. req.sessionStorage.save(req.session);
  72. // Redirect to the default route
  73. res.redirect(303, req.makeAbsolute('/'));
  74. }, 'oauth2_callback')
  75. .queryParam('error', joi.string().optional())
  76. .queryParam('csrfToken', joi.string().optional())
  77. .queryParam('code', joi.string().optional());

Creating an OAuth 2.0 client

createOAuth2Client(options): OAuth2Client

Creates an OAuth 2.0 client.

Arguments

  • options: Object

An object with the following properties:

  • authEndpoint: string

The fully-qualified URL of the provider’sauthorization endpoint.

  • tokenEndpoint: string

The fully-qualified URL of the provider’stoken endpoint.

  • refreshEndpoint: string (optional)

The fully-qualified URL of the provider’srefresh token endpoint.

  • activeUserEndpoint: string (optional)

The fully-qualified URL of the provider’s endpoint for fetchingdetails about the current user.

  • clientId: string

The application’s Client ID (or App ID) for the provider.

  • clientSecret: string

The application’s Client Secret (or App Secret) for the provider.

Returns an OAuth 2.0 client for the given provider.

Setting up OAuth 2.0 for Facebook

If you want to use Facebook as the OAuth 2.0 provider, use the following options:

  • authEndpoint: https://www.facebook.com/dialog/oauth
  • tokenEndpoint: https://graph.facebook.com/oauth/access_token
  • activeUserEndpoint: https://graph.facebook.com/v2.0/meYou also need to obtain a client ID and client secret from Facebook:

  • Create a regular account at Facebook or use anexisting account you own.

  • Visit the Facebook Developers page.
  • Click on Apps in the menu, then select Register as a Developer(the only option) and follow the instructions provided. You may need toverify your account by phone.
  • Click on Apps in the menu, then select Create a New App and followthe instructions provided.
  • Open the app dashboard, then note down the App ID and App Secret.The secret may be hidden by default.
  • Click on Settings, then Advanced and enter one or moreValid OAuth redirect URIs. At least one of them must match yourredirect_uri later. Don’t forget to save your changes.
  • Set the option clientId to the App ID and the option clientSecret_to the _App Secret.

Setting up OAuth 2.0 for GitHub

If you want to use GitHub as the OAuth 2.0 provider, use the following options:

Setting up OAuth 2.0 for Google

If you want to use Google as the OAuth 2.0 provider, use the following options:

  • authEndpoint: https://accounts.google.com/o/oauth2/auth?access_type=offline&scope=profile
  • tokenEndpoint: https://accounts.google.com/o/oauth2/token
  • activeUserEndpoint: https://www.googleapis.com/plus/v1/people/meYou also need to obtain a client ID and client secret from Google:

  • Create a regular account at Google or use anexisting account you own.

  • Visit the Google Developers Console.
  • Click on Create Project, then follow the instructions provided.
  • When your project is ready, open the project dashboard, then click onEnable an API.
  • Enable the Google+ API to allow your app to distinguish between different users.
  • Open the Credentials page and click Create new Client ID, then followthe instructions provided. At least one Authorized Redirect URI must matchyour redirect_uri later. At least one Authorized JavaScript Origin mustmatch your app’s fully-qualified domain.
  • When the Client ID is ready, note down the Client ID and Client secret.
  • Set the option clientId to the Client ID and the option clientSecret_to the _Client secret.

Get the authorization URL

oauth2.getAuthUrl(redirect_uri, args): string

Generates the authorization URL for the authorization endpoint.

Arguments

  • redirect_uri: string

The fully-qualified URL of your application’s OAuth 2.0 callback.

  • args: (optional)

An object with any of the following properties:

  • response_type: string (Default: "code")See RFC 6749.

Returns a fully-qualified URL for the authorization endpoint of the providerby appending the client ID and any additional arguments from args to theauthEndpoint.

Exchange a grant code for an access token

oauth2.exchangeGrantToken(code, redirect_uri)

Exchanges a grant code for an access token.

Performs a POST response to the tokenEndpoint.

Throws an exception if the remote server responds with an empty response body.

Arguments

  • code: string

A grant code returned by the provider’s authorization endpoint.

  • redirect_uri: string

The original callback URL with which the code was requested.

  • args: Object (optional)

An object with any of the following properties:

  • grant_type: string (Default: "authorization_code")

See RFC 6749.

Returns the parsed response object.

Fetch the active user

oauth2.fetchActiveUser(access_token): Object

Fetches details of the active user.

Performs a GET response to the activeUserEndpoint.

Throws an exception if the remote server responds with an empty response body.

Returns null if the activeUserEndpoint is not configured.

Arguments

  • access_token: string

An OAuth 2.0 access token as returned by exchangeGrantToken.

Returns the parsed response object.

Examples

  1. const authData = oauth2.exchangeGrantToken(code, redirect_uri);
  2. const userData = oauth2.fetchActiveUser(authData.access_token);