Auth solution (password, facebook, & more) for your node.js Connect & Express apps
npm install everyautheveryauth
==========
Authentication and authorization (password, facebook, & more) for your node.js Connect and Express apps.
There is a NodeTuts screencast of everyauth here
There is also a Google Groups (recently created)
here to post questions and discuss
potential ideas and extensions to the library.
So far, everyauth enables you to login via:
| Authenticate Via | Credits |
|---|---|
| Password | |
| | |
| | |
| | |
| | RocketLabs Development |
| | |
| | Torgeir |
Tumblr | |
| | Danny Amey |
| | |
| | |
| | |
| | |
| | slickplaid |
Vimeo | slickplaid |
| (Basecamp, Highrise, Backpack, Campfire) | |
| | Alfred Nerstu |
| | |
| | Kenan Shifflett |
| | Christoph Giesel |
| | Alexey Simonenko |
| | Alexey Gordeyev |
| | Rodolphe Stoclin |
| | Andrew Kramolisch |
TripIt | Damian Krzeminski |
| | Danny Amey |
| | Chris Leishman |
| | ufssf |
Mailchimp | Winfred Nadeau |
| | Eduard Baun |
| | Jeff Zabel from Datahero |
| | Jeff Zabel from Datahero |
| | |
| | RocketLabs Development, Andrew Mee, Brian Noguchi |
| LDAP / ActiveDirectory | Marek Obuchowicz from Korekontrol |
| Windows Azure Access Control Service (ACS) | Dario Renzulli, Juan Pablo Garcia, Matias Woloski from Southworks |
everyauth is:
- Modular - We have you covered with Facebook and Twitter
OAuth logins, basic login/password support, and modules
coming soon for beta invitation support and more.
- Easily Configurable - everyauth was built with powerful
configuration needs in mind. Configure an authorization strategy
in a straightforward, easy-to-read & easy-to-write approach,
with as much granularity as you want over the steps and
logic of your authorization strategy.
- Idiomatic - The syntax for configuring and extending your authorization strategies are
idiomatic and chainable.
Incorporate everyauth into your express app in just 2 easy steps.
1. Choose and Configure Auth Strategies - Find the authentication strategy
you desire in one of the sections below. Follow the configuration
instructions.
2. Add the Middleware to Express
``javascript
var everyauth = require('everyauth');
// Step 1 code goes here
// Step 2 code
var express = require('express');
var app = express();
app
.use(express.bodyParser())
.use(express.cookieParser('mr ripley'))
.use(express.session())
.use(everyauth.middleware(app));
`
There is an example application at ./example
To run it:
$ cd example
$ node server.js
Important - Some OAuth Providers do not allow callbacks to localhost, so you will need to create a localhostlocal.host
alias called . Make sure you set up your /etc/hosts so that 127.0.0.1 is also
associated with 'local.host'. So inside your /etc/hosts file, one of the lines will look like:
127.0.0.1 localhost local.host
Then point your browser to http://local.host:3000
$ npm install everyauth --dev
Then, update test/creds.js with credentials that the integration tests use to
login to each 3rd party service.
$ make test
If you are using express or connect, then everyauth
provides an easy way to access the user as:
- req.user from your app servereveryauth.user
- via the everyauth helper accessible from your express views.user
- as a helper accessible from your express views
To access the user, configure everyauth.everymodule.findUserById andeveryauth.everymodule.userPkey
optionally .
For example, using mongoose:
`javascript`
everyauth.everymodule.findUserById( function (userId, callback) {
User.findById(userId, callback);
// callback has the signature, function (err, user) {...}
});
If you need access to the request object the function can have three arguments:
`javascript
everyauth.everymodule.findUserById( function (req, userId, callback) {
// use the request in some way ...
// callback has the signature, function (err, user) {...}
});
`
Once you have configured this method, you now have access to the user object
that was fetched anywhere in your server app code as req.user. For instance:
`javascript
var app = require('express').createServer()
// Configure your app
app.get('/', function (req, res) {
console.log(req.user); // FTW!
res.render('home');
});
`
Moreover, you can access the user in your views as everyauth.user or as user.
//- Inside ./views/home.jade
span.user-id= everyauth.user.name
#user-id= user.id
everyauth assumes that you store your users with an id property. If not --user.uid
e.g, if you adopt the convention over user.id -- then just makeeveryauth.everymodule.userPkey
sure to configure the parameter:
`javascript`
everyauth.everymodule.userPkey('uid');
If you are using express, everyauth comes with some useful dynamic helpers.
To enable them:
`javascript
var express = require('express')
, everyauth = require('everyauth')
, app = express.createServer();
everyauth.helpExpress(app);
`
Then, from within your views, you will have access to the following helpers methods
attached to the helper, everyauth:
- everyauth.loggedIneveryauth.user
- - the User document associated with the sessioneveryauth.facebook
- - The is equivalent to what is stored at req.session.auth.facebook, everyauth.facebook.user
so you can do things like ...
- - returns the user json provided from the OAuth provider.everyauth.facebook.accessToken
- - returns the access_token provided from the OAuth providereveryauth.twitter.user
for authorized API calls on behalf of the user.
- And you also get this pattern for other modules - e.g., , everyauth.github.user
, etc.
You also get access to the view helper
- user - the same as everyauth.user above
As an example of how you would use these, consider the following ./views/user.jade jade template:
.user-id
.label User Id
.value #{user.id}
.facebook-id
.label User Facebook Id
.value #{everyauth.facebook.user.id}
If you already have an express helper named user, then you can configureeveryauth to use a different helper name to access the user object thatuserAlias
everyauth manages. To do so, leverage the option foreveryauth.helpExpress:
`javascript`
everyauth.helpExpress(app, { userAlias: '__user__' });
Then, you could access the user object in your view with the helper __user__user
instead of the default helper . So you can compare with the default use
of helpers given previously, the alternative leveraging userAlias would look like:
.user-id
.label User Id
.value #{__user__.id}
.facebook-id
.label User Facebook Id
.value #{everyauth.facebook.user.id}
everyauth also provides convenience methods on the ServerRequest instance req. req
From any scope that has access to , you get the following convenience getters and methods:
- req.loggedIn - a Boolean getter that tells you if the request is by a logged in userreq.user
- - the User document associated with the sessionreq.logout()
- - clears the session of your auth data
If you integrate everyauth with connect, then everyauth automaticallylogoutPath
sets up a at GET /logout for your app. It also
sets a default handler for your logout route that clears your session
of auth information and redirects them to '/'.
To over-write the logout path:
`javascript`
everyauth.everymodule.logoutPath('/bye');
To over-write the logout redirect path:
`javascript`
everyauth.everymodule.logoutRedirectPath('/navigate/to/after/logout');
To over-write the logout handler:
`javascript`
everyauth.everymodule.handleLogout( function (req, res) {
// Put you extra logic here
req.logout(); // The logout method is added for you by everyauth, too
// And/or put your extra logic here
this.redirect(res, this.logoutRedirectPath());
});
You may want your own callback that decides where to send a user after login or registration. One way of doing this is with the respondToLoginSucceed and respondToRegistrationSucceed methods. This assumes that you have set a .redirectTo property on your req.session object:
`javascript`
everyauth.password
.respondToLoginSucceed( function (res, user, data) {
if (user) {
this.redirect(res, data.session.redirectTo)
}
})
.respondToRegistrationSucceed( function (res, user, data) {
this.redirect(res, data.session.redirectTo)
})
If you are using express and want your redirects to be subject to express
redirect mapping), you can
overwrite redirect method employed by everyauth.
`javascript`
everyauth.everymodule
.performRedirect( function (res, location) {
res.redirect(location, 303);
});
A newly defined method will be used by everyauth to perform all redirects.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');
everyauth.facebook
.appId('YOUR APP ID HERE')
.appSecret('YOUR APP SECRET HERE')
.handleAuthCallbackError( function (req, res) {
// If a user denies your app, Facebook will redirect the user to
// /auth/facebook/callback?error_reason=user_denied&error=access_denied&error_description=The+user+denied+your+request.
// This configurable route handler defines how you want to respond to
// that.
// If you do not configure this, everyauth renders a default fallback
// view notifying the user that their authentication failed and why.
})
.findOrCreateUser( function (session, accessToken, accessTokExtra, fbUserMetadata) {
// find or create user logic goes here
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`
You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript`
everyauth.facebook
.entryPath('/auth/facebook')
.callbackPath('/auth/facebook/callback')
.scope('email') // Defaults to undefined
.fields('id,name,email,picture') // Controls the returned fields. Defaults to undefined
If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript`
everyauth.facebook.scope(); // undefined
everyauth.facebook.fields(); // undefined
everyauth.facebook.entryPath(); // '/auth/facebook'
To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript`
everyauth.facebook.configurable();
Facebook provides many different
permissions
for which your app can ask your user. This is bundled up in the scope query
paremter sent with the oauth request to Facebook. While your app may require
several different permissions from Facebook, Facebook recommends that you only
ask for these permissions incrementally, as you need them. For example, you might
want to only ask for the "email" scope upon registration. At the same time, for
another user, you may want to ask for "user_status" permissions because they
have progressed further along in your application.
everyauth enables you to specify the "scope" dynamically with a secondscope
variation of the configurable . In addition to the first variation
that looks like:
`javascript`
everyauth.facebook
.scope('email,user_status');
you can have greater dynamic control over "scope" via the second variation of scope:
`javascript
everyauth.facebook
.scope( function (req, res) {
var session = req.session;
switch (session.userPhase) {
case 'registration':
return 'email';
case 'share-media':
return 'email,user_status';
}
});
`
to your configuration as seen here:`javascript
everyauth.facebook
.mobile(true)
.appId('YOUR APP ID HERE')
.appSecret('YOUR APP SECRET HERE')
// rest of configuration
`Twitter OAuth
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.twitter
.consumerKey('YOUR CONSUMER ID HERE')
.consumerSecret('YOUR CONSUMER SECRET HERE')
.findOrCreateUser( function (session, accessToken, accessTokenSecret, twitterUserMetadata) {
// find or create user logic goes here
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`Important - Some developers forget to do the following, and it causes them to have issues with
everyauth.
Please make sure to do the following: When you set up your app at http://dev.twitter.com/, make sure that your callback url is set up to
include that path '/auth/twitter/callback/'. In general, when dealing with OAuth or OAuth2 modules
provided by everyauth, the default callback path is always set up to follow the pattern
'/auth/#{moduleName}/callback', so just ensure that you configure your OAuth settings accordingly with
the OAuth provider -- in this case, the "Edit Application Settings" section for your app at http://dev.twitter.com.Alternatively, you can specify the callback url at the application level by configuring
callbackPath (which
has a default configuration of "/auth/twitter/callback"):`javascript
everyauth.twitter
.consumerKey('YOUR CONSUMER ID HERE')
.consumerSecret('YOUR CONSUMER SECRET HERE')
.callbackPath('/custom/twitter/callback/path')
.findOrCreateUser( function (session, accessToken, accessTokenSecret, twitterUserMetadata) {
// find or create user logic goes here
})
.redirectPath('/');
`So if your hostname is
example.com, then this configuration will over-ride the dev.twitter.com callback url configuration.
Instead, Twitter will redirect back to example.com/custom/twitter/callback/path in the example just given above.You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.twitter
.entryPath('/auth/twitter')
.callbackPath('/auth/twitter/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.twitter.callbackPath(); // '/auth/twitter/callback'
everyauth.twitter.entryPath(); // '/auth/twitter'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.twitter.configurable();
`Password Authentication
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.password
.getLoginPath('/login') // Uri path to the login page
.postLoginPath('/login') // Uri path that your login form POSTs to
.loginView('a string of html; OR the name of the jade/etc-view-engine view')
.authenticate( function (login, password) {
// Either, we return a user or an array of errors if doing sync auth.
// Or, we return a Promise that can fulfill to promise.fulfill(user) or promise.fulfill(errors)
//
errors is an array of error message strings
//
// e.g.,
// Example 1 - Sync Example
// if (usersByLogin[login] && usersByLogin[login].password === password) {
// return usersByLogin[login];
// } else {
// return ['Login failed'];
// }
//
// Example 2 - Async Example
// var promise = this.Promise()
// YourUserModel.find({ login: login}, function (err, user) {
// if (err) return promise.fulfill([err]);
// promise.fulfill(user);
// }
// return promise;
})
.loginSuccessRedirect('/') // Where to redirect to after a login
// If login fails, we render the errors via the login view template,
// so just make sure your loginView() template incorporates an errors local.
// See './example/views/login.jade' .getRegisterPath('/register') // Uri path to the registration page
.postRegisterPath('/register') // The Uri path that your registration form POSTs to
.registerView('a string of html; OR the name of the jade/etc-view-engine view')
.validateRegistration( function (newUserAttributes) {
// Validate the registration input
// Return undefined, null, or [] if validation succeeds
// Return an array of error messages (or Promise promising this array)
// if validation fails
//
// e.g., assuming you define validate with the following signature
// var errors = validate(login, password, extraParams);
// return errors;
//
// The
errors you return show up as an errors local in your jade template
})
.registerUser( function (newUserAttributes) {
// This step is only executed if we pass the validateRegistration step without
// any errors.
//
// Returns a user (or a Promise that promises a user) after adding it to
// some user store.
//
// As an edge case, sometimes your database may make you aware of violation
// of the unique login index, so if this error is sent back in an async
// callback, then you can just return that error as a single element array
// containing just that error message, and everyauth will automatically handle
// that as a failed registration. Again, you will have access to this error via
// the errors local in your register view jade template.
// e.g.,
// var promise = this.Promise();
// User.create(newUserAttributes, function (err, user) {
// if (err) return promise.fulfill([err]);
// promise.fulfill(user);
// });
// return promise;
//
// Note: Index and db-driven validations are the only validations that occur
// here; all other validations occur in the validateRegistration step documented above.
})
.registerSuccessRedirect('/'); // Where to redirect to after a successful registrationvar routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.password
.loginFormFieldName('login') // Defaults to 'login'
.passwordFormFieldName('password') // Defaults to 'password'
.loginLayout('custom_login_layout') // Only with express
.registerLayout('custom reg_layout') // Only with express
.loginLocals(fn); // See Recipe 3 below
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.password.loginFormFieldName(); // 'login'
everyauth.password.passwordFormFieldName(); // 'password'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.password.configurable();
`$3
Sometimes your registration will ask for more information from the user besides the login and password.
For this particular scenario, you can configure the optional step,
extractExtraRegistrationParams.`javascript
everyauth.password.extractExtraRegistrationParams( function (req) {
return {
phone: req.body.phone
, name: {
first: req.body.first_name
, last: req.body.last_name
}
};
});
`Then, you will have access to this data from within your configured
validateRegistration and registerUser:`javascript
everyauth.password
.validateRegistration( function (newUserAttributes) {
var phone = newUserAttributes.phone
, firstName = newUserAttributes.name.first
, lastName = newUserAttributes.name.last;
})
.registerUser( function (newUserAttributes) {
var phone = newUserAttributes.phone
, firstName = newUserAttributes.name.first
, lastName = newUserAttributes.name.last;
});
`$3
By default,
everyauth uses the field and user key name login during the
registration and login process.Sometimes, you want to use
email or phone instead of login. Moreover,
you also want to validate email and phone fields upon registration.everyauth provides an easy way to do this:`javascript
everyauth.password.loginWith('email');// OR
everyauth.password.loginWith('phone');
`With simple login configuration like this, you get email (or phone) validation
in addition to renaming of the form field and user key corresponding to what
otherwise would typically be referred to as 'login'.
$3
If you are using
express, you are able to pass variables from your app
context to your view context via local variables. everyauth provides
several convenience local vars for your views, but sometimes you will want
to augment this set of local vars with additional locals.So
everyauth also provides a mechanism for you to do so via the following
configurables:`javascript
everyauth.password.loginLocals(...);
everyauth.password.registerLocals(...);
`loginLocals and registerLocals configuration have symmetrical APIs, so I
will only cover loginLocals here to illustrate how to use both.You can configure this parameter in one of 3 ways. Why 3? Because there are 3 types of ways that you can retrieve your locals.
1. Static local vars that never change values:
`javascript
everyauth.password.loginLocals({
title: 'Login'
});
`
2. Dynamic synchronous local vars that depend on the incoming request, but whose values are retrieved synchronously
`javascript
everyauth.password.loginLocals( function (req, res) {
var sess = req.session;
return {
isReturning: sess.isReturning
};
});
`
3. Dynamic asynchronous local vars
`javascript
everyauth.password.loginLocals( function (req, res, done) {
asyncCall( function ( err, data) {
if (err) return done(err);
done(null, {
title: il8n.titleInLanguage('Login Page', il8n.language(data.geo))
});
});
});
`$3
By default,
everyauth.password automatically- validates that the login (or email or phone, depending on what you authenticate with -- see Password Recipe 2) is present in the login http request,
- validates that the password is present
- validates that an email login is a correctly formatted email
- validates that a phone login is a valid phone number
If any of these validations fail, then the appropriate errors are generated and accessible to you in your view via the
errors view local variable.If you want to add additional validations beyond this, you can do so by configuring the step,
validateRegistration:`javascript
everyauth.password
.validateRegistration( function (newUserAttributes, baseErrors) {
// Here, newUserAttributes is the hash of parameters extracted from the incoming request.
// baseErrors is the array of errors generated by the default automatic validation outlined above
// in this same recipe. // First, validate your errors. Here, validateUser is a made up function
var moreErrors = validateUser( newUserAttributes );
if (moreErrors.length) baseErrors.push.apply(baseErrors, moreErrors);
// Return the array of errors, so your view has access to them.
return baseErrors;
});
`$3
By default, everyauth is agnostic about how you decide to store your users and
therefore passwords. However, one should always use password hashing and
salting for security.
Here's an example of how to incorporate password hashing into everyauth using
bcrypt hashing. The idea is to store a salt and hash value inside your user object
instead of the password. The hash value is generated from the password (sent with a
registration or login request) and unique salt per user, using the bcrypt algorithm.
`javascript
// Make sure to npm install bcrypt
var bcrypt = require('bcrypt');everyauth.password
.registerUser( function (newUserAttrs) {
var promise = this.Promise()
, password = newUserAttrs.password;
delete newUserAttrs[password]; // Don't store password
newUserAttrs.salt = bcrypt.genSaltSync(10);
newUserAttrs.hash = bcrypt.hashSync(password, salt);
// Create a new user in your data store
createUser( newUserAttrs, function (err, createdUser) {
if (err) return promise.fail(err);
return promise.fulfill(createdUser);
});
return promise;
})
.authenticate( function (login, password) {
var promise
, errors = [];
if (!login) errors.push('Missing login.');
if (!password) errors.push('Missing password.');
if (errors.length) return errors;
promise = this.Promise();
// findUser passes an error or user to a callback after finding the
// user by login
findUser( login, function (err, user) {
if (err) {
errors.push(err.message || err);
return promise.fulfill(errors);
}
if (!user) {
errors.push('User with login ' + login + ' does not exist.');
return promise.fulfill(errors);
}
bcrypt.compare(password, user.hash, function (err, didSucceed) {
if (err) {
return promise.fail(err);
errors.push('Wrong password.');
return promise.fulfill(errors);
}
if (didSucceed) return promise.fulfill(user);
errors.push('Wrong password.');
return promise.fulfill(errors);
});
});
return promise;
})
`Other Modules
$3
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.github
.appId('YOUR CLIENT ID HERE')
.appSecret('YOUR CLIENT SECRET HERE')
.findOrCreateUser( function (session, accessToken, , accessTokenExtra, githubUserMetadata) {
// find or create user logic goes here
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.github
.entryPath('/auth/github')
.callbackPath('/auth/github/callback')
.scope('repo'); // Defaults to undefined
// Can be set to a combination of: 'user', 'public_repo', 'repo', 'gist'
// For more details, see http://develop.github.com/p/oauth.html
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.github.scope(); // undefined
everyauth.github.entryPath(); // '/auth/github'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.github.configurable();
`$3
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.instagram
.appId('YOUR CLIENT ID HERE')
.appSecret('YOUR CLIENT SECRET HERE')
.findOrCreateUser( function (session, accessToken, accessTokenExtra, instagramUserMetadata) {
// find or create user logic goes here
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.instagram
.entryPath('/auth/instagram')
.callbackPath('/auth/instagram/callback')
.scope('basic') // Defaults to 'basic'
// Can be set to a combination of: 'basic', 'comments', 'relationships', 'likes'
// For more details, see http://instagram.com/developer/auth/#scope
.display(undefined); // Defaults to undefined; Set to 'touch' to see a mobile optimized version
// of the instagram auth page
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.instagram.callbackPath(); // '/auth/instagram/callback'
everyauth.instagram.entryPath(); // '/auth/instagram'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.instagram.configurable();
`$3
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.foursquare
.appId('YOUR CLIENT ID HERE')
.appSecret('YOUR CLIENT SECRET HERE')
.findOrCreateUser( function (session, accessToken, accessTokenExtra, foursquareUserMetadata) {
// find or create user logic goes here
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.foursquare
.entryPath('/auth/foursquare')
.callbackPath('/auth/foursquare/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.foursquare.callbackPath(); // '/auth/foursquare/callback'
everyauth.foursquare.entryPath(); // '/auth/foursquare'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.foursquare.configurable();
`$3
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.linkedin
.consumerKey('YOUR CONSUMER ID HERE')
.consumerSecret('YOUR CONSUMER SECRET HERE')
.findOrCreateUser( function (session, accessToken, accessTokenSecret, linkedinUserMetadata) {
// find or create user logic goes here
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.linkedin
.entryPath('/auth/linkedin')
.callbackPath('/auth/linkedin/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.linkedin.callbackPath(); // '/auth/linkedin/callback'
everyauth.linkedin.entryPath(); // '/auth/linkedin'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.linkedin.configurable();
`$3
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.google
.appId('YOUR CLIENT ID HERE')
.appSecret('YOUR CLIENT SECRET HERE')
.scope('https://www.google.com/m8/feeds') // What you want access to
.handleAuthCallbackError( function (req, res) {
// If a user denies your app, Google will redirect the user to
// /auth/facebook/callback?error=access_denied
// This configurable route handler defines how you want to respond to
// that.
// If you do not configure this, everyauth renders a default fallback
// view notifying the user that their authentication failed and why.
})
.findOrCreateUser( function (session, accessToken, accessTokenExtra, googleUserMetadata) {
// find or create user logic goes here
// Return a user or Promise that promises a user
// Promises are created via
// var promise = this.Promise();
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.google
.entryPath('/auth/google')
.callbackPath('/auth/google/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.google.scope(); // undefined
everyauth.google.entryPath(); // '/auth/google'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.google.configurable();
`$3
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.gowalla
.appId('YOUR CLIENT ID HERE')
.appSecret('YOUR CLIENT SECRET HERE')
.handleAuthCallbackError( function (req, res) {
// TODO - Update this documentation
// This configurable route handler defines how you want to respond to
// a response from Gowalla that something went wrong during the oauth2 process.
// If you do not configure this, everyauth renders a default fallback
// view notifying the user that their authentication failed and why.
})
.findOrCreateUser( function (session, accessToken, accessTokenExtra, gowallaUserMetadata) {
// find or create user logic goes here
// Return a user or Promise that promises a user
// Promises are created via
// var promise = this.Promise();
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.gowalla
.entryPath('/auth/gowalla')
.callbackPath('/auth/gowalla/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.gowalla.scope(); // undefined
everyauth.gowalla.entryPath(); // '/auth/gowalla'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.gowalla.configurable();
`$3
First, register an app at integrate.37signals.com.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth['37signals']
.appId('YOUR CLIENT ID HERE')
.appSecret('YOUR CLIENT SECRET HERE')
.handleAuthCallbackError( function (req, res) {
// TODO - Update this documentation
// This configurable route handler defines how you want to respond to
// a response from 37signals that something went wrong during the oauth2 process.
// If you do not configure this, everyauth renders a default fallback
// view notifying the user that their authentication failed and why.
})
.findOrCreateUser( function (session, accessToken, accessTokenExtra, _37signalsUserMetadata) {
// find or create user logic goes here
// Return a user or Promise that promises a user
// Promises are created via
// var promise = this.Promise();
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth['37signals']
.entryPath('/auth/37signals')
.callbackPath('/auth/37signals/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth['37signals'].entryPath(); // '/auth/37signals'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth['37signals'].configurable();
`$3
First, register an app on AngelList.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.angellist
.appId('YOUR CLIENT ID HERE')
.appSecret('YOUR TOKEN HERE')
.findOrCreateUser( function (session, accessToken, accessTokenExtra, angelListUserMetadata) {
// find or create user logic goes here
// Return a user or Promise that promises a user
// Promises are created via
// var promise = this.Promise();
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.angellist
.entryPath('/auth/angellist')
.callbackPath('/auth/angellist/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.angellist.entryPath(); // '/auth/angellist'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.angellist.configurable();
`$3
First, register an app on Dwolla.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.dwolla
.appId('YOUR CLIENT ID HERE')
.appSecret('YOUR TOKEN HERE')
.scope('accountinfofull')
.findOrCreateUser( function (session, accessToken, accessTokenExtra, dwollaUserMetadata) {
// find or create user logic goes here
// Return a user or Promise that promises a user
// Promises are created via
// var promise = this.Promise();
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
`$3
First, register an app on Skyrock.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.skyrock
.consumerKey('YOUR CONSUMER KEY HERE')
.consumerSecret('YOUR CONSUMER SECRET HERE')
.findOrCreateUser( function (session, accessToken, accessTokenExtra, skyrockUserMetadata) {
// find or create user logic goes here
// Return a user or Promise that promises a user
// Promises are created via
// var promise = this.Promise();
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`$3
First, register an app on VKontakte.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.vkontakte
.appId('YOUR APP ID HERE')
.appSecret('YOUR TOKEN HERE')
.scope('photo')
.findOrCreateUser( function (session, accessToken, accessTokenExtra, vkUserMetadata) {
// find or create user logic goes here
// Return a user or Promise that promises a user
// Promises are created via
// var promise = this.Promise();
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes)
).listen(3000);
`$3
First, register an app on mail.ru.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.mailru
.appId('YOUR CONSUMER KEY HERE')
.appSecret('YOUR CONSUMER SECRET HERE')
.scope('messages')
.entryPath('/auth/mailru')
.callbackPath('/auth/mailru/callback')
.findOrCreateUser( function (session, accessToken, accessTokenExtra, mailruUser) {
// find or create user logic goes here
// Return a user or Promise that promises a user
// Promises are created via
// var promise = this.Promise();
// return promise;
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`$3
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.yahoo
.consumerKey('YOUR CONSUMER KEY HERE')
.consumerSecret('YOUR CONSUMER SECRET HERE')
.findOrCreateUser( function (session, accessToken, accessTokenSecret, yahooUserMetadata) {
// find or create user logic goes here
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.yahoo
.entryPath('/auth/yahoo')
.callbackPath('/auth/yahoo/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.yahoo.callbackPath(); // '/auth/yahoo/callback'
everyauth.yahoo.entryPath(); // '/auth/yahoo'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.yahoo.configurable();
`$3
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.readability
.consumerKey('YOUR CONSUMER KEY HERE')
.consumerSecret('YOUR CONSUMER SECRET HERE')
.findOrCreateUser( function (sess, accessToken, accessSecret, reader) {
// find or create user logic goes here
//
// e.g.,
// return usersByReadabilityId[reader.username] || (usersByReadabilityId[reader.username] = reader);
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.readability
.entryPath('/auth/readability')
.callbackPath('/auth/readability/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.readability.callbackPath(); // '/auth/readability/callback'
everyauth.readability.entryPath(); // '/auth/readability'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.readability.configurable();
`$3
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.dropbox
.consumerKey('YOUR CONSUMER KEY HERE')
.consumerSecret('YOUR CONSUMER SECRET HERE')
.findOrCreateUser( function (sess, accessToken, accessSecret, user) {
// find or create user logic goes here
//
// e.g.,
// return usersByDropboxId[user.uid] || (usersByDropboxId[user.uid] = user);
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.dropbox
.entryPath('/auth/dropbox')
.callbackPath('/auth/dropbox/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.dropbox.callbackPath(); // '/auth/dropbox/callback'
everyauth.dropbox.entryPath(); // '/auth/dropbox'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.dropbox.configurable();
`$3
Sign up for a Justin.tv account and activate it as a developer account to get your consumer key and secret.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');
everyauth.justintv
.consumerKey('YOUR CONSUMER KEY HERE')
.consumerSecret('YOUR CONSUMER SECRET HERE')
.findOrCreateUser( function (sess, accessToken, accessSecret, justintvUser) {
// find or create user logic goes here
//
// e.g.,
// return usersByJustintvId[justintvUser.id] || (usersByJustintvId[justintvUser.id] = justintvUser);
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`The
justintvUser parameter in the .findOrCreateUser() function above returns the account/whoami API call`javascript
{
"image_url_huge": "http:\/\/static-cdn.justin.tv\/jtv_user_pictures\/justin-320x240-4.jpg",
"profile_header_border_color": null,
"favorite_quotes": "I love Justin.tv",
"sex": "Male",
"image_url_large": "http:\/\/static-cdn.justin.tv\/jtv_user_pictures\/justin-125x94-4.jpg",
"profile_about": "Check out my website:\n\nwww.justin.tv\n",
"profile_background_color": null,
"image_url_medium": "http:\/\/static-cdn.justin.tv\/jtv_user_pictures\/justin-75x56-4.jpg",
"id": 1698,
"broadcaster": true,
"profile_url": "http:\/\/www.justin.tv\/justin\/profile",
"profile_link_color": null,
"image_url_small": "http:\/\/static-cdn.justin.tv\/jtv_user_pictures\/justin-50x37-4.jpg",
"profile_header_text_color": null,
"name": "The JUST UN",
"image_url_tiny": "http:\/\/static-cdn.justin.tv\/jtv_user_pictures\/justin-33x25-4.jpg",
"login": "justin",
"profile_header_bg_color": null,
"location": "San Francisco"
}
`You can also configure more parameters (most are set to defaults) via the same chainable API:
`javascript
everyauth.justintv
.entryPath('/auth/justintv')
.callbackPath('/auth/justintv/callback');
`If you want to see what the current value of a configured parameter is, you can do so via:
`javascript
everyauth.justintv.callbackPath(); // '/auth/justintv/callback'
everyauth.justintv.entryPath(); // '/auth/justintv'
`To see all parameters that are configurable, the following will return an object whose parameter name keys map to description values:
`javascript
everyauth.justintv.configurable();
`$3
You will first need to sign up for a developer application to get the consumer key and secret.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.vimeo
.consumerKey('YOUR CONSUMER KEY HERE')
.consumerSecret('YOUR CONSUMER SECRET HERE')
.findOrCreateUser( function (sess, accessToken, accessSecret, user) {
// find or create user logic goes here
//
// e.g.,
// return usersByVimeoId[user.id] || (usersByVimeoId[user.id] = user);
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.vimeo
.entryPath('/auth/vimeo')
.callbackPath('/auth/vimeo/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.vimeo.callbackPath(); // '/auth/vimeo/callback'
everyauth.vimeo.entryPath(); // '/auth/vimeo'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.vimeo.configurable();
`$3
You will first need to register an app to get the consumer key and secret.
During registration of your new app, enter a "Default callback URL" of "http://:/auth/tumblr/callback".
Once you register your app, copy down your "OAuth Consumer Key" and "Secret Key" and proceed below.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.tumblr
.consumerKey('YOUR CONSUMER KEY HERE')
.consumerSecret('YOUR CONSUMER SECRET HERE')
.findOrCreateUser( function (sess, accessToken, accessSecret, user) {
// find or create user logic goes here
//
// e.g.,
// return usersByTumblrName[user.name] || (usersByTumblrName[user.name] = user);
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.tumblr
.entryPath('/auth/tumblr')
.callbackPath('/auth/tumblr/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.tumblr.callbackPath(); // '/auth/tumblr/callback'
everyauth.tumblr.entryPath(); // '/auth/tumblr'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.tumblr.configurable();
`$3
You will first need to request an API key to get the consumer key and secret. Note that this consumer key and secret will only be valid for the sandbox rather than the production OAuth host. By default the Evernote module will use the production host, so you'll need to override this using the chainable API if you're using the sandbox.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.evernote
.consumerKey('YOUR CONSUMER KEY HERE')
.consumerSecret('YOUR CONSUMER SECRET HERE')
.findOrCreateUser( function (sess, accessToken, accessSecret, user) {
// find or create user logic goes here
//
// e.g.,
// return usersByEvernoteId[user.userId] || (usersByEvernoteId[user.userId] = user);
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.evernote
.oauthHost('https://sandbox.evernote.com')
.entryPath('/auth/evernote')
.callbackPath('/auth/evernote/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.evernote.oauthHost(); // 'https://sandbox.evernote.com'
everyauth.evernote.callbackPath(); // '/auth/evernote/callback'
everyauth.evernote.entryPath(); // '/auth/evernote'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.evernote.configurable();
`$3
You will first need to login to OpenStreetMap. Then register you application on your OpenStreetMap user page via the View my OAuth details link on the bottom of the page to get the consumer key and secret. The registered application does not need any permission listed there to login via OAuth.
`javascript
var everyauth = require('osm')
, connect = require('connect');everyauth.osm
.consumerKey('YOUR CONSUMER KEY HERE')
.consumerSecret('YOUR CONSUMER SECRET HERE')
.findOrCreateUser( function (sess, accessToken, accessSecret, user) {
// find or create user logic goes here
//
// e.g.,
// return usersByOSMId[user.id] || (usersByOSMId[user.id] = user);
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
`javascript
everyauth.osm
.oauthHost('http://api06.dev.openstreetmap.org')
.entryPath('/auth/osm')
.callbackPath('/auth/osm/callback');
`If you want to see what the current value of a
configured parameter is, you can do so via:
`javascript
everyauth.osm.oauthHost(); // 'http://api.openstreetmap.org'
everyauth.osm.callbackPath(); // '/auth/osm/callback'
everyauth.osm.entryPath(); // '/auth/osm'
`To see all parameters that are configurable, the following will return an
object whose parameter name keys map to description values:
`javascript
everyauth.osm.configurable();
`$3
Obtain consumer key and consumer secret for your app by registering it.
Please note that TripIt is using _API Key_ and _API Secret_ terminology: use those values as describe below.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.tripit
.consumerKey('YOUR API KEY')
.consumerSecret('YOUR API SECRET')
.findOrCreateUser( function (sess, accessToken, accessSecret, tripitProfile) {
// find or create user logic goes here
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`$3
You will first need to request an API key to get the consumer key and secret.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth['500px']
.consumerKey('YOUR CONSUMER KEY HERE')
.consumerSecret('YOUR CONSUMER SECRET HERE')
.findOrCreateUser( function (sess, accessToken, accessSecret, user) {
// find or create user logic goes here
//
// e.g.,
// return usersBy500pxId[user.userId] || (usersBy500pxId[user.userId] = user);
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`$3
You will first need to register an app to get the client id and secret.
During registration of your new app, enter a "Default callback URL" of "http://:/auth/soundcloud/callback".
Once you register your app, copy down your "Client ID" and "Client Secret" and proceed below.
`javascript
var everyauth = require('everyauth')
, connect = require('connect');everyauth.soundcloud
.appId('YOUR CLIENT ID HERE')
.appSecret('YOUR CLIENT SECRET HERE')
.handleAuthCallbackError( function (req, res) {
// TODO - Update this documentation
// This configurable route handler defines how you want to respond to
// a response from SoundCloud that something went wrong during the oauth2 process.
// If you do not configure this, everyauth renders a default fallback
// view notifying the user that their authentication failed and why.
})
.findOrCreateUser( function (session, accessToken, accessTokenExtra, soundcloudUserMetadata) {
// find or create user logic goes here
// Return a user or Promise that promises a user
// Promises are created via
// var promise = this.Promise();
})
.redirectPath('/');
var routes = function (app) {
// Define your routes here
};
connect(
connect.bodyParser()
, connect.cookieParser()
, connect.session({secret: 'whodunnit'})
, everyauth.middleware()
, connect.router(routes);
).listen(3000);
`You can also configure more parameters (most are set to defaults) via
the same chainable API:
``javascript