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_key
andconsumer_secret
orclient_id
andclient_secret
.redirect
orcallback
URL 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
redirect
URL of your OAuth application always use this format:[protocol]://[host]/connect/[provider]/callback
-
Create a
authentication.json
in 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/facebook
to initiate the OAuth flow for Facebook, or navigate to/connect/twitter
to initiate the OAuth flow for Twitter. -
Once the OAuth flow is completed you will receive the response data in the
/handle_facebook_response
route for Facebook, and in the/handle_twitter_response
route 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_key
orclient_id
of your application.secret
(string):consumer_secret
orclient_secret
of 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_params
option:
{
"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
23andme
500px
acton
acuityscheduling
aha
amazon
angellist
appnet
asana
assembla
axosoft
basecamp
beatport
beatsmusic
bitbucket
bitly
box
buffer
campaignmonitor
cheddar
clio
codeplex
coinbase
concur
constantcontact
copy
coursera
dailymile
dailymotion
deezer
delivery
deputy
deviantart
digitalocean
discogs
disqus
dribbble
dropbox
echosign
ecwid
edmodo
egnyte
elance
etsy
eventbrite
evernote
everyplay
eyeem
facebook
familysearch
feedly
fitbit
flattr
flickr
flowdock
fluidsurveys
formstack
foursquare
freeagent
freshbooks
geeklist
getbase
getpocket
gitbook
github
gitlab
gitter
goodreads
google
groove
gumroad
harvest
hellosign
heroku
imgur
infusionsoft
instagram
intuit
jawbone
jumplead
kakao
letsfreckle
linkedin
live
mailchimp
mailup
mapmyfitness
meetup
mixcloud
moves
moxtra
myob
odesk
openstreetmap
optimizely
paypal
plurk
podio
producteev
producthunt
projectplace
pushbullet
ravelry
rdio
redbooth
reddit
runkeeper
salesforce
shoeboxed
shopify
skyrock
slack
slice
smartsheet
socialpilot
socrata
soundcloud
spotify
square
stackexchange
stocktwits
stormz
strava
stripe
surveygizmo
surveymonkey
thingiverse
ticketbud
todoist
trakt
traxo
trello
tripit
tumblr
twitch
twitter
uber
underarmour
upwork
uservoice
vend
verticalresponse
vimeo
visualstudio
vk
weekdone
weibo
withings
wordpress
wrike
xero
xing
yahoo
yammer
yandex
zendesk
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"
]
}
}
}