I'm working on REST
api using NodeJS
. For authentication I decided to use Passport
. I want truly RESTful api. So it means I have to use tokens instead of sessions.
I want to let users login using username and password, or using social networks like Facebook, Google and Twitter.
I make my own OAuth2.0
server for issuing Access
and Refresh tokens
using oauth2orize
module. So now I can register new user and then issue them tokens.
I followed this tutorial:
http://aleksandrov.ws/2013/09/12/restful-api-with-nodejs-plus-mongodb/
Verifying user for route:
// api ------------------------------------------------------------------------------------
app.get('/api/userInfo',
passport.authenticate('bearer', { session: false }),
function(req, res) {
// req.authInfo is set using the `info` argument supplied by
// `BearerStrategy`. It is typically used to indicate scope of the token,
// and used in access control checks. For illustrative purposes, this
// example simply returns the scope in the response.
res.json({ user_id: req.user.userId, name: req.user.username, scope: req.authInfo.scope })
}
);
All this works quite well. Unfortunately I don't know how to implement social authentication.
I was reading this tutorial:
http://scotch.io/tutorials/javascript/easy-node-authentication-facebook
But in this tutorial they are not making a truly RESTful api. I already implemented user schema according this tutorial where tokens for local user are stored in separated models.
// define the schema for our user model
var userSchema = mongoose.Schema({
local: {
username: {
type: String,
unique: true,
required: true
},
hashedPassword: {
type: String,
required: true
},
created: {
type: Date,
default: Date.now
}
},
facebook: {
id: String,
token: String,
email: String,
name: String
},
twitter: {
id: String,
token: String,
displayName: String,
username: String
},
google: {
id: String,
token: String,
email: String,
name: String
}
});
But now, how can I verify user?
passport.authenticate('bearer', { session: false }),
this is verifying only bearer token against to my db, but how can I verify social tokens? Am I missing something?
if your using a bearer token all you have to do is pass the unique Identifier to the user of the API. This would most likely be done in one singular call maybe in the form of a login. Then every call to the API require that token which verifies the token exists in the database and updates its Time To Live value. You do not need individual tokens in your schema for each login you need an individual schema for tokens which has a Time To Live Value (TTL)
Iv'e created the following Schema's:
When logging in to my web app, I use a PassportJS Social plugin like facebook/google. Example:
Now when I want to navigate my web application I use the session authentication that was made available to me via the Facebook plugin. When a user wants to request an API token they need to be logged in so I can Associate that token with the user.
So now a user has a token associated with them that they can use for Token authentication for my API.
My API routes dont care or look at sessions, all they care about is the token. Iv'e done this by creating an express router, and using passport's bearer strategy as a middleware for all routes heading towards my API.
So now I use only token authentication for my API's(Doesn't ever look at session data), and Session authentication to easily navigate my webapp. An example of me using sessions to navigate my app is shown below:
Hopefully this will help you!
I am using Facebook login for my own RESTful API for my Notepads app here. I started the application as one that will be used as a web page but still the communication after the login will be through the API.
Then I decided to create a mobile version of the same app that will use the API. I decided to make it that way: The mobile app logs in through Facebook and sends the facebook user id and FB access token to the API, the API calls Facebooks's API to verify these params and if successful registers a new user(or logs in an existing one) in my app's DB, creates a custom token for this user and returns it to the mobile app. From here the mobile app sends this custom token to authenticate the app with the API.
Here's some code:
The auth in the API (uses the fbgraph npm module):
https://github.com/iliyan-trifonov/notepads-nodejs-angularjs-mongodb-bootstrap/blob/6617a5cb418ba8acd6351ef9a9f69228f1047154/src/routes/users.js#L46 .
The User model:
https://github.com/iliyan-trifonov/notepads-nodejs-angularjs-mongodb-bootstrap/blob/master/src/models/user.js#L9 .
The Facebook auth in the mobile app:
https://github.com/iliyan-trifonov/notepads-ionic/blob/master/www/js/services.js#L33 .
The mobile app sends the token with the request:
It's an Ionic/Angular/Cordova app. The Facebook login from the mobile app starts the Facebook app installed on your phone or opens a popup to login in Facebook. Then a callback returns the Facebook user's id and access token to my mobile app.
The fbgraph npm module: https://github.com/criso/fbgraph
The social media strategies for passport depend on the session. They will not function without one.
I'm running int o the same issue I wanted my REST server to be stateless.
In my opinion there are 2 options.
PS: You should tag this as passport so that pass port devs might see it.