npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

passport-curity

v1.1.1

Published

Curity authentication strategy for Passport.js

Downloads

659

Readme

passport-curity

Quality Availability

passport-curity is a strategy for the passport library which enables an effortless integration with the Curity Identity Server.

It covers different scenarios of authenticating a user with the Curity Identity Server using the Open ID Connect protocol. If you're looking for an option to secure your endpoints in an Express API app with JWTs have a look at this library: express-oauth-jwt.

Installation

You can install the strategy with npm.

npm install passport-curity

Usage

In order to properly use the strategy you need to provide it with an openid connect client, the parameters that should be used with the authorization request as well as a verify callback, which you can use to process the incoming tokens and profile information. (See passport documentation to read more about the verify callback.)

Configure the client

You can use a convenience method discoverAndCreateClient to quickly setup the oidc client needed by this strategy. The method returns a Promise.

discoverAndCreateClient({
    issuerUrl: 'https://example.com',
    clientID: "my-client",
    clientSecret: "S3cret!",
    redirectUris: ["http://localhost:3000/callback"],
    responseTypes: ['code', 'token']
}).then((client) => {
    // Create strategy, configure and start the Express app.
});
  • issuerUrl is the URL to your instance of the Curity Identity Server. This address is used to access the .well-known endpoints exposed by the Curity Identity Server in order to obtain all the necessary configuration of the different OAuth and OpenID Connect endpoints.
  • clientID, clientSecret and redirectUris should be filled with data used by your client registered with the Curity Identity Server.
  • responseTypes parameters tells the client which authorization flows will be used by the strategy. This parameter is optional and defaults to ["code"].

If you rather have more control on creating the client have a look at the openid-client documentation to check the available options.

The verify callback

Each passport strategy accepts a verify callback which can be used to properly handle incoming authorization credentials in the Express app. E.g. create a new user account, save tokens to a database, etc. The verify callback used by the passport-curity strategy has the following signature:

function(accessToken, refreshToken, profile, callback) {
    callback(null, profile); // The callback function needs to be called from the verify callback.
}
  • accessToken and refreshToken are strings containing the respective tokens, or null if the given token was not returned by the given flow.
  • profile contains a map of all the claims present in the ID token. If the ID token was not returned in the response the strategy can fall back to requesting this data from the userinfo endpoint. See Customization to check how this can be enabled.

Authorization code flow

Here's a minimal example showing passport configured with the Curity strategy using the authorization code flow:

const express = require('express');

const app = express();
const passport = require('passport');
const CurityStrategy = require('passport-curity').Strategy;
const discoverAndCreateClient = require('passport-curity').discoverAndCreateClient;

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

const session = {
    secret: "someSecret",
    cookie: {},
    resave: false,
    saveUninitialized: false
  };

(async () => {
    // Create the oidc client
    const client = await discoverAndCreateClient({
        issuerUrl: 'https://example.com',
        clientID: "my-client",
        clientSecret: "S3cret!",
        redirectUris: ["http://localhost:3000/callback"]
    });

    // Create the Curity Strategy object
    const strategy = new CurityStrategy({
        client,
        params: {
            scope: "openid"
        }
    }, function(accessToken, refreshToken, profile, cb) {
        cb(null, profile);
    });

    // Initialize the passport middleware
    passport.use(strategy);

    passport.serializeUser((user, done) => {
        done(null, user);
    });

    passport.deserializeUser((user, done) => {
        done(null, user);
    });

    app.use(expressSession(session));

    app.use(passport.initialize());
    app.use(passport.session());

    // The /authorize endpoint initializes the authorization process
    app.get('/authorize', passport.authenticate('curity'));

    // The callback endpoint is where the Curity Identity Server redirects the user back after positive authentication
    app.get('/callback', passport.authenticate('curity', { failureRedirect: '/failed', failureMessage: true }), function(req, res) {
        res.redirect('/');
    });

    // When a user authenticates and authorizes your app you will be able to access their data in the request object.
    app.get('/', function(req, res) {
        res.json({ profile: req.user });
    });

    app.get('/failed', function(req, res) {
        res.json({ message: "Auth failed: " + req.session.messages[0] });
    });

    app.listen(3000, function() {
        console.log("Server started on port 3000");
    });
})();

Implicit flow

In order to use the implicit flow instead of the code flow you need to change a few lines in the example above:

  1. Configure the client with appropriate response types:
const client = await discoverAndCreateClient({
        issuerUrl: 'https://example.com',
        clientID: "my-client",
        clientSecret: "S3cret!",
        redirectUris: ["http://localhost:3000/callback"],
        responseTypes: ["token"]
    });

Note: If you only need the ID token you can instead use the response type id_token.

  1. Set the response_mode for the strategy to form_post so that the tokens are posted back to the callback endpoint, not sent in the fragment part of the url.
const strategy = new CurityStrategy({
        client,
        params: {
            scope: "openid",
            response_mode: "form_post"
        }
    }, function(accessToken, refreshToken, profile, cb) {
        ...
    });

Note: If you configure the client with more response types then you have to add a response_type parameter to the params map.

  1. Configure the callback endpoint to accept POST requests and to properly parse the body of the request:
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));

app.post('/auth/example/callback', passport.authenticate('curity', { failureRedirect: '/failed', failureMessage: true}), function(req, res) {
        res.redirect('/');
    });

Obtaining both: ID token and access token

It's possible to obtain both the ID token and the access token in one request in an implicit flow. To do that just provide both response types together as one value:

const client = await discoverAndCreateClient({
        issuerUrl: 'https://example.com',
        clientID: "my-client",
        clientSecret: "S3cret!",
        redirectUris: ["http://localhost:3000/callback"],
        responseTypes: ["token id_token"]
    });

Customization

userinfo fallback

The user profile data will normally be decoded from the ID token. However, if the ID token is not present in the response the strategy can fall back to requesting the userinfo endpoint of the Curity Identity Server. By default this option is disabled. If you want to enable it add fallbackToUserInfoRequest: true to the strategy options:

const strategy = new CurityStrategy({
    client,
    params: {
        scope: "openid"
    },
    fallbackToUserInfoRequest: true
}, function(accessToken, refreshToken, profile, cb) {
    ...
});

Setting authorization parameters

The params map in the Curity strategy options is a map of the parameters that are sent together with the authorization request. E.g. you can set the prompt parameter to use the feature as described in the OpenID Connect protocol. So if you add to the params map prompt: "login", then you will always see a login page regardless of the user being logged in or not.

Another popular parameter you can use is the scope parameter, where you can provide a string with space-delimited scope tokens - the ones that your app need in order to properly access the user's resources. E.g. scope: "openid profile email".

Below is the list of all the parameters that can be set for requests made by this strategy:

  • acr_values
  • audience
  • claims.id_token
  • claims.userinfo
  • claims_locales
  • client_id
  • code_challenge_method
  • code_challenge
  • display
  • id_token_hint
  • login_hint
  • max_age
  • nonce
  • prompt
  • redirect_uri
  • registration
  • request_uri
  • request
  • resource
  • response_mode
  • response_type
  • scope
  • ui_locales

Other customization

The Curity passport strategy is based on the openid-client library written by Filip Skokan. If you need some more customization and fine-grained tuning you can have a look the openid-client documentation.

Questions and Support

For questions and support, contact Curity AB:

Curity AB

[email protected]

https://curity.io

Copyright (C) 2020 Curity AB.