Skip to main content

OpenID Provider framework for sanic

Project description

https://img.shields.io/pypi/v/sanic_openid_connect_provider.svg https://img.shields.io/travis/terrycain/sanic-openid-provider.svg Updates

It’s a work-in-progress, Alpha stage I would say. If anyone finds this useful / wants to use it, drop an issue I’d be more than happy to fix it up so its actually helpful to someone other than myself.

Last time I checked it passed around 82 / 93 of the OpenID Connect Provider Certification tests that appear when you tick webfinger, dynamic info discovery, dynamic client registration and select code response type.

It’s pretty usable for the authorization code flow. Still needs a fair amount of re-architecting and cleaning up but I’m trying to make it so you can plug it into various backends like DynamoDB/Redis for token/client storage.

Docs and examples will be coming soon.

Preconditions

The package expects sanic_jinja2 and sanic_session to be in use and configured.

Testing

As said above it passes most of the OpenID tests I’ve ran against it. Below are the ones I haven’t passed yet

Signature + Encryption

Haven’t figured out why the userinfo enc/sig doesnt work yet.

  • OP-IDToken-SigEnc

  • OP-UserInfo-SigEnc

  • OP-request_uri-SigEnc

Claims

Haven’t got around to this bit yet

  • OP-claims-acr-essential

  • OP-claims-acr-voluntary

  • OP-claims-acr=1

Misc Request Parameters

Haven’t dealt with this yet.

  • OP-Req-acr_values

Key Rotation

Need some methods to rotate keys

  • OP-Rotation-OP-Enc

  • OP-Rotation-OP-Sig

  • OP-Rotation-RP-Enc

  • OP-Rotation-RP-Sig

Key creation

RSA Key

openssl genrsa -nodes -out rsa.pem 4096

ECDSA Key

openssl ecparam -name prime256v1 -genkey -noout -out ec.pem
openssl ec -in ec.pem -pubout -out ec.pub

OpenID Connect Node Example

app.js

/*
*
* Note: This example is a "full" example that registers a new client with the OIDC server each time. This returns a client ID and secret.
*       In reality, you should only register once per service and then save the client information for future use.
*       I would advise using this script to register your client and test it - It will console.log the ID and secret which you can then hardcode:
*       https://github.com/panva/node-openid-client#manually-recommended
*
*   In production, I import a modified version of this script with promise support. Make sure it's finished discovery before defining your
*   error handlers!
*/

//******* Config
const config = {
    /* jshint ignore:start */
    //Server we're going to auth with
    authServer: "https://authserver",
    //Access token provided by admin for initial registration
    initialAccessToken: "dcb89d4c-fec4-11e8-8eb2-f2801f1b9fd1",
    //Listen port
    port: 3000,
    //All the settings required to register our client
    registration: {
        //IDP prefers ES256 encryption
        id_token_signed_response_alg: 'ES256',
        //Array of all potential redirect URI's
        redirect_uris: ["http://127.0.0.1:3000/callback", "http://127.0.0.1/callback"],
        //String space-delimited list of all potentially required scopes
        scope: "openid email profile",
        grant_types: ['authorization_code'],
        application_type: 'web',
        //Name of client - For reference only
        client_name: 'Some client',
        subject_type: 'public',
        response_types: ["code"]
    },
    auth: {
        //uri the IDP redirects to after authentication - Must be in the array above
        redirect_uri: "http://127.0.0.1:3000/callback",
        //Scopes we want for authentication
        scope: "openid email profile",
        id_token_signed_response_alg: 'ES256'
    }
    /* jshint ignore:end */
}

//******* End Config


const { Issuer } = require('openid-client');
const { Strategy } = require('openid-client');
const session = require('express-session');
const express = require('express');
const app = express();
const passport = require('passport');

// Set up Express sessions in memory - Please don't do this in production, use something to store your sessions
// so we can load balance.
app.use(session({
    secret: 'asupersecretpassword',
    resave: true,
    saveUninitialized: true
}));
//Make sure to initialise before we start discovery
app.use(passport.initialize());
app.use(passport.session());

