Criipto
  1. Integrations
  2. Node.js (Express)

This guide shows you how to use Criipto Verify in a Node.js web application with Express, optionally Passport and @criipto/verify-express.

You may get a completed and ready to run sample from GitHub showing the below recipe in the simplest of Node.js Express applications.

Register Your Application in Criipto Verify

After you signed up for Criipto Verify, you must register an application before you can actually try logging in with any eID.

Once you register your application you will also need some of the information for communicating with Criipto Verify. You get these details from the settings of the application in the dashboard.

Specifically you need the following information to configure you application

  • Client ID to identify your application to Criipto Verify.
  • Client Secret for token exchange in redirect based flows, shown when you enable OAUth2 code flow.
  • Domain on which you will be communicating with Criipto Verify.

If you do not have a client secret, you can generate or regenerate one by going to Applications and selecting the "OpenID Connect" tab.

Register callback URLs

Before you can start sending authentication requests to Criipto Verify you need to register the URLs on which you want to receive the returned JSON Web Token, JWT.

The Callback URL of your application is the URL where Criipto Verify will redirect to after the user has authenticated in order for the OpenID Connect middleware to complete the authentication process.

You will need to add this URL to the list of allowed URLs for your application.

If you were running locally with an Express login and logout route, your callback URLs might look something like:

http://localhost:3000/login
http://localhost:3000/logout

If you deploy your application to a different URL you will also need to ensure to add that URL to the Callback URLs.

Install SDK

Using npm

npm install @criipto/verify-express

Web-application with sessions and redirect.

Sessions must be setup when using redirect based authentication.

You must also register a Callback URL on your Criipto Application matching the URL of your redirect handling route.

// server.js

const express = require('express');
const expressSession = require('express-session');
const app = express();

app.use(
  expressSession({
    secret: '{{YOUR_SESSION_SECRET}}',
    resave: false,
    saveUninitialized: true
  })
);

Passport

// server.js

const CriiptoVerifyRedirectPassportStrategy = require('@criipto/verify-express').CriiptoVerifyRedirectPassportStrategy;

app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done) {
  done(null, user);
});
passport.deserializeUser(function(user, done) {
  done(null, user);
});

const redirectPassport = new CriiptoVerifyRedirectPassportStrategy(
  {
    domain: "{{YOUR_CRIIPTO_DOMAIN}}",
    clientID: "{{YOUR_CLIENT_ID}}",
    clientSecret: "{{YOUR_CLIENT_SECRET}}",
    // Should match an express route that is an allowed callback URL in your application
    // This route should also have the authentication middleware applied.
    redirectUri: '/login',
    postLogoutRedirectUri: '/',

    // Amend authorize request if you wish
    beforeAuthorize(req, options) {
      return {
        ...options,
        acr_values: req.query.acr_values,
        prompt: req.query.prompt
      }
    }
  },
  // Map claims to an express user
  async (jwtClaims) => {
    return jwtClaims;
  }
);

// Route to both trigger and handle redirect
app.get('/login', passport.authenticate('criiptoVerifyRedirect', {failureRedirect: '/error', successReturnToOrRedirect: '/passport/protected'}), (req, res) => {
  res.json(req.user);
});
app.get('/protected', passport.authenticate('criiptoVerifyRedirect', {}), (req, res) => {
  res.json(req.user);
});
app.get('/logout', redirectPassport.logout.bind(redirectPassport));
app.get('/error', function (req, res, next) {
  res.json({
    error: req.query.error,
    error_description: req.query.error_description,
  });
});

Plain express


const CriiptoVerifyExpressRedirect = require('@criipto/verify-express').CriiptoVerifyExpressRedirect;

const expressRedirect = new CriiptoVerifyExpressRedirect({
  domain: "{{YOUR_CRIIPTO_DOMAIN}}",
  clientID: "{{YOUR_CLIENT_ID}}",
  clientSecret: "{{YOUR_CLIENT_SECRET}}",
  // Should match an express route that is an allowed callback URL in your application
  // This route should also have the authentication middleware applied.
  redirectUri: '/login',
  postLogoutRedirectUri: '/',

  // Amend authorize request if you wish
  beforeAuthorize(req, options) {
    return {
      ...options,
      acr_values: req.query.acr_values,
      prompt: req.query.prompt
    }
  }
});

// Route to both trigger and handle redirect
app.get('/login', expressRedirect.middleware({failureRedirect: '/error', successReturnToOrRedirect: '/plain/protected'}), (req, res) => {
  res.json(req.claims);
});
app.get('/protected', expressRedirect.middleware({}), (req, res) => {
  res.json(req.claims);
});

app.get('/logout', expressRedirect.logout.bind(expressRedirect));

app.get('/error', function (req, res, next) {
  res.json({
    error: req.query.error,
    error_description: req.query.error_description,
  });
});

Single-page application

SPAs can utilize frontend frameworks like @criipto/auth-js or @criipto/verify-react to handle the login in the frontend and then send a Bearer token to their API.

You must register a Callback URL on your Criipto Application matching the href of the URL you are triggering SPA login from.

Passport

// server.js
const express = require('express');
const passport = require('passport');
const CriiptoVerifyJwtPassportStrategy = require('@criipto/verify-express').CriiptoVerifyJwtPassportStrategy;

const app = express();

app.use(passport.initialize());
passport.serializeUser(function(user, done) {
  done(null, user);
});
passport.deserializeUser(function(user, done) {
  done(null, user);
});

passport.use(
  'criiptoVerifyJwt',
  new CriiptoVerifyJwtPassportStrategy({
    domain: "{{YOUR_CRIIPTO_DOMAIN}}",
    clientID: "{{YOUR_CLIENT_ID}}"
  },
  // Map claims to an express user
  async (jwtClaims) => {
    return jwtClaims;
  })
);

app.get('/jwt-protected-route', passport.authenticate('criiptoVerifyJwt', { session: false }), (req, res) => {
  res.json({
    ...req.user,
    passport: 'says hi'
  });
});

// client.js
const {id_token} = login();

fetch(`{server}/jwt-protected-route`, {
  headers: {
    Authorization: `Bearer ${id_token}`
  }
})

Plain express

// server.js

const express = require('express');
const CriiptoVerifyExpressJwt = require('@criipto/verify-express').CriiptoVerifyExpressJwt;
const app = express();

const expressJwt = new CriiptoVerifyExpressJwt({
  domain: "{{YOUR_CRIIPTO_DOMAIN}}",
  clientID: "{{YOUR_CLIENT_ID}}"
});

app.get('/jwt-protected-route', expressJwt.middleware(), (req, res) => {
  res.json({
    ...req.user,
    express: 'says hi'
  });
});

// client.js
const {id_token} = login();

fetch(`{server}/jwt-protected-route`, {
  headers: {
    Authorization: `Bearer ${id_token}`
  }
})