87 Supported Providers / OAuth Playground
500px | amazon | angellist | appnet | asana | assembla | basecamp | bitbucket | bitly | box | buffer | cheddar | coinbase | dailymile | dailymotion | deezer | deviantart | digitalocean | disqus | dropbox | edmodo | elance | eventbrite | evernote | everyplay | eyeem | facebook | feedly | fitbit | flattr | flickr | flowdock | foursquare | freshbooks | geeklist | getpocket | github | gitter | goodreads | google | harvest | heroku | imgur | instagram | jawbone | linkedin | live | mailchimp | meetup | mixcloud | moves | odesk | openstreetmap | paypal | podio | rdio | redbooth | reddit | runkeeper | salesforce | shopify | skyrock | slack | slice | soundcloud | spotify | stackexchange | stocktwits | stormz | strava | stripe | traxo | trello | tripit | tumblr | twitch | twitter | uber | vimeo | vk | withings | wordpress | xing | yahoo | yammer | yandex | zendesk
- Express
- Koa
- Hapi
- Reserved Routes for Grant
- Configuration
- Redirect Url
- Static Overrides
- Dynamic Override
- Quirks
- Custom Providers
- Development Environments
- Response Data
- Typical Flow
- Get User Profile
- Examples
npm install grant-expressvar express = require('express')
var Grant = require('grant-express')
, grant = new Grant({/*configuration see below*/})
var app = express()
// mount grant
app.use(grant)
// other middlewares
app.use(cookieParser())
app.use(session())npm install grant-koavar koa = require('koa')
, mount = require('koa-mount')
// https://github.com/simov/grant/tree/master/example/koa-session
, session = require('any session store')
var Grant = require('grant-koa')
, grant = new Grant({/*configuration see below*/})
var app = koa()
// required: set the session store before mounting grant!
app.keys = ['keys']
app.use(session(...))
// mount grant
app.use(mount(grant))
// other middlewares
app.use(bodyParser())npm install grant-hapivar Hapi = require('hapi')
, yar = require('yar')
var Grant = require('grant-hapi')
, grant = new Grant()
var server = new Hapi.Server()
server.register([{
register: grant,
options: {/*configuration see below*/}
}, {
register: yar,
options: {cookieOptions: {password:'password', isSecure:false}}
}], function (err) {
server.start()
})/connect/:provider/:override?
/connect/:provider/callback{
"server": {
"protocol": "http",
"host": "localhost:3000",
"callback": "/callback",
"transport": "session",
"state": true
},
"provider1": {
"key": "...",
"secret": "...",
"scope": ["scope1", "scope2", ...],
"state": "some state",
"callback": "/provider1/callback"
},
"provider2": {...},
...
}- server - configuration about your server
- protocol - either
httporhttps - host - your server's host name
localhost:3000|dummy.com:5000|mysite.com... - callback - common callback for all providers in your config
/callback|/done... - transport - transport to use to deliver the response data in your final callback
querystring|session(defaults to querystring if omitted) - state - generate 6 digit random state number on each authorization attempt
true|false(OAuth2 only, defaults to false if omitted)
- protocol - either
- provider1 - any supported provider
facebook|twitter...- key -
consumer_keyorclient_idof your app - secret -
consumer_secretorclient_secretof your app - scope - array of OAuth scopes to request
- state - OAuth state string to send
- callback - specific callback to use for this provider (overrides the global one specified under the
serverkey)
- key -
(additionally any of the reserved keys can be overriden for a provider)
For callback/redirect url of your OAuth application you should always use this format
[protocol]://[host]/connect/[provider]/callback
Where protocol and host should match the ones from which you initiate the OAuth flow, and provider is the provider's name from the list of supported providers
This redirect url is used internally by Grant. You will receive the response data from the OAuth flow in the route specified in the callback key of your Grant configuration
You can add arbitrary {object} keys inside your provider's configuration to create sub configurations that override the global settings for that provider
// navigate to /connect/facebook
"facebook": {
"key": "...",
"secret": "...",
// by default request publish permissions
"scope": ["publish_actions", "publish_stream"],
// set specific callback route on your server for this provider
"callback": "/facebook/callback"
// navigate to /connect/facebook/groups
"groups": {
// request only group permissions
"scope": ["user_groups", "friends_groups"]
},
// navigate to /connect/facebook/pages
"pages": {
// request only page permissions
"scope": ["manage_pages"],
// additionally use specific callback route on your server for this override
"callback": "/facebook_pages/callback"
}
}(these custom key names should be different than the reserved ones)
Additionally you can make a POST request to the /connect/:provider/:override? route to override your provider's configuration dynamically on each request
<form action="/connect/facebook" method="post" accept-charset="utf-8">
<input name="state" type="text" value="" />
<input name="scope" type="checkbox" value="read" />
<input name="scope" type="checkbox" value="write" />
<button>submit</button>
</form>Alternatively you can use a GET request with the /connect/:provider/:override? route
app.get('/connect_facebook', function (req, res) {
// generate random state parameter on each authorization attempt
var state = (Math.floor(Math.random() * 999999) + 1)
res.redirect('/connect/facebook?state=' + state)
})- To use the LinkedIn's OAuth2 flow you should use
linkedin2as a provider name, instead oflinkedinwhich is for OAuth1 - For Freshbooks, Shopify and Zendesk you should specify your company's sub domain name through the
subdomainoption - Some providers may employ custom authorization parameters outside of the ones specified in the configuration section. You can pass those custom parameters directly in your configuration, for example: Google -
access_type:'offline', Reddit -duration:'permanent', Trello -expiration:'never', and so on. Refer to the provider's OAuth documentation, and the Grant's OAuth configuration (search forcustom_parameters)
In case you have a private OAuth provider that you don't want to be part of the officially supported ones, you can still define it in your configuration by adding a custom key for it
In this case you have to provide all of the required provider keys by yourself. Take a look at the OAuth configuration to see how the different types of flows are configured
{
"server": {
"protocol": "https",
"host": "mywebsite.com"
},
"custom1": {
"authorize_url": "https://mywebsite.com/authorize",
"access_url": "https://mywebsite.com/token",
"oauth": 2,
"key": "client_id",
"secret": "client_secret",
"scope": ["read", "write"]
}
}You can easily configure different development environments
{
"development": {
"server": {"protocol": "http", "host": "dummy.com:3000"},
"facebook": {
"key": "development OAuth app credentials",
"secret": "development OAuth app credentials"
},
"twitter": {...}, ...
},
"staging": {
"server": {"protocol": "https", "host": "staging.mywebsite.com"},
"facebook": {
"key": "staging OAuth app credentials",
"secret": "staging OAuth app credentials"
},
"twitter": {...}, ...
},
"production": {
"server": {"protocol": "https", "host": "mywebsite.com"},
"facebook": {
"key": "production OAuth app credentials",
"secret": "production OAuth app credentials"
},
"twitter": {...}, ...
}
}Then you can pass the environment flag
$ NODE_ENV=production node app.jsAnd use it in your application
var config = require('./config.json')
var grant = new Grant(config[process.env.NODE_ENV||'development'])The OAuth data is returned as a querystring in your final callback (the one you specify in the callback key of your Grant configuration)
Alternatively the response data can be returned in the session, see the configuration section above and the session transport example
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'
}
}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'
}
}In case of an error, the error key will be populated with the raw error data
{
error:{
some:'error data'
}
}- Register OAuth application on your provider's web site
- For
callback/redirecturl always use this format[protocol]://[host]/connect/[provider]/callback - Create a
config.jsonfile containing
"server": {
"protocol": "https",
"host": "mywebsite.com"
},
"facebook": {
"key": "[APP_ID]",
"secret": "[APP_SECRET]",
"callback": "/handle_facebook_response"
},
"twitter": {
"key": "[CONSUMER_KEY]",
"secret": "[CONSUMER_SECRET]",
"callback": "/handle_twitter_response"
}- Initialize Grant and mount it
// Express
var express = require('express')
, Grant = require('grant-express')
, grant = new Grant(require('./config.json'))
var app = express()
app.use(grant)
// or Koa (see above)
// or Hapi (see above)- 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 complete you will receive the response data in the
/handle_facebook_responseroute for Facebook, and in the/handle_twitter_responseroute for Twitter
(also take a look at the examples)
Once you have your access tokens secured, you can start making authorized requests on behalf of your users. Purest is a great REST API library that supports dozens of REST API providers
For example, you may want to get the user's profile after the OAuth flow has completed
var Purest = require('purest')
, facebook = new Purest({provider:'facebook'})
, twitter = new Purest({provider:'twitter',
key:'[CONSUMER_KEY]', secret:'[CONSUMER_SECRET]'})
facebook.query()
.get('me')
.auth('[ACCESS_TOKEN]')
.request(function (err, res, body) {
// here body is a parsed JSON object containing things such as
// id, first_name, last_name, gender, username and so on
})
twitter.query()
.get('users/show')
.qs({screen_name:'nodejs'})
.auth('[ACCESS_TOKEN]', '[ACCESS_SECRET]')
.request(function (err, res, body) {
// here body is a parsed JSON object containing things such as
// id, screen_name and so on
})MIT