1
0
Fork 0

Documented OAuth2 app.

This commit is contained in:
Alan Plum 2014-06-24 16:16:52 +02:00
parent c4173ae192
commit 7c17a98ade
1 changed files with 299 additions and 1 deletions

View File

@ -1,3 +1,301 @@
!CHAPTER The OAuth2 Authentication App
WRITEME
The OAuth2 authentication app provides authentication abstractions over OAuth2 providers like Facebook, GitHub and Google. If you want to support additional providers, you can easily define your own.
```js
var providers = Foxx.requireApp('/_oauth2').providers;
```
!SECTION Configuration
The app requires no configuration, but you need to update its *providers* collection with your client ID and client secret for each provider you wish to support.
!SUBSECTION Registering your app with GitHub
If you want to use the *github* provider, you need to obtain a client ID and client secret from GitHub.
1. Create a regular account at [GitHub](https://github.com) or use an existing account you own.
2. Go to [Account Settings > Applications > Register new application](https://github.com/settings/applications/new).
3. Provide an *authorization callback URL*. This must match your *redirect_uri* later.
4. Fill in the other required details and follow the instructions provided.
5. Open the application page, then note down the *Client ID* and *Client Secret*.
6. Update the *github* provider by setting its *clientId* attribute to the *Client ID* and its *clientSecret* attribute to the *Client Secret*. Don't forget to save your changes.
!SUBSECTION Registering your app with Facebook
If you want to use the *facebook* provider, you need to obtain a client ID and client secret from Facebook.
1. Create a regular account at [Facebook](https://www.facebook.com) or use an existing account you own.
2. Visit the [Facebook Developers](https://developers.facebook.com) page.
3. Click on *Apps* in the menu, then select *Register as a Developer* (the only option) and follow the instructions provided. You may need to verify your account by phone.
4. Click on *Apps* in the menu, then select *Create a New App* and follow the instructions provided.
5. Open the app dashboard, then note down the *App ID* and *App Secret*. The secret may be hidden by default.
6. Click on *Settings*, then *Advanced* and enter one or more *Valid OAuth redirect URIs*. At least one of them must match your *redirect_uri* later. Don't forget to save your changes.
7. Update the *facebook* provider by setting its *clientId* attribute to the *App ID* and its *clientSecret* attribute to the *App Secret*. Don't forget to save your changes.
!SUBSECTION Registering your app with Google
If you want to use the *google* provider, you need to obtain a client ID and client secret from Google.
1. Create a regular account at [Google](https://www.google.com) or use an existing account you own.
2. Visit the [Google Developers Console](https://console.developers.google.com).
3. Click on *Create Project*, then follow the instructions provided.
4. When your project is ready, open the project dashboard, then click on *Enable an API*.
5. Enable the *Google+ API* to allow your app to distinguish between different users.
6. Open the *Credentials* page and click *Create new Client ID*, then follow the instructions provided. At least one *Authorized Redirect URI* must match your *redirect_uri* later. At least one *Authorized JavaScript Origin* must match your app's fully-qualified domain.
7. When the Client ID is ready, note down the *Client ID* and *Client secret*.
8. Update the *google* provider by settiing its *clientId* attribute to the *Client ID* and its *clientSecret* attribute to the *Client secret*. Don't forget to save your changes.
!SECTION Exceptions
!SUBSECTION Provider Not Found
Indicates a provider could not be found in the database.
`new providers.errors.ProviderNotFound(providerId)`
Thrown by the provider storage's *delete* and *get* methods if passed a provider ID that does not exist in the database.
@EXAMPLES
```js
try {
providers.get(invalidProviderId);
} catch(err) {
assertTrue(err instanceof providers.errors.ProviderNotFound);
}
```
!SECTION The provider object
Provider objects are instances of a Foxx model with the following attributes:
* *label*: a human-readable identifier for the provider (e.g. *"GitHub"*).
* *authEndpoint*: the fully-qualified URL of the provider's [authorization endpoint](http://tools.ietf.org/html/rfc6749#section-3.1).
* *tokenEndpoint*: the fully-qualified URL of the provider's [token endpoint](http://tools.ietf.org/html/rfc6749#section-3.2).
* *refreshEndpoint* (optional): the fully-qualified URL of the provider's [refresh token](http://tools.ietf.org/html/rfc6749#section-6) endpoint.
* *activeUserEndpoint* (optional): the fully-qualified URL of the provider's endpoint for fetching details about the current user.
* *usernameTemplate* (optional): An underscore.js template for extracting the user's permanent identifier from the user's details. Default: *"<%= id %>"*.
* *clientId*: the client ID of the app registered with the provider.
* *clientSecret*: the client secret of the app registered with the provider.
!SECTION List available OAuth2 providers
Returns a list of OAuth2 providers that can be presented to the front-end.
`providers.list()`
Each item in the list is an object with the following properties:
* *_key*: *_key* of the provider.
* *label*: a human-readable identifier that can be presented to the user.
* *clientId*: the client ID stored for the given provider.
If you wish to exclude providers you don't support in your app, you need to filter the result manually.
@EXAMPLES
```js
var supportedProviders = providers.list().filter(function(obj) {
return Boolean(obj.clientId);
});
```
!SECTION Define a new OAuth2 provider
Creates a new OAuth2 provider with the given data.
`providers.create(data)`
Saves and returns a new instance of the provider model with its attributes set to the properties of the given object.
*Parameter*
* *data*: an arbitrary object, see above.
@EXAMPLES
```js
var provider = providers.create({
_key: 'myoauth2',
label: 'My OAuth2 Provider',
authEndpoint: 'https://example.com/oauth2/authorize',
tokenEndpoint: 'https://example.com/oauth2/access_token',
refreshEndpoint: 'https://example.com/oauth2/access_token',
activeUserEndpoint: 'https://example.com/api/v2/users/me',
usernameTemplate: '<%= user_id %>',
clientId: '1234567890',
clientSecret: 'kEyBoArDcAt'
});
```
!SECTION Fetch an existing OAuth2 provider
Fetches an existing OAuth2 provider from the database.
`providers.get(providerId)`
Throws a *ProviderNotFound* exception if the provider does not exist.
*Parameters*
* *providerId*: the provider's *_key*.
@EXAMPLES
```js
var provider = providers.get('github');
assertTrue(provider.get('_key'), 'github');
```
!SECTION Delete a provider
There are two ways to delete a provider from the database:
* calling the provider storage's *delete* method with a provider's *_key* directly
* telling a provider to delete itself
!SUBSECTION Delete a provider by its ID
Delete a provider with a given ID.
`providers.delete(providerId)`
Attempts to delete the provider with the given *providerId* from the database. If the provider does not exist, a *ProviderNotFound* exception will be thrown. The method always returns *null*.
*Parameter*
* *providerId*: a provider *_key*.
@EXAMPLES
```js
providers.delete('github');
```
!SUBSECTION Tell a provider to delete itself
Delete a provider from the database.
`provider.delete()`
Attempts to delete the provider from the database.
Returns *true* if the provider was deleted successfully.
Returns *false* if the provider already didn't exist.
@EXAMPLES
```js
var provider = providers.get('github');
provider.delete();
```
!SECTION Save a provider
Save a provider to the database.
`provider.save()`
In order to commit changes made to the provider in your code, you need to call this method.
@EXAMPLES
```js
provider.set('clientId', '1234567890');
provider.set('clientSecret', 'kEyBoArDcAt');
provider.save();
```
!SECTION Get the authorization URL of a provider
Generates the authorization URL for the authorization endpoint of the provider.
`provider.getAuthUrl(redirect_uri, args)`
Returns a fully-qualified URL for the authorization endpoint of the provider by appending the provider object's client ID and any additional arguments from *args* to the provider object's *authEndpoint*.
*Parameter*
* *redirect_uri*: the fully-qualified URL of your app's OAuth2 callback.
* *args* (optional): an object with any of the following properties:
* *response_type* (optional): See [RFC 6749](http://tools.ietf.org/html/rfc6749). Default: *"code"*.
!SECTION _getTokenRequest
(Internal.) Generates the token URL and request body for token endpoint of the provider.
`provider._getTokenRequest(code, redirect_uri, args)`
Returns an object with two properties:
* *url*: the fully-qualified URL for the token endpoint.
* *body*: the form-encoded request body for the token endpoint created by appending the provider object's client ID, client secret and any additional arguments from *args* to the provider object's *tokenEndpoint*.
*Parameter*
* *code*: a grant code returned by the provider's authorization endpoint.
* *redirect_uri*: the original callback URL with which the code was requested.
* *args* (optional): an object with any of the following properties:
* *grant_type* (optional): see [RFC 6749](http://tools.ietf.org/html/rfc6749). Default: *"authorization_code"*.
!SECTION Exchange a grant code for an access token
Exchanges a grant code for an access token.
`provider.exchangeGrantToken(code, redirect_uri)`
Performs a *POST* response to the provider object's *tokenEndpoint* and returns the parsed response body.
Throws an exception if the remote server responds with an empty response body.
*Parameter*
* *code*: a grant code returned by the provider's authorization endpoint.
* *redirect_uri*: the original callback URL with which the code was requested.
* *args* (optional): an object with any of the following properties:
* *grant_type* (optional): see [RFC 6749](http://tools.ietf.org/html/rfc6749). Default: *"authorization_code"*.
!SECTION Fetch the active user
Fetches details of the active user.
`provider.fetchActiveUser(access_token)`
Performs a *GET* response to the provider object's *activeUserEndpoint* and returns the parsed response body.
Throws an exception if the remote server responds with an empty response body.
Also throws an exception if the provider object has no *activeUserEndpoint*.
*Parameter*
* *access_token*: an OAuth2 access token as returned by *exchangeGrantToken*.
@EXAMPLES
```js
var authData = provider.exchangeGrantToken(code, redirect_uri);
var userData = provider.fetchActiveUser(authData.access_token);
```
!SECTION Get a user's identifier
Fetches the user's identifier from a user object returned by the provider.
`provider.getUsername(userData)`
Applies the provider's *usernameTemplate* to the given user object.
*Parameter*
* *userData*: the object returned by *getActiveUser*.
@EXAMPLES
```js
var userData = provider.fetchActiveUser(access_token);
var username = provider.getUsername(userData);
```