18 KiB
Executable File
Authentication
The Strapi OAuth hook allows you to easily connect your application to 150+ providers.
Overview
OAuth is used by the web service providers to provide access to user resources in a secure manner. Each developer using this service must create an OAuth application and, after, requires the user to grant access to it.
As a part of the OAuth flow, the user is redirected to the web service's server, to log in (this step can be omitted if the user has already logged in).
Once the user agrees to use the application, he's redirected back to your website with the generated access token. We need to store that token and send it along, with each request made, to the service on behalf of the user.
Strapi enables you to add support for multiple providers through a simple and straightforward configuration data structure. This allows you to easily implement login forms with support for multiple options so your users can log in using different service providers.
The minimum required information to configure OAuth properly is:
consumer_keyandconsumer_secretorclient_idandclient_secret.redirectorcallbackURL pointing back to your website.
Strapi requires that the redirect/callback URL specified in your OAuth application should have this format:
[protocol]://[host]/connect/[provider]/callback
Typical flow
-
Register OAuth application on your provider's web site.
-
For
redirectURL of your OAuth application always use this format:[protocol]://[host]/connect/[provider]/callback -
Create a
authentication.jsonin each environment (since you'll use different credentials) file containing:
{
"authentication": {
"facebook": {
"key": "[CLIENT_ID]",
"secret": "[CLIENT_SECRET]",
"callback": "/handle_facebook_response"
},
"twitter": {
"key": "[CONSUMER_KEY]",
"secret": "[CONSUMER_SECRET]",
"callback": "/handle_twitter_response"
}
}
}
-
Navigate to
/connect/facebookto initiate the OAuth flow for Facebook, or navigate to/connect/twitterto initiate the OAuth flow for Twitter. -
Once the OAuth flow is completed you will receive the response data in the
/handle_facebook_responseroute for Facebook, and in the/handle_twitter_responseroute for Twitter.
Configuration
Configuration:
- Key:
authentication - Environment:
development - Location:
./config/environments/development/authentication.json - Type:
object
Example:
{
"authentication": {
"facebook": {
"key": "[APP_ID]",
"secret": "[APP_SECRET]",
"callback": "/handle_facebook_callback"
},
"twitter": {
"key": "[CONSUMER_KEY]",
"secret": "[CONSUMER_SECRET]",
"callback": "/handle_twitter_callback"
}
}
}
Options (for each provider):
key(string):consumer_keyorclient_idof your application.secret(string):consumer_secretorclient_secretof your application.scope(array): Array of OAuth scopes to requestcallback(string): Specific callback to use for this provider.custom_params(object): Some providers may employ custom authorization parameters outside of the ones specified in the configuration section. You can pass those custom parameters using thecustom_paramsoption:
{
"authentication": {
"google": {
"custom_params": {
"access_type": "offline"
}
},
"reddit": {
"custom_params": {
"duration": "permanent"
}
},
"trello": {
"custom_params": {
"name": "my app",
"expiration": "never"
}
}
}
}
Usage
Each key is a provider that you'll want to configure and use in your application. You want to configure and use both Twitter and Facebook. The key and the secret keys are required and they must contain the credentials for your OAuth application.
The callback key is the route on your server where you want to receive the access tokens after the OAuth flow is completed.
First, you need to register your callback route for each provider. Keeping the previous example, it should look like this:
{
"routes": {
"GET /handle_facebook_callback": {
"controller": "User",
"action": "registerFacebook",
"policies": []
},
"GET /handle_twitter_callback": {
"controller": "User",
"action": "registerTwitter",
"policies": []
}
}
}
Then, you need to create an action for the route. Here is a simple example:
// Action to handle Facebook registration in the `User` controller.
registerFacebook: function * () {
this.body = JSON.stringify(this.query, null, 2)
},
// Action to handle Twitter registration in the `User` controller.
registerTwitter: function * () {
this.body = JSON.stringify(this.query, null, 2)
}
Specific configuration options
There are a few more configuration options that you might want to use.
scope
Some service providers allow us to configure the permissions that our application will request from the user. These permissions are set inside the scope key of the configuration:
{
"authentication": {
"facebook": {
"key": "[APP_ID]",
"secret": "[APP_SECRET]",
"callback": "/handle_facebook_callback",
"scope": [
"user_groups",
"user_likes"
]
}
}
}
In this case, the user will be asked to grant access to its groups and likes on Facebook.
state
Some providers require us to send a CORS token to ensure that the flow was initiated from our own server. The state key in the configuration can be used for that purpose:
{
"authentication": {
"facebook": {
"key": "[APP_ID]",
"secret": "[APP_SECRET]",
"callback": "/handle_facebook_callback",
"scope": [
"user_groups",
"user_likes"
],
"state": "very secret"
}
}
}
Sandbox Redirect URI
Very rarely you may need to override the default redirect_uri that Strapi generates for you.
For example Feedly supports only http://localhost as redirect URL of their Sandbox OAuth application, and it won't allow the http://localhost/connect/feedly/callback path:
{
"authentication": {
"feedly": {
"redirect_uri": "http://localhost"
}
}
}
In case you override the redirect_uri in your config, you'll have to redirect the user to the [protocol]://[host]/connect/[provider]/callback route that Strapi uses to execute the last step of the OAuth flow using sessions and this.redirect.
After that you will receive the results from the OAuth flow inside the route specified in the callback key of your configuration.
Quirks
Subdomain
Some providers require you to set your company name as a subdomain in the OAuth URLs. For example for Freshbooks, Shopify, Vend and Zendesk you can set that value through the subdomain option:
{
"authentication": {
"shopify": {
"subdomain": "mycompany"
}
}
}
Then Strapi will generate the correct OAuth URLs:
{
"authentication": {
"shopify": {
"authorize_url": "https://mycompany.myshopify.com/admin/oauth/authorize",
"access_url": "https://mycompany.myshopify.com/admin/oauth/access_token"
}
}
}
Alternatively you can override the entire request_url, authorize_url and access_url in your configuration.
Sandbox URLs
Some providers may have sandbox URLs for testing. To use them just override the entire request_url, authorize_url and access_url in your configuration:
{
"authentication": {
"paypal": {
"authorize_url": "https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize",
"access_url": "https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice"
},
"evernote": {
"request_url": "https://sandbox.evernote.com/oauth",
"authorize_url": "https://sandbox.evernote.com/OAuth.action",
"access_url": "https://sandbox.evernote.com/oauth"
}
}
}
Flickr, Optimizely
Flickr uses a custom authorization parameter to pass its scopes called perms, and Optimizely uses scopes. However you should use the regular scope option in your configuration:
{
"authentication": {
"flickr": {
"scope": ["write"]
}
"optimizely": {
"scope": ["all"]
}
}
}
SurveyMonkey
For SurveyMonkey set your Mashery user name as key and your application key as api_key:
{
"authentication": {
"surveymonkey": {
"key": "[MASHERY_USER_NAME]",
"secret": "[CLIENT_SECRET]",
"api_key": "[CLIENT_ID]"
}
}
}
Fitbit, LinkedIn, ProjectPlace
Initially these providers supported only OAuth1, so the fitbit and linkedin names are used for that. To use their OAuth2 flow append 2 at the end of their names:
{
"authentication": {
"fitbit2": {},
"linkedin2": {},
"projectplace2": {}
}
}
Response Data
The OAuth response data is returned as a querystring in your final callback - the one you specify in the callback key of your Strapi configuration.
OAuth1
For OAuth1 the access_token and the access_secret are accessible directly, raw contains the raw response data:
{
access_token: '...',
access_secret: '...',
raw: {
oauth_token: '...',
oauth_token_secret: '...',
some: 'other data'
}
}
OAuth2
For OAuth2 the access_token and the refresh_token (if present) are accessible directly, raw contains the raw response data:
{
access_token: '...',
refresh_token: '...',
raw: {
access_token: '...',
refresh_token: '...',
some: 'other data'
}
}
Error
In case of an error, the error key will be populated with the raw error data:
{
error: {
some: 'error data'
}
}
Bypass unauthorized localhost
You should keep in mind that not all web service providers allow localhosts as a value for the OAuth application redirect URL. The easiest way to get around this is to add a new entry to your host's file like this:
127.0.0.1 mywebsite.com
If you need to use a different URL than your localhost you also need to override your server config for the authentication key like this:
{
"authentication": {
"server": {
"protocol": "http",
"host": "mywebsite.com:3000"
},
"facebook": {
"key": "[APP_ID]",
"secret": "[APP_SECRET]",
"callback": "/handle_facebook_callback",
"scope": [
"user_groups",
"user_likes"
]
},
"twitter": {
"key": "[CONSUMER_KEY]",
"secret": "[CONSUMER_SECRET]",
"callback": "/handle_twitter_callback"
}
}
}
The server key is required and it contains the host name of your server and the protocol you're running your site on.
Providers
Supported providers
23andme500pxactonacuityschedulingahaamazonangellistappnetasanaassemblaaxosoftbasecampbeatportbeatsmusicbitbucketbitlyboxbuffercampaignmonitorcheddarcliocodeplexcoinbaseconcurconstantcontactcopycourseradailymiledailymotiondeezerdeliverydeputydeviantartdigitaloceandiscogsdisqusdribbbledropboxechosignecwidedmodoegnyteelanceetsyeventbriteevernoteeveryplayeyeemfacebookfamilysearchfeedlyfitbitflattrflickrflowdockfluidsurveysformstackfoursquarefreeagentfreshbooksgeeklistgetbasegetpocketgitbookgithubgitlabgittergoodreadsgooglegroovegumroadharvesthellosignherokuimgurinfusionsoftinstagramintuitjawbonejumpleadkakaoletsfrecklelinkedinlivemailchimpmailupmapmyfitnessmeetupmixcloudmovesmoxtramyobodeskopenstreetmapoptimizelypaypalplurkpodioproducteevproducthuntprojectplacepushbulletravelryrdioredboothredditrunkeepersalesforceshoeboxedshopifyskyrockslackslicesmartsheetsocialpilotsocratasoundcloudspotifysquarestackexchangestocktwitsstormzstravastripesurveygizmosurveymonkeythingiverseticketbudtodoisttrakttraxotrellotripittumblrtwitchtwitteruberunderarmourupworkuservoicevendverticalresponsevimeovisualstudiovkweekdoneweibowithingswordpresswrikexeroxingyahooyammeryandexzendesk
Custom providers
In case you have a private OAuth provider that is not part of the officially supported ones, you can define it in your configuration by adding a custom key for it.
In this case you have to specify all of the required provider keys by yourself:
{
"authentication": {
"mywebsite": {
"authorize_url": "https://mywebsite.com/authorize",
"access_url": "https://mywebsite.com/token",
"oauth": 2,
"key": "[CLIENT_ID]",
"secret": "[CLIENT_SECRET]",
"scope": [
"read",
"write"
]
}
}
}