In this project, we'll use passport
to handle authenticating users. Passport can use many different strategies
to authenticate users. However, we'll take a look at just one of them for this project. We are going to use the auth0
strategy. We'll have to sign-up at manage.auth0.com
to get an app (aka client) that we can log in to.
Fork
andclone
this repository.cd
into the project directory.- Run
npm install
.
In this step, we'll install the required dependencies to use passport and the auth0
strategy in a node application.
- Run
npm install --save passport passport-auth0
.
In this step, we'll go to manage.auth0.com
to create an account and modify the default client they give us.
- Go to
manage.auth0.com
. - Register for an account.
- Set the account type to
Personal
. - Set the role to
Developer
. - Set the project to
Just playing around
.
- Set the account type to
- Log in to your Auth0 account.
- Go to
Clients
using the left navigation bar. - Click on
Settings
for the default app.- Change the
Client Type
toNon Interactive Client
. - Change the
Token Endpoint Authentication Method
toBasic
. - Change the
Allowed Callback URLs
tohttp://localhost:3000/login
. - Change the
Allowed Origins
tohttp://localhost:3000
- Change the
- Click
Save Changes
. - Keep the page open, we'll need the
domain
,id
, andsecret
later.
In this step, we'll create a config.js
file and strategy.js
. We'll add config.js
to our .gitignore
so we can keep the client domain
, id
, and secret
off of GitHub. We'll then require it in strategy.js
and configure strategy.js
to use the auth0
strategy.
- Create a
config.js
file. - Open
config.js
. - Use
module.exports
to export an object.- The object should have a
domain
,clientID
, andclientSecret
property that equal strings. - The strings should equal the values of your
domain
,clientID
, andclientSecret
frommanage.auth0.com
.
- The object should have a
- Add
config.js
to.gitignore
. - Create a
strategy.js
file. - Open
strategy.js
. - Require
config.js
. - Require the
passport-auth0
strategy in a variable calledAuth0Strategy
. - Use
module.exports
to export anew Auth0Strategy
.-
Syntax
module.exports = new Auth0Strategy({ domain: '...', clientID: '...', clientSecret: '...', callbackURL: '/login' }, function(accessToken, refreshToken, extraParams, profile, done) { // accessToken is the token to call Auth0 API (not needed in the most cases) // extraParams.id_token has the JSON Web Token // profile has all the information from the user return done(null, profile); } );
-
- Modify the
domain
,clientID
, andclientSecret
to use the values fromconfig.js
.
strategy.js
const Auth0Strategy = require('passport-auth0');
const config = require(`${__dirname}/config.js`);
const { domain, clientID, clientSecret } = config;
module.exports = new Auth0Strategy({
domain: domain,
clientID: clientID,
clientSecret: clientSecret,
callbackURL: '/login'
},
function(accessToken, refreshToken, extraParams, profile, done) {
// accessToken is the token to call Auth0 API (not needed in the most cases)
// extraParams.id_token has the JSON Web Token
// profile has all the information from the user
return done(null, profile);
}
);
In this step, we'll configure our app to use sessions and passport with our newly created strategy.
- Open
index.js
. - Require
passport
andstrategy
fromstrategy.js
. - Configure the app to use sessions.
- Initialize passport and configure passport to use sessions.
- Configure passport to use our required strategy.
index.js
const express = require('express');
const session = require('express-session');
const passport = require('passport');
const strategy = require(`${__dirname}/strategy.js`);
const app = express();
app.use( session({
secret: 'sup dude',
resave: false,
saveUninitialized: false
}));
app.use( passport.initialize() );
app.use( passport.session() );
passport.use( strategy );
const port = 3000;
app.listen( port, () => { console.log(`Server listening on port ${port}.`); } );
In this step, we'll use the serializeUser
and deSerializeUser
methods of passport. These methods get called before a successful redirect. We can use these methods to pick what properties we want to store on session.
- Open
index.js
. - Call the
passport.serializeUser
method and pass in a function as the first argument.- This function should have a
user
anddone
parameter. - This function should call
done
withnull
as the first argument and an object as the second argument.- Use an object that only has the
id
,displayName
,nickname
, andemail
fromuser
.
- Use an object that only has the
- This function should have a
- Call the
passport.deSerializeUser
method and pass in a function as the first argument.- This function should should have a
obj
anddone
parameter.obj
will equal the object we passed intodone
fromserializeUser
.
- This functions should call
done
withnull
as the first argument andobj
as the second argument.- After
done
is finished, the value ofobj
is then stored onreq.user
andreq.session.passport.user
.
- After
- This function should should have a
index.js
const express = require('express');
const session = require('express-session');
const passport = require('passport');
const strategy = require(`${__dirname}/strategy.js`);
const app = express();
app.use( session({
secret: 'sup dude',
resave: false,
saveUninitialized: false
}));
app.use( passport.initialize() );
app.use( passport.session() );
passport.use( strategy );
passport.serializeUser(function(user, done) {
done(null, { id: user.id, display: user.displayName, nickname: user.nickname, email: user.emails[0].value });
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
const port = 3000;
app.listen( port, () => { console.log(`Server listening on port ${port}.`); } );
In this step, we'll create a login endpoint that will call the authenticate
method on passport. We'll then configure it to redirect
to a /me
endpoint on success and the /login
endpoint on failure. We'll also enable failureFlash
so passport can flash an error message on failure.
- Open
index.js
. - Create a
GET
endpoint at/login
that calls theauthenticate
method on passport.- The first argument should be a string of the strategy:
'auth0'
. - The second argument should be a configuration object:
- Add a
successRedirect
property that equals'/me'
. - Add a
failureRedirect
property that equals'/login'
. - Add a
failureFlash
property that equalstrue
.
- Add a
- The first argument should be a string of the strategy:
index.js
const express = require('express');
const session = require('express-session');
const passport = require('passport');
const strategy = require(`${__dirname}/strategy.js`);
const app = express();
app.use( session({
secret: 'sup dude',
resave: false,
saveUninitialized: false
}));
app.use( passport.initialize() );
app.use( passport.session() );
passport.use( strategy );
passport.serializeUser(function(user, done) {
done(null, { id: user.id, display: user.displayName, nickname: user.nickname, email: user.emails[0].value });
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
app.get( '/login',
passport.authenticate('auth0',
{ successRedirect: '/me', failureRedirect: '/login', failureFlash: true }
)
);
const port = 3000;
app.listen( port, () => { console.log(`Server listening on port ${port}.`); } );
In this step, we'll create a /me
endpoint that checks to see if req.user
exists. If it does, it will send it. If it doesn't, it will redirect to the /login
endpoint.
- Create a
GET
endpoint at/me
that checks to see ifreq.user
exists.- If it does, return a status 200 with the
req.user
object. - If it doesn't, redirect to
/login
.
- If it does, return a status 200 with the
index.js
const express = require('express');
const session = require('express-session');
const passport = require('passport');
const strategy = require(`${__dirname}/strategy.js`);
const app = express();
app.use( session({
secret: 'sup dude',
resave: false,
saveUninitialized: false
}));
app.use( passport.initialize() );
app.use( passport.session() );
passport.use( strategy );
passport.serializeUser(function(user, done) {
done(null, { id: user.id, display: user.displayName, nickname: user.nickname, email: user.emails[0].value });
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
app.get( '/login',
passport.authenticate('auth0',
{ successRedirect: '/me', failureRedirect: '/login', failureFlash: true }
)
);
app.get('/me', ( req, res, next) => {
if ( !req.user ) {
res.redirect('/login');
} else {
// req.user === req.session.passport.user
// console.log( req.user )
// console.log( req.session.passport.user );
res.status(200).send( JSON.stringify( req.user, null, 10 ) );
}
});
const port = 3000;
app.listen( port, () => { console.log(`Server listening on port ${port}.`); } );
In this step, we'll open a browser and see if we can log in to our Auth0 client.
- Open a browser and navigate to
http://localhost:3000/login
. - Sign up for the client and then log in to it.