Easily Integrate OKTA (SSO) layer for Node.JS application hosted on Heroku

Okta is one of the major player  (see Gartner magic quadrant) these days in market offering Identity Management Service. You can easi...


Okta is one of the major player (see Gartner magic quadrant) these days in market offering Identity Management Service. You can easily plugin OKTA with active directory of your company to identify legit user. Salesforce integration with OKTA is fairly easy and straightforward so as Heorku. But while building a custom SAML support for Node.Js I couldn't find much support, later with some research we found saml integration to be straightforward without passport, but you can see passportJS saml authentication via heroku platform here as well

I have written a boiler-plate code covering any node application with OKTA layer with SAML (2.0), you can fork this code, add you code in it and simply provide okta layer on top your application. So lets get started on this


For node, I am considering express as my framework to build facade for my application and relying on passport to provide SAML backbone flow architecture. Lets being by building package.json and list all our dependencies

{
    "name": "Okta-SAML-Node",
    "description": "Application demonstrating OKTA SSO integration for Node application",
    "main": "index.js",
    "scripts": {
        "start": "node index.js",
        "test": "NODE_ENV=production node index.js"
    },
    "dependencies": {
        "connect": "^2.30.2",
        "express": "^3.5.3",
        "passport": "^0.2.2",
        "passport-saml": "0.15.0"
    },
    "repository": {
        "type": "git",
        "url": "https://github.com/mailtoharshit/okta-saml-node.git"
    },
    "contributors": [{
        "name": "Harshit Pandey",
        "email": "mailtoharshit@gmail.com"
    }],
    "keywords": [
        "saml",
        "sso"
    ],
    "license": "MIT"
}

In express, we can spin a quick application using express generator, to spin up a scaffold for your application

$ npm install express-generator -g

Lets begin by writing routing for express application begging with "login" page

//Lets call passport authenticate method to authenticate 

app.get('/login', auth.authenticate('saml', { failureRedirect: '/', failureFlash: true }), function(req, res) {
    res.redirect('/');
});

Now lets handle the redirection on successful login to homepage


//POST Methods, redirect to home successful login
app.post('/login/callback', auth.authenticate('saml', { failureRedirect: '/', failureFlash: true }), function(req, res) {
    res.redirect('/home');
});


You can always double check, if a user is authenticated before he/she call for a managed service endpoint


//Get Methods
app.get('/', auth.protected, function(req, res) {
    res.sendfile('index.html');
});

app.get('/home', auth.protected, function(req, res) {
    res.sendfile('index.html');
});

Applying SAML Strategy 

Apply SAML strategy by checking on parameters you need, in here, I used email as key identifier for user


passport.use(new SamlStrategy({
        issuer: config.auth.issuer,
        path: '/login/callback',
        entryPoint: config.auth.entryPoint,
        cert: config.auth.cert
    },
    function(profile, done) {
        console.log('Succesfully Profile' + profile);
        if (!profile.email) {
            return done(new Error("No email found"), null);
        }
        process.nextTick(function() {
            console.log('process.nextTick' + profile);
            findByEmail(profile.email, function(err, user) {
                if (err) {
                    return done(err);
                }
                if (!user) {
                    users.push(profile);
                    return done(null, profile);
                }
                console.log('Ending Method for profiling');
                return done(null, user);
            })
        });
    }
));

SAML Configs

Let's setup environment variables, clearly you can divide dev/qa/product config variables Apply SAML strategy by checking on parameters you need, in here, I used email as key identifier for user


{
    "dev": {
        "auth": {
            "issuer": "https://oktanode.herokuapp.com/",
            "entryPoint": "https://dev-467749.oktapreview.com/app/oyecodedev970378_roomfinder_1/exk8x3ahm3ycfQYCI0h7/sso/saml",
            "cert": "MII/FB"
        }
    },
    "qa": {
        "auth": {
            "issuer": "https://oktanode.herokuapp.com/",
            "entryPoint": "https://dev-467749.oktapreview.com/app/oyecodedev970378_roomfinder_1/exk8x3ahm3ycfQYCI0h7/sso/saml",
            "cert": "MII/FB"
        }
    },
    "production": {
        "auth": {
            "issuer": "https://oktanode.herokuapp.com/",
            "entryPoint": "https://dev-467749.oktapreview.com/app/oyecodedev970378_roomfinder_1/exk8x3ahm3ycfQYCI0h7/sso/saml",
            "cert": "MII\/FB"
        }
    }
}


Running Application locally 
When you fork and run application locally (http://localhost:3000), you will be prompted by okta login and which on success takes you landing page.


Push your application Heroku 

$ git clone git@github.com:mailtoharshit/OKTA-SAML-Node.git
$ git push heroku master
$ heroku open

Source Code

The source code for the application is available in this repository.
To install and run the app:
  1. Clone the okta-node repository:
    1
    git clone https://github.com/mailtoharshit/OKTA-SAML-Node
  2. Navigate (cd) to the okta-saml-node  directory.
  3. Install the dependencies:
    1
    $ sudo npm install
  4. Start the application:
    1
    $ npm run

What Others Are Reading