Javascript - Node

This tutorial will walk you through creating a simple Node + Express application using Swoop for user authentication.

You can download the comprehensive Starter Example Here if you prefer.

Before you begin, make sure you head to the Swoop Dashboard and create a new property.

2396

Click the 'Add Property' button on the top right of the dashboard landing page.

2398

Then fill in the property fields and submit. Make sure to set the Redirect URL to the following to work with our test project:
http://localhost:3000/auth/swoop/callback.

1. Setting Up the Basic Express App

We are going to make a simple app that has one protected route called swoop_test.

mkdir swoop_test
cd swoop_test
npm init -y
touch index.js

This will create a basic Node app. Now we are going to add Express in order to set up routes.

2. Creating a Basic Express Server

Start by installing express and express-session.

npm install --save express express-session

Now, open index.js and add the following code:

const express        = require('express');
const app            = express()
const port           = process.env.PORT || 3000;

/*****************
* Routes
*****************/

// Root Route
app.get('/', (req, res) => {
  res.send('Hello Swoop! \
  <div><a href="/auth/swoop">Login</a></div> \
  <div><a href="/logout">Logout</a></div>');
});

// Route that will be made secret
app.get('/secret', (req, res, next) => {
  res.send('Shhhhhh! It\' a secret!');
});

// Start the server
app.listen(port, () => console.log(`Swoop Demo listening on port ${port}!`));

Run this code by executing the following command in the terminal:

node index.js

This will create a basic Express server that has two routes: a root route and a secret route. Open your browser to http://localhost:3000/secret and you will see the output "Shhhhh! It's a secret!". We will now set up Swoop to secure this route and require a user to login to view this resource.

3. Setting Up Passport for Swoop

Open the terminal and install the following node modules:

npm install --save passport passport-swoop

We are using a Passport.js strategy for Swoop to help us with the OAuth integration. Given a little configuration, it will help us generate the OAuth link to send our users to Swoop and will handle the callback when Swoop sends the authorization code.

Add the following code to the top of index.js:

// Previous imports...
const passport       = require('passport');
const SwoopStrategy  = require('passport-swoop')

/*****************
* Middleware
*****************/
app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true }));
app.use(passport.initialize());
app.use(passport.session());

// Routes...

This imports the Passport module and the SwoopStrategy from Passport. Lastly, we set up a "Middleware" section to our code. This sets up the session management middleware for our application. We need to use sessions in order to support the more secure PKCE extension of OAuth.

Now we are going to configure Passport with the Swoop parameters. Add the following code AFTER the Middleware section:

// Middleware...

/*****************
* Passport Config
*****************/
passport.use(new SwoopStrategy({
    clientID: 'CLIENT_ID',
    clientSecret: 'CLIENT_SECRET',
    callbackURL: '/auth/swoop/callback'
  },
  function(profile, cb) {
    return cb(null, profile);
  }));

passport.serializeUser(function(user, cb) {
  cb(null, user);
});

passport.deserializeUser(function(obj, cb) {
  cb(null, obj);
});

// Routes...

We are setting up a new SwoopStrategy for Passport with the configuration for your Swoop property. There are 3 properties here to pay attention to:

  • CLIENT_ID The Client ID associated with your Swoop Property.
  • CLIENT_SECRET The Client Secret that was generated for your Swoop Property.
  • CALLBACK_URL You need to make sure that this matches the value you used when setting up the property. You can add multiple callback URLs in the Swoop Dashboard for local, production, etc.

The second part of this method is passed a profile from Passport. It contains the email (profile.email) and ID (profile.id) or the user. This method is where you might look up your actual user in the database and pass it to the done callback. This way, it will be available on all routes as req.user.

The profile object also contains the following information, which conforms to the Open ID Connect standard in the _json field:

{
  iss: 'https://auth.swoop.email',
  sub: '5e1f6bfe587c1a00046b98da',
  aud: 'swoop_pdkhq4k87gd75p',
  nonce: 'S_on5v1avdi',
  email: '[email protected]',
  iat: 1585255245,
  exp: 1586119245
}

Finally, the code above tells express how to serialize and de-serialize a user. For now, this is just the user object returned from Swoop. In a production environment, it should be the user from your database with a matching email address or Swoop ID.

4 Create the Swoop Routes

You might have noticed that clicking on the login and logout links on the root route results in 404 pages. We are going to implement two routes to complete the OAuth2 process.

Add the following code to the "Routes" section of index.js:

// Oauth 2 Config...

// Swoop Login Route
app.get('/auth/swoop', passport.authenticate('swoop', { scope: ['email'] }));

// Callback function after authentication occurs
app.get('/auth/swoop/callback',
        passport.authenticate('swoop', { session: true }),
        (req, res, next) => {
  res.redirect('/secret');
});

// Logs the user out and redirects to the homepage
app.get('/logout', (req, res) => {
  req.logout();
  res.redirect('/');
});

// Routes...

Now, restart the server and head over to http://localhost:3000 and click Login.

node index.js

Congratulations! You are now authenticating users with Swoop. The last piece of this puzzle is to persist user logins inside of a session in order to protect our secret route.

Now you can use req.user in ANY route that you want to secure.

5. Securing the Secret Route

Update the secret route code to the following:

// Routes...

app.get('/secret', (req, res, next) => {
  if(req.user) {
    res.send('This contains a secret. Welcome ' + req.user.email);
  } else {
    res.redirect('/');
  }
});

Now when the user attempts to open "/secret", it will redirect them to the homepage unless they have logged in. If the user is logged in, their email will be accessible when they view req.user.

Restart the server and go through the login flow again.

node index.js

You are now able to secure ANY route using the Swoop authentication service. Yippee!