//Discover settings from OID server
Issuer.discover(config.authServer)
    .then(customIssuer => {

        const opts = { initialAccessToken: config.initialAccessToken };
        const metadata = config.registration;

        // You only need to do client registration once (ever) - You should do it during development and then hardcode the client id and secret
        // Below is an example of a hardcoded client, rather than a client that registers each time
        // See more in the docs: https://github.com/panva/node-openid-client#manually-recommended

            // const client = new customIssuer.Client({
            //         client_id: '83fc3323d3c045a4',
            //         client_secret: '7f9b5e1721a244c989d011839595b766',
            //         id_token_signed_response_alg: 'ES256'
            //     });

         customIssuer.Client.register(metadata, opts)
           .then(client => {
            console.log("!!!!! Save this information for re-use later! !!!!!")
            console.log("Client ID:     " + client.client_id)
            console.log("Client Secret: " + client.client_secret)
            console.log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
            console.log("Metadata:      " + JSON.stringify(client.metadata, null, 2))

            const params = config.auth;
            // Setting up our strategy + validation function
            passport.use('oidc', new Strategy({client, params, passReqToCallback: null, sessionKey: null, usePKCE: false}, (tokenset, userinfo, done) => {
                return done(null, userinfo)
            }));

            passport.serializeUser((user, done) => {
                // This is where you'd get any extra locally-stored data from the database or something for accessing in req.user
                done(null, user);
            });

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

            // GET /login will start authentication
            app.get('/login', passport.authenticate('oidc'));

            // GET /callback redirected from IDP with code
            app.get('/callback', passport.authenticate('oidc', {
              successRedirect: '/',
              failureRedirect: '/login'
            }));

            // Force every other request to check if user is authed, if not then redirect to /login and start auth
            app.use((req, res, next) => {
                if (!req.user) {
                    res.redirect('/login');
                } else {
                    next();
                }
            })

            // Example authenticated endpoint
            app.get('/',(req, res) => {
                console.log(`User ${req.user.name} has logged in.`);
                res.send(req.user);
            })


            app.listen(config.port, () => console.log(`Example app listening on port ${config.port}!`))

        });
    })

package.json

{
  "name": "openidtest",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.16.4",
    "express-session": "^1.15.6",
    "passport": "^0.4.0",
    "passport-openid-connect": "^0.1.0"
  }
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sanic_openid_connect_provider-0.6.0.tar.gz (44.0 kB view details)

Uploaded Source

Built Distribution

File details

Details for the file sanic_openid_connect_provider-0.6.0.tar.gz.

File metadata

  • Download URL: sanic_openid_connect_provider-0.6.0.tar.gz
  • Upload date:
  • Size: 44.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.35.0 CPython/3.6.7

File hashes

Hashes for sanic_openid_connect_provider-0.6.0.tar.gz
Algorithm Hash digest
SHA256 e0d85b024e6a6edf0ef14518f548d1458cc7f6f6929be7648548a2381cae7d84
MD5 4346e9ac08191d9e9216f9786d5189b6
BLAKE2b-256 3d51ebad112a21b6e56f5a9f6b36022c7fb849f31ebc3bcb3edf23baa3bd61c6

See more details on using hashes here.

Provenance

File details

Details for the file sanic_openid_connect_provider-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: sanic_openid_connect_provider-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 44.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.35.0 CPython/3.6.7

File hashes

Hashes for sanic_openid_connect_provider-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 72523a3c6081c0d088eb2b78d5beab2344fdcd6a880289b36517f0f77535f6c4
MD5 733ee79a58fb39336ad8e13150e81cd4
BLAKE2b-256 5bc00d7f01a9315a7d71fab2073bda984e9938ac9456394ba232d0a04d3c585d

See more details on using hashes here.

Provenance

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page