├── .env.example ├── .gitignore ├── CREDITS.md ├── LICENSE.md ├── README.md ├── app.js ├── bin └── www ├── demo.gif ├── keys └── login-gov │ ├── expressjs_demo_sp.crt │ ├── expressjs_demo_sp.key │ └── openssl.conf ├── login-gov.js ├── package-lock.json ├── package.json ├── public ├── images │ └── login-gov.svg └── stylesheets │ ├── basscss.min.css │ └── style.css ├── routes ├── auth │ └── login-gov.js ├── index.js └── users.js └── views ├── error.ejs ├── index.ejs ├── page.ejs ├── page_content.ejs └── success.ejs /.env.example: -------------------------------------------------------------------------------- 1 | # 2 | # This is an example environment variable configuration file. 3 | # ... see https://github.com/motdotla/dotenv#usage for more information on how to use a .env file. 4 | # 5 | 6 | #DISCOVERY_URL="https://idp.dev.identitysandbox.gov" 7 | #DISCOVERY_URL="https://idp.int.identitysandbox.gov" 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | .DS_Store 4 | 5 | .env 6 | -------------------------------------------------------------------------------- /CREDITS.md: -------------------------------------------------------------------------------- 1 | # Credits, Notes, and Reference 2 | 3 | ## Links 4 | 5 | ### Login.gov 6 | 7 | + [Login.gov developer documentation](https://developers.login.gov/) 8 | + [Login.gov OIDC documentation](https://developers.login.gov/openid-connect/#developer-portal) 9 | + [Registered Login.gov Service Providers](https://github.com/18F/identity-idp/blob/master/config/service_providers.yml#L125-L129) 10 | + [Login.gov OIDC Sinatra Client](https://github.com/18F/identity-sp-sinatra) 11 | + [Login.gov SAML Rails Client](https://github.com/18F/identity-sp-rails) 12 | + [18F's U.S. Forest Service Intake Module](https://github.com/18F/fs-intake-module/blob/master/server/src/auth/login-gov.es6) - a super helpful Login.gov client implementation using Express.js and Passport.js 13 | + Login.gov OIDC Auto-Discovery URLs: 14 | + https://localhost:3000/.well-known/openid-configuration 15 | + https://idp.int.login.gov/.well-known/openid-configuration 16 | + [Alternative run strategy](https://stackoverflow.com/a/42157085/670433) - essential solution for bypassing client request errors produced by the `openid-client` package 17 | + [Example service provider environment configuration](https://github.com/18F/identity-openidconnect-sinatra/blob/master/.env.example) 18 | 19 | ### Node.js and Express.js 20 | 21 | + [A previous Express.js project by the author](https://github.com/data-creative/express-on-rails-starter-app/blob/starter/app.js) 22 | + [A previous Express.js tutorial by the author](https://github.com/prof-rossetti/southernct-csc-443-01-201701/blob/master/projects/crud-application/checkpoints/) 23 | + [Running Express.js apps in debug mode](https://expressjs.com/en/guide/debugging.html) 24 | 25 | ### Passport.js 26 | 27 | + [Passport.js Docs](http://www.passportjs.org/docs/) 28 | + [Using multiple Passport strategies - gist](https://gist.github.com/joshbirk/1732068) 29 | + [Using multiple Passport strategies - issue comment](https://github.com/jaredhanson/passport/issues/287#issuecomment-58188179) 30 | 31 | ### Authentication and OIDC 32 | 33 | + [Node.js + Passport.js OIDC Demo / Walkthrough](https://github.com/srmoore/oidc_nodejs_demo) - very helpful for understanding OIDC mechanics and implementation using Passport.js 34 | + [`openid-client`](https://github.com/panva/node-openid-client) 35 | + [JSON Web Tokens (JWT)](https://jwt.io/) 36 | + [Converting PEM to JWK](https://github.com/dannycoates/pem-jwk) 37 | + [PEM vs CRT vs KEY](https://crypto.stackexchange.com/questions/43697/what-is-the-difference-between-pem-csr-key-and-crt) 38 | + [Node Jose](https://github.com/cisco/node-jose) 39 | 40 | ### Assets 41 | 42 | + [Login.gov SVG](https://github.com/18F/identity-sp-sinatra/blob/master/public/img/login-gov.svg) 43 | + [Stylesheet](https://github.com/18F/identity-sp-sinatra/blob/master/public/css/lib/basscss.min.css) 44 | + [Page Content](https://github.com/18F/identity-sp-sinatra/blob/master/views/success.erb) 45 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | As a work of the United States government, this project is in the 2 | public domain within the United States. 3 | 4 | Additionally, we waive copyright and related rights in the work 5 | worldwide through the CC0 1.0 Universal public domain dedication. 6 | 7 | ## CC0 1.0 Universal summary 8 | 9 | This is a human-readable summary of the [Legal Code (read the full text)](https://creativecommons.org/publicdomain/zero/1.0/legalcode). 10 | 11 | ### No copyright 12 | 13 | The person who associated a work with this deed has dedicated the work to 14 | the public domain by waiving all rights to the work worldwide 15 | under copyright law, including all related and neighboring rights, to the 16 | extent allowed by law. 17 | 18 | You can copy, modify, distribute and perform the work, even for commercial 19 | purposes, all without asking permission. 20 | 21 | ### Other information 22 | 23 | In no way are the patent or trademark rights of any person affected by CC0, 24 | nor are the rights that other persons may have in the work or in how the 25 | work is used, such as publicity or privacy rights. 26 | 27 | Unless expressly stated otherwise, the person who associated a work with 28 | this deed makes no warranties about the work, and disclaims liability for 29 | all uses of the work, to the fullest extent permitted by applicable law. 30 | When using or citing the work, you should not imply endorsement by the 31 | author or the affirmer. 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This sample SP has been retired. It was used for early prototyping for integrations with login.gov and has not been maintained. It has confirmed vulnerabilities and should not be used for production itegrations. 2 | 3 | For maintained examples of integrations with login.gov please refer to: 4 | 5 | - https://github.com/18F/identity-saml-sinatra 6 | - https://github.com/18F/identity-oidc-sinatra 7 | 8 | # identity-oidc-expressjs 9 | 10 | An example [Login.gov](https://login.gov/) client application which authenticates users via OpenID Connect (OIDC). Built with [Node.js](https://nodejs.org/en/), [Express.js](https://expressjs.com/), and [Passport.js](http://www.passportjs.org/docs/). Uses the [`openid-client`](https://github.com/panva/node-openid-client) package, a certified OpenID Relaying Party, to issue authentication requests. 11 | 12 | Demo: 13 | 14 |  15 | 16 | ## Prerequisites 17 | 18 | ### Install Dependencies 19 | 20 | Install Node.js (version 8.9.3), perhaps using NVM to do so. 21 | 22 | Install `nodemon` development server globally: 23 | 24 | ```sh 25 | npm install nodemon -g 26 | ``` 27 | 28 | Install package dependences: 29 | 30 | ```sh 31 | npm install 32 | ``` 33 | 34 | ### Choose a Login.gov Environment 35 | 36 | #### Sandbox Environment 37 | 38 | Set the `DISCOVERY_URL` environment variable to one of the sandbox urls: 39 | 40 | + `https://idp.dev.identitysandbox.gov` 41 | + `https://idp.int.identitysandbox.gov` (untested) 42 | 43 | #### Development Environment (Local Server) 44 | 45 | Set the `DISCOVERY_URL` environment variable to `http://localhost:3000`. 46 | 47 | Run a [Login.gov (`identity-idp`)](https://github.com/18F/identity-idp/) instance locally on port 3000: 48 | 49 | ```sh 50 | cd path/to/identity-idp 51 | 52 | bin/rails s -b 127.0.0.1 53 | bundle exec sidekiq --config config/sidekiq.yml 54 | mailcatcher -f 55 | ``` 56 | 57 | > NOTE: the `openid-client` package attempts to make various authentication requests to `127.0.0.1:3000`, but when the Login.gov instance is running normally on `localhost:3000` via the `make run` command, the `openid-client` requests won't be able to find it (produces `RequestError: connect ECONNREFUSED 127.0.0.1:3000` client errors). So a work-around for this issue is to run the Login.gov instance via the commands listed above. :smiley: 58 | 59 | ## Usage 60 | 61 | Run this client application on a local web server: 62 | 63 | ```sh 64 | DEBUG=identity-oidc-expressjs:* npm start # then view localhost:9393 in a browser 65 | ``` 66 | 67 | ## [License](LICENSE.md) 68 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); // use environment variables from .env file 2 | 3 | var express = require('express'); 4 | var path = require('path'); 5 | var favicon = require('serve-favicon'); 6 | var logger = require('morgan'); 7 | var cookieParser = require('cookie-parser'); 8 | var bodyParser = require('body-parser'); 9 | var passport = require('passport'); 10 | var session = require('express-session'); 11 | 12 | var loginGov = require('./login-gov'); 13 | 14 | var loginGovRoutes = require('./routes/auth/login-gov'); 15 | var index = require('./routes/index'); 16 | var users = require('./routes/users'); 17 | 18 | var app = express(); 19 | 20 | app.locals.title = "Login.gov OIDC Client (Express.js)"; 21 | 22 | // view engine setup 23 | app.set('views', path.join(__dirname, 'views')); 24 | app.set('view engine', 'ejs'); 25 | 26 | // uncomment after placing your favicon in /public 27 | //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); 28 | app.use(logger('dev')); 29 | app.use(bodyParser.json()); 30 | app.use(bodyParser.urlencoded({ extended: false })); 31 | app.use(cookieParser()); 32 | app.use(express.static(path.join(__dirname, 'public'))); 33 | 34 | app.use(session({ 35 | secret: process.env.SESSION_SECRET || 'identity-oidc-expressjs-secret', 36 | name: 'identity-oidc-expressjs-session', 37 | resave: false, 38 | saveUninitialized: true 39 | })); 40 | 41 | app.use(passport.initialize()); 42 | app.use(passport.session()); 43 | 44 | passport.serializeUser(function(user, done) { done(null, user); }); 45 | passport.deserializeUser(function(user, done) { done( null, user); }); // this is where you might fetch a user record from the database. see http://www.passportjs.org/docs/configure/#sessions 46 | 47 | loginGov.configure(passport, 1); // configure LOA1 strategy 48 | loginGov.configure(passport, 3); // configure LOA3 strategy 49 | 50 | loginGovRoutes.configure(app, passport); // use login.gov auth routes 51 | app.use('/', index); 52 | app.use('/users', users); 53 | 54 | // catch 404 and forward to error handler 55 | app.use(function(req, res, next) { 56 | var err = new Error('Not Found'); 57 | err.status = 404; 58 | next(err); 59 | }); 60 | 61 | // error handler 62 | app.use(function(err, req, res, next) { 63 | // set locals, only providing error in development 64 | res.locals.message = err.message; 65 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 66 | 67 | // render the error page 68 | res.status(err.status || 500); 69 | res.render('error'); 70 | }); 71 | 72 | module.exports = app; 73 | -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('identity-oidc-expressjs:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort('9393'); // var port = normalizePort(process.env.PORT || '9393') // FYI login.gov as currently configured only recognizes this example client app when run on port 9393 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/18F/identity-oidc-expressjs/4e98ff709d1ca5fd307913f48a234041a16ab348/demo.gif -------------------------------------------------------------------------------- /keys/login-gov/expressjs_demo_sp.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDnDCCAoQCCQC825/W4H+z7zANBgkqhkiG9w0BAQsFADCBjzEmMCQGA1UEAwwd 3 | aHR0cHM6Ly9kZXZlbG9wZXJzLmxvZ2luLmdvdi8xDDAKBgNVBAoMA0dTQTEMMAoG 4 | A1UECwwDMThmMRMwEQYDVQQHDApXYXNoaW5ndG9uMQswCQYDVQQIDAJEQzELMAkG 5 | A1UEBhMCVVMxGjAYBgkqhkiG9w0BCQEWCzE4ZkBnc2EuZ292MB4XDTE4MDEwNDAy 6 | MzgxN1oXDTE5MDEwNDAyMzgxN1owgY8xJjAkBgNVBAMMHWh0dHBzOi8vZGV2ZWxv 7 | cGVycy5sb2dpbi5nb3YvMQwwCgYDVQQKDANHU0ExDDAKBgNVBAsMAzE4ZjETMBEG 8 | A1UEBwwKV2FzaGluZ3RvbjELMAkGA1UECAwCREMxCzAJBgNVBAYTAlVTMRowGAYJ 9 | KoZIhvcNAQkBFgsxOGZAZ3NhLmdvdjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC 10 | AQoCggEBAMXwprn0ZJJs6sZp0PdDL9NzslFXtns6E6MVIPpEt/DeMQ+BJglYkGzH 11 | F1BueC2zYFJKtMzT696gfYnOEhOxDgsEH6kXr8ChX/AWj+FlmiSCfJjsu1c609tY 12 | SaNDbXCrFY51yqtypFlidFNWXWqtmrnQgk6vv32kH5Y41UfY3hg4FPBk1OkRLPgh 13 | lwUZSMRS9x1yZ2k5CbHSXiykO++TX/eB8e5xkvW5Lcq1ogasDe2tyyBWqxoxgm3J 14 | aCX+uGWL/SDqdtGq9PnhshtBCURAYVLz5k1a/0UFvuuzJUDiTfeEP+cZvMrfgMx/ 15 | NHaTfCYjw1T9E6QJkn4JVGnKad9Z7CsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA 16 | dz3EIf4ouzbHDdue3kmnNQquFt6D4tLYlRqUSCTu9xV14Kmk2jF4D0CHeC+f4AHP 17 | 9Xv7Ew6+rN8HREsfaEcT26GSxf0Sa0ZM+2XGU845VRk5q+kTSp1v8DqCC3dJpcuA 18 | BUVG4dA/7RRb+jpMpygHK0DwIo78eH2F4ZsfgHXtbIMCvVpZi01f9/8NGrEwnOOn 19 | zaUZfgabNEyc6FwI1lr0kZ2JbKV9bAMYk0cM6drepZef/mp0l3stzNt98XJkoHVk 20 | nQjFnWx6jrTZ69dacMTooJw+izaqpa3nPFIeRf5VY1x4QooAvrKoId2UP9DZjyVo 21 | TvGhl3oFNpM4DgJT8yDoEg== 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /keys/login-gov/expressjs_demo_sp.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAxfCmufRkkmzqxmnQ90Mv03OyUVe2ezoToxUg+kS38N4xD4Em 3 | CViQbMcXUG54LbNgUkq0zNPr3qB9ic4SE7EOCwQfqRevwKFf8BaP4WWaJIJ8mOy7 4 | VzrT21hJo0NtcKsVjnXKq3KkWWJ0U1Zdaq2audCCTq+/faQfljjVR9jeGDgU8GTU 5 | 6REs+CGXBRlIxFL3HXJnaTkJsdJeLKQ775Nf94Hx7nGS9bktyrWiBqwN7a3LIFar 6 | GjGCbcloJf64ZYv9IOp20ar0+eGyG0EJREBhUvPmTVr/RQW+67MlQOJN94Q/5xm8 7 | yt+AzH80dpN8JiPDVP0TpAmSfglUacpp31nsKwIDAQABAoIBABb9iJ/4nuXS+MHq 8 | 8HaHuzpYKdIA2hUd/cHnZlkrOiIj7JbcbUqQmtXHmhGhgxvrxbhJLQ7NXowRIAOt 9 | h7P50KO+6t58/dDl7Xq5ZCTN5EVxUn+An5HWJ11Gt+baog+AD5ToYY3gVu563QAA 10 | /AC0AVCrwzbYeulg8rpEB6G8sq8lQB2M6Tk95yA28fBMFVYQr6uD7C3NrBfcouyj 11 | Dl6MFPt0Tlxv8emu6kkRA/52wTT49VlkYAfd69U5gqtQMJ5+NvW/kBzUL9gxb/lb 12 | eWMNOkROu1N2rpxij1QDVC1Tp708OBlcTw2wQSf3lrTYcLcLXLZVkcYDtEAMnR1Z 13 | RkexrIECgYEA4+9AvaRWCkgFJ30wmDsAuxOn3nDYTzPxfSbattyVaT+hSMbiggRT 14 | EmqZ8tptbYSgx35s+ZFeT8XiU8XulYmXoEUmUopiYF3m8MMe5uFtLrpfP5s/SkPE 15 | 9Jly2jfm6NQRP0ute6AsvDQxTBYPEQrrtve4ulRIuPNo8qNE5AY0WBsCgYEA3k/w 16 | Ejf7BbGn3XZ8vv4nqpxNTZY/TXmvAuFDs5DTEPdUbNzR+vXx4P4QNsp8ybfxoK2O 17 | +eaF2z5j6/1+t7ABF/uyubjP47Jm6EMqhF6RGg+Z6PFEZe+XTJbE7YTACLCzh3tk 18 | cC7kT9H9gbhj8g05zigwCDURWo8JaAg5Qo2uHTECgYAqXlC0b5Wmt5htrLGZum36 19 | WD799A/hORCMaOqCzyHevHsoYf+8lz0x0Sron31zvBF+w5tSEJltTqUxWTtuBHNw 20 | 0Sm8cgizTQEeg8Z8uC5pXy9RTXRIQ6yaouNceMOtR64lC9YlgrKOEU2QjREj49nI 21 | 2uc1i3ExH93ELGEj2ZtlPQKBgHTUW5yncLLgVxBqeUpB9ISTmYhhoijL/u4rhdGz 22 | FUjAQczoCy2w3IlZ2xmANi4oDcJcE1w/Ci9azVYypMpRo3GAI7+4YQAPPEdpLMnd 23 | jLG+ayrgyAot7Dwiq6EK94RZoC9d6D2QVwmfmHL4fQWyb6NouT1G7jTCILZcRAM2 24 | w76xAoGBAMfUtoy2V47Yliep63wtSXXJoINd6Y9A5vJaZr1ryaVUp53tVcjqHXV6 25 | 0ArVT2QHom52yfyidOVu37q9LauQiadruOeRt2acLJN9ULFU0kn0KrwvB1A9QzvZ 26 | SomsxTaEYJfYtpWPionOsvyJBjvcijmWQYzw3Lla8GaiefCyF1Pw 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /keys/login-gov/openssl.conf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | default_bits = 2048 3 | distinguished_name = req_distinguished_name 4 | prompt = no 5 | 6 | [ req_distinguished_name ] 7 | commonName = https://developers.login.gov/ 8 | organizationName = GSA 9 | organizationalUnitName = 18f 10 | localityName = Washington 11 | stateOrProvinceName = DC 12 | countryName = US 13 | emailAddress = 18f@gsa.gov 14 | -------------------------------------------------------------------------------- /login-gov.js: -------------------------------------------------------------------------------- 1 | var crypto = require('crypto'); 2 | var fs = require('fs'); 3 | var pem2jwk = require('pem-jwk').pem2jwk; 4 | var jose = require('node-jose'); 5 | var Issuer = require('openid-client').Issuer; 6 | var Strategy = require('openid-client').Strategy; 7 | 8 | var loginGov = {}; 9 | 10 | var keyFile = './keys/login-gov/expressjs_demo_sp.key'; 11 | var key = fs.readFileSync(keyFile, 'ascii'); 12 | var jwk = pem2jwk(key); 13 | var keys = [jwk]; 14 | 15 | loginGov.discoveryUrl = process.env.DISCOVERY_URL || 'http://localhost:3000'; 16 | 17 | var clientOptions = { 18 | client_id: 'urn:gov:gsa:openidconnect:sp:expressjs', 19 | token_endpoint_auth_method: 'private_key_jwt', 20 | id_token_signed_response_alg: 'RS256' 21 | }; 22 | 23 | function strategyParams(loaNumber){ 24 | return { 25 | response_type: 'code', 26 | acr_values: `http://idmanagement.gov/ns/assurance/loa/${loaNumber}`, 27 | scope: 'openid email address phone profile:birthdate profile:name profile social_security_number', 28 | redirect_uri: `http://localhost:9393/auth/login-gov/callback/loa-${loaNumber}`, 29 | nonce: loginGov.randomString(32), 30 | state: loginGov.randomString(32), 31 | prompt: 'select_account' 32 | }; 33 | }; 34 | 35 | loginGov.configure = function(passport, loaNumber){ 36 | if (parseInt(loaNumber) != 1 && parseInt(loaNumber) != 3) { throw "OOPS PLEASE CHOOSE A VALID LOA (expecting '1' OR '3')" }; 37 | 38 | Promise.all([ 39 | jose.JWK.asKeyStore(keys), 40 | Issuer.discover(loginGov.discoveryUrl) 41 | ]).then(function([keystore, issuer]){ 42 | loginGov.issuer = issuer; // allow subsequent access to issuer.end_session_endpoint (required during RP-Initiated Logout) 43 | 44 | var client = new issuer.Client(clientOptions, keystore); 45 | 46 | var params = strategyParams(loaNumber); 47 | 48 | var strategy = new Strategy({client: client, params: params}, function(tokenset, userinfo, done) { 49 | console.log("TOKEN SET", tokenset); 50 | console.log("USER INFO", userinfo); 51 | userinfo.token = tokenset.id_token; // required for RP-Initiated Logout 52 | userinfo.state = params.state; // required for RP-Initiated Logout 53 | return done(null, userinfo); 54 | }); 55 | 56 | passport.use(`oidc-loa-${loaNumber}`, strategy); 57 | 58 | console.log("LOGIN.GOV CONFIGURATION SUCCESS", `(LOA${loaNumber})`); 59 | 60 | }).catch(function(err){ 61 | console.log("LOGIN.GOV CONFIGURATION ERROR", err); 62 | }); 63 | }; 64 | 65 | loginGov.randomString = function(length) { 66 | return crypto.randomBytes(length).toString('hex'); // source: https://github.com/18F/fs-permit-platform/blob/c613a73ae320980e226d301d0b34881f9d954758/server/src/util.es6#L232-L237 67 | }; 68 | 69 | module.exports = loginGov; 70 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "identity-oidc-expressjs", 3 | "version": "0.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "asn1.js": { 8 | "version": "1.0.3", 9 | "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-1.0.3.tgz", 10 | "integrity": "sha1-KBuj7B8kSP52X5Kk7s+IP+E2S1Q=", 11 | "requires": { 12 | "bn.js": "1.3.0", 13 | "inherits": "2.0.3", 14 | "minimalistic-assert": "1.0.0" 15 | } 16 | }, 17 | "basic-auth": { 18 | "version": "2.0.1", 19 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", 20 | "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", 21 | "requires": { 22 | "safe-buffer": "5.1.2" 23 | } 24 | }, 25 | "bn.js": { 26 | "version": "1.3.0", 27 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-1.3.0.tgz", 28 | "integrity": "sha1-DbTL+W+PI7dC9by50ap6mZSgXoM=", 29 | "optional": true 30 | }, 31 | "body-parser": { 32 | "version": "1.18.2", 33 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", 34 | "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", 35 | "requires": { 36 | "bytes": "3.0.0", 37 | "content-type": "1.0.4", 38 | "debug": "2.6.9", 39 | "depd": "1.1.1", 40 | "http-errors": "1.6.2", 41 | "iconv-lite": "0.4.19", 42 | "on-finished": "2.3.0", 43 | "qs": "6.5.1", 44 | "raw-body": "2.3.2", 45 | "type-is": "1.6.15" 46 | }, 47 | "dependencies": { 48 | "bytes": { 49 | "version": "3.0.0", 50 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 51 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 52 | }, 53 | "content-type": { 54 | "version": "1.0.4", 55 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 56 | "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=" 57 | }, 58 | "depd": { 59 | "version": "1.1.1", 60 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 61 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 62 | }, 63 | "http-errors": { 64 | "version": "1.6.2", 65 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 66 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 67 | "requires": { 68 | "depd": "1.1.1", 69 | "inherits": "2.0.3", 70 | "setprototypeof": "1.0.3", 71 | "statuses": "1.4.0" 72 | }, 73 | "dependencies": { 74 | "inherits": { 75 | "version": "2.0.3", 76 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 77 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 78 | }, 79 | "setprototypeof": { 80 | "version": "1.0.3", 81 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 82 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 83 | }, 84 | "statuses": { 85 | "version": "1.4.0", 86 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 87 | "integrity": "sha1-u3PURtonlhBu/MG2AaJT1sRr0Ic=" 88 | } 89 | } 90 | }, 91 | "iconv-lite": { 92 | "version": "0.4.19", 93 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 94 | "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=" 95 | }, 96 | "on-finished": { 97 | "version": "2.3.0", 98 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 99 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 100 | "requires": { 101 | "ee-first": "1.1.1" 102 | }, 103 | "dependencies": { 104 | "ee-first": { 105 | "version": "1.1.1", 106 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 107 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 108 | } 109 | } 110 | }, 111 | "qs": { 112 | "version": "6.5.1", 113 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", 114 | "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=" 115 | }, 116 | "raw-body": { 117 | "version": "2.3.2", 118 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 119 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 120 | "requires": { 121 | "bytes": "3.0.0", 122 | "http-errors": "1.6.2", 123 | "iconv-lite": "0.4.19", 124 | "unpipe": "1.0.0" 125 | }, 126 | "dependencies": { 127 | "unpipe": { 128 | "version": "1.0.0", 129 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 130 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 131 | } 132 | } 133 | }, 134 | "type-is": { 135 | "version": "1.6.15", 136 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", 137 | "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", 138 | "requires": { 139 | "media-typer": "0.3.0", 140 | "mime-types": "2.1.17" 141 | }, 142 | "dependencies": { 143 | "media-typer": { 144 | "version": "0.3.0", 145 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 146 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 147 | }, 148 | "mime-types": { 149 | "version": "2.1.17", 150 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", 151 | "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", 152 | "requires": { 153 | "mime-db": "1.30.0" 154 | }, 155 | "dependencies": { 156 | "mime-db": { 157 | "version": "1.30.0", 158 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", 159 | "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" 160 | } 161 | } 162 | } 163 | } 164 | } 165 | } 166 | }, 167 | "cookie-parser": { 168 | "version": "1.4.3", 169 | "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz", 170 | "integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=", 171 | "requires": { 172 | "cookie": "0.3.1", 173 | "cookie-signature": "1.0.6" 174 | }, 175 | "dependencies": { 176 | "cookie": { 177 | "version": "0.3.1", 178 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 179 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 180 | }, 181 | "cookie-signature": { 182 | "version": "1.0.6", 183 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 184 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 185 | } 186 | } 187 | }, 188 | "debug": { 189 | "version": "2.6.9", 190 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 191 | "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", 192 | "requires": { 193 | "ms": "2.0.0" 194 | }, 195 | "dependencies": { 196 | "ms": { 197 | "version": "2.0.0", 198 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 199 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 200 | } 201 | } 202 | }, 203 | "depd": { 204 | "version": "1.1.2", 205 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 206 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 207 | }, 208 | "dotenv": { 209 | "version": "4.0.0", 210 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", 211 | "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=" 212 | }, 213 | "ee-first": { 214 | "version": "1.1.1", 215 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 216 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 217 | }, 218 | "ejs": { 219 | "version": "2.5.7", 220 | "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", 221 | "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=" 222 | }, 223 | "express": { 224 | "version": "4.15.5", 225 | "resolved": "https://registry.npmjs.org/express/-/express-4.15.5.tgz", 226 | "integrity": "sha1-ZwI1ypWYiQpa6BcLg9tyK4Qu2Sc=", 227 | "requires": { 228 | "accepts": "1.3.4", 229 | "array-flatten": "1.1.1", 230 | "content-disposition": "0.5.2", 231 | "content-type": "1.0.4", 232 | "cookie": "0.3.1", 233 | "cookie-signature": "1.0.6", 234 | "debug": "2.6.9", 235 | "depd": "1.1.1", 236 | "encodeurl": "1.0.1", 237 | "escape-html": "1.0.3", 238 | "etag": "1.8.1", 239 | "finalhandler": "1.0.6", 240 | "fresh": "0.5.2", 241 | "merge-descriptors": "1.0.1", 242 | "methods": "1.1.2", 243 | "on-finished": "2.3.0", 244 | "parseurl": "1.3.2", 245 | "path-to-regexp": "0.1.7", 246 | "proxy-addr": "1.1.5", 247 | "qs": "6.5.0", 248 | "range-parser": "1.2.0", 249 | "send": "0.15.6", 250 | "serve-static": "1.12.6", 251 | "setprototypeof": "1.0.3", 252 | "statuses": "1.3.1", 253 | "type-is": "1.6.15", 254 | "utils-merge": "1.0.0", 255 | "vary": "1.1.2" 256 | }, 257 | "dependencies": { 258 | "accepts": { 259 | "version": "1.3.4", 260 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", 261 | "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", 262 | "requires": { 263 | "mime-types": "2.1.17", 264 | "negotiator": "0.6.1" 265 | }, 266 | "dependencies": { 267 | "mime-types": { 268 | "version": "2.1.17", 269 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", 270 | "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", 271 | "requires": { 272 | "mime-db": "1.30.0" 273 | }, 274 | "dependencies": { 275 | "mime-db": { 276 | "version": "1.30.0", 277 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", 278 | "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" 279 | } 280 | } 281 | }, 282 | "negotiator": { 283 | "version": "0.6.1", 284 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 285 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 286 | } 287 | } 288 | }, 289 | "array-flatten": { 290 | "version": "1.1.1", 291 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 292 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 293 | }, 294 | "content-disposition": { 295 | "version": "0.5.2", 296 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 297 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 298 | }, 299 | "content-type": { 300 | "version": "1.0.4", 301 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 302 | "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=" 303 | }, 304 | "cookie": { 305 | "version": "0.3.1", 306 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 307 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 308 | }, 309 | "cookie-signature": { 310 | "version": "1.0.6", 311 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 312 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 313 | }, 314 | "depd": { 315 | "version": "1.1.1", 316 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 317 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 318 | }, 319 | "encodeurl": { 320 | "version": "1.0.1", 321 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", 322 | "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" 323 | }, 324 | "escape-html": { 325 | "version": "1.0.3", 326 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 327 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 328 | }, 329 | "etag": { 330 | "version": "1.8.1", 331 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 332 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 333 | }, 334 | "finalhandler": { 335 | "version": "1.0.6", 336 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.6.tgz", 337 | "integrity": "sha1-AHrqM9Gk0+QgF/YkhIrVjSEvgU8=", 338 | "requires": { 339 | "debug": "2.6.9", 340 | "encodeurl": "1.0.1", 341 | "escape-html": "1.0.3", 342 | "on-finished": "2.3.0", 343 | "parseurl": "1.3.2", 344 | "statuses": "1.3.1", 345 | "unpipe": "1.0.0" 346 | }, 347 | "dependencies": { 348 | "unpipe": { 349 | "version": "1.0.0", 350 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 351 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 352 | } 353 | } 354 | }, 355 | "fresh": { 356 | "version": "0.5.2", 357 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 358 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 359 | }, 360 | "merge-descriptors": { 361 | "version": "1.0.1", 362 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 363 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 364 | }, 365 | "methods": { 366 | "version": "1.1.2", 367 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 368 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 369 | }, 370 | "on-finished": { 371 | "version": "2.3.0", 372 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 373 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 374 | "requires": { 375 | "ee-first": "1.1.1" 376 | }, 377 | "dependencies": { 378 | "ee-first": { 379 | "version": "1.1.1", 380 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 381 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 382 | } 383 | } 384 | }, 385 | "parseurl": { 386 | "version": "1.3.2", 387 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 388 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 389 | }, 390 | "path-to-regexp": { 391 | "version": "0.1.7", 392 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 393 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 394 | }, 395 | "proxy-addr": { 396 | "version": "1.1.5", 397 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", 398 | "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg=", 399 | "requires": { 400 | "forwarded": "0.1.2", 401 | "ipaddr.js": "1.4.0" 402 | }, 403 | "dependencies": { 404 | "forwarded": { 405 | "version": "0.1.2", 406 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 407 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 408 | }, 409 | "ipaddr.js": { 410 | "version": "1.4.0", 411 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", 412 | "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA=" 413 | } 414 | } 415 | }, 416 | "qs": { 417 | "version": "6.5.0", 418 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", 419 | "integrity": "sha1-jQSVTTZN7z78VbWgeT4eLIsebkk=" 420 | }, 421 | "range-parser": { 422 | "version": "1.2.0", 423 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 424 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 425 | }, 426 | "send": { 427 | "version": "0.15.6", 428 | "resolved": "https://registry.npmjs.org/send/-/send-0.15.6.tgz", 429 | "integrity": "sha1-IPI6nJJbdiq4JwX+L52yUqzkfjQ=", 430 | "requires": { 431 | "debug": "2.6.9", 432 | "depd": "1.1.1", 433 | "destroy": "1.0.4", 434 | "encodeurl": "1.0.1", 435 | "escape-html": "1.0.3", 436 | "etag": "1.8.1", 437 | "fresh": "0.5.2", 438 | "http-errors": "1.6.2", 439 | "mime": "1.3.4", 440 | "ms": "2.0.0", 441 | "on-finished": "2.3.0", 442 | "range-parser": "1.2.0", 443 | "statuses": "1.3.1" 444 | }, 445 | "dependencies": { 446 | "destroy": { 447 | "version": "1.0.4", 448 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 449 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 450 | }, 451 | "http-errors": { 452 | "version": "1.6.2", 453 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 454 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 455 | "requires": { 456 | "depd": "1.1.1", 457 | "inherits": "2.0.3", 458 | "setprototypeof": "1.0.3", 459 | "statuses": "1.3.1" 460 | }, 461 | "dependencies": { 462 | "inherits": { 463 | "version": "2.0.3", 464 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 465 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 466 | } 467 | } 468 | }, 469 | "mime": { 470 | "version": "1.3.4", 471 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", 472 | "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" 473 | }, 474 | "ms": { 475 | "version": "2.0.0", 476 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 477 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 478 | } 479 | } 480 | }, 481 | "serve-static": { 482 | "version": "1.12.6", 483 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.6.tgz", 484 | "integrity": "sha1-uXN3P2NEmTTaVOW+ul4x2fQhFXc=", 485 | "requires": { 486 | "encodeurl": "1.0.1", 487 | "escape-html": "1.0.3", 488 | "parseurl": "1.3.2", 489 | "send": "0.15.6" 490 | } 491 | }, 492 | "setprototypeof": { 493 | "version": "1.0.3", 494 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 495 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 496 | }, 497 | "statuses": { 498 | "version": "1.3.1", 499 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", 500 | "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" 501 | }, 502 | "type-is": { 503 | "version": "1.6.15", 504 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", 505 | "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", 506 | "requires": { 507 | "media-typer": "0.3.0", 508 | "mime-types": "2.1.17" 509 | }, 510 | "dependencies": { 511 | "media-typer": { 512 | "version": "0.3.0", 513 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 514 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 515 | }, 516 | "mime-types": { 517 | "version": "2.1.17", 518 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", 519 | "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", 520 | "requires": { 521 | "mime-db": "1.30.0" 522 | }, 523 | "dependencies": { 524 | "mime-db": { 525 | "version": "1.30.0", 526 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", 527 | "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" 528 | } 529 | } 530 | } 531 | } 532 | }, 533 | "utils-merge": { 534 | "version": "1.0.0", 535 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", 536 | "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" 537 | }, 538 | "vary": { 539 | "version": "1.1.2", 540 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 541 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 542 | } 543 | } 544 | }, 545 | "express-session": { 546 | "version": "1.15.6", 547 | "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.6.tgz", 548 | "integrity": "sha1-R7QWDIj0KrcP6KUI4xy/92dXqwo=", 549 | "requires": { 550 | "cookie": "0.3.1", 551 | "cookie-signature": "1.0.6", 552 | "crc": "3.4.4", 553 | "debug": "2.6.9", 554 | "depd": "1.1.1", 555 | "on-headers": "1.0.1", 556 | "parseurl": "1.3.2", 557 | "uid-safe": "2.1.5", 558 | "utils-merge": "1.0.1" 559 | }, 560 | "dependencies": { 561 | "cookie": { 562 | "version": "0.3.1", 563 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 564 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 565 | }, 566 | "cookie-signature": { 567 | "version": "1.0.6", 568 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 569 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 570 | }, 571 | "crc": { 572 | "version": "3.4.4", 573 | "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz", 574 | "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms=" 575 | }, 576 | "depd": { 577 | "version": "1.1.1", 578 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 579 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 580 | }, 581 | "on-headers": { 582 | "version": "1.0.1", 583 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", 584 | "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" 585 | }, 586 | "parseurl": { 587 | "version": "1.3.2", 588 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 589 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 590 | }, 591 | "uid-safe": { 592 | "version": "2.1.5", 593 | "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", 594 | "integrity": "sha1-Kz1cckDo/C5Y+Komnl7knAhXvTo=", 595 | "requires": { 596 | "random-bytes": "1.0.0" 597 | }, 598 | "dependencies": { 599 | "random-bytes": { 600 | "version": "1.0.0", 601 | "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", 602 | "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" 603 | } 604 | } 605 | }, 606 | "utils-merge": { 607 | "version": "1.0.1", 608 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 609 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 610 | } 611 | } 612 | }, 613 | "inherits": { 614 | "version": "2.0.3", 615 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 616 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 617 | }, 618 | "minimalistic-assert": { 619 | "version": "1.0.0", 620 | "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", 621 | "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=" 622 | }, 623 | "morgan": { 624 | "version": "1.9.1", 625 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", 626 | "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", 627 | "requires": { 628 | "basic-auth": "~2.0.0", 629 | "debug": "2.6.9", 630 | "depd": "~1.1.2", 631 | "on-finished": "~2.3.0", 632 | "on-headers": "~1.0.1" 633 | } 634 | }, 635 | "node-jose": { 636 | "version": "0.11.0", 637 | "resolved": "https://registry.npmjs.org/node-jose/-/node-jose-0.11.0.tgz", 638 | "integrity": "sha1-WnN1gLw6ObAf95ONI5gzXEWNhYc=", 639 | "requires": { 640 | "base64url": "2.0.0", 641 | "es6-promise": "4.1.1", 642 | "lodash.assign": "4.2.0", 643 | "lodash.clone": "4.5.0", 644 | "lodash.fill": "3.4.0", 645 | "lodash.flatten": "4.4.0", 646 | "lodash.intersection": "4.4.0", 647 | "lodash.merge": "4.6.0", 648 | "lodash.omit": "4.5.0", 649 | "lodash.partialright": "4.2.1", 650 | "lodash.pick": "4.4.0", 651 | "lodash.uniq": "4.5.0", 652 | "long": "3.2.0", 653 | "node-forge": "0.7.1", 654 | "uuid": "3.1.0" 655 | }, 656 | "dependencies": { 657 | "base64url": { 658 | "version": "2.0.0", 659 | "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", 660 | "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=" 661 | }, 662 | "es6-promise": { 663 | "version": "4.1.1", 664 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz", 665 | "integrity": "sha1-iBHpCRXZoNujYnTwskLb2nj5ySo=" 666 | }, 667 | "lodash.assign": { 668 | "version": "4.2.0", 669 | "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", 670 | "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" 671 | }, 672 | "lodash.clone": { 673 | "version": "4.5.0", 674 | "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", 675 | "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=" 676 | }, 677 | "lodash.fill": { 678 | "version": "3.4.0", 679 | "resolved": "https://registry.npmjs.org/lodash.fill/-/lodash.fill-3.4.0.tgz", 680 | "integrity": "sha1-o8dK5kDQU63w3CB5+HIHiOi/74U=" 681 | }, 682 | "lodash.flatten": { 683 | "version": "4.4.0", 684 | "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", 685 | "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" 686 | }, 687 | "lodash.intersection": { 688 | "version": "4.4.0", 689 | "resolved": "https://registry.npmjs.org/lodash.intersection/-/lodash.intersection-4.4.0.tgz", 690 | "integrity": "sha1-ChG6Yx0OlcI8fy9Mu5ppLtF45wU=" 691 | }, 692 | "lodash.merge": { 693 | "version": "4.6.0", 694 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.0.tgz", 695 | "integrity": "sha1-aYhLoUSsM/5plzemCG3v+t0PicU=" 696 | }, 697 | "lodash.omit": { 698 | "version": "4.5.0", 699 | "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", 700 | "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=" 701 | }, 702 | "lodash.partialright": { 703 | "version": "4.2.1", 704 | "resolved": "https://registry.npmjs.org/lodash.partialright/-/lodash.partialright-4.2.1.tgz", 705 | "integrity": "sha1-ATDYDoM2MmTUAHTzKbij56ihzEs=" 706 | }, 707 | "lodash.pick": { 708 | "version": "4.4.0", 709 | "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", 710 | "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" 711 | }, 712 | "lodash.uniq": { 713 | "version": "4.5.0", 714 | "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", 715 | "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" 716 | }, 717 | "long": { 718 | "version": "3.2.0", 719 | "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", 720 | "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" 721 | }, 722 | "node-forge": { 723 | "version": "0.7.1", 724 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", 725 | "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=" 726 | }, 727 | "uuid": { 728 | "version": "3.1.0", 729 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", 730 | "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=" 731 | } 732 | } 733 | }, 734 | "on-finished": { 735 | "version": "2.3.0", 736 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 737 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 738 | "requires": { 739 | "ee-first": "1.1.1" 740 | } 741 | }, 742 | "on-headers": { 743 | "version": "1.0.2", 744 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", 745 | "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" 746 | }, 747 | "openid-client": { 748 | "version": "1.19.0", 749 | "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-1.19.0.tgz", 750 | "integrity": "sha1-W5V5ZGLAN/3fx3/2DK/9ZvnFbrw=", 751 | "requires": { 752 | "base64url": "2.0.0", 753 | "create-error-class": "3.0.2", 754 | "got": "8.0.1", 755 | "lodash": "4.17.4", 756 | "lru-cache": "4.1.1", 757 | "node-jose": "0.11.0", 758 | "oidc-token-hash": "2.0.0", 759 | "uuid": "3.1.0" 760 | }, 761 | "dependencies": { 762 | "base64url": { 763 | "version": "2.0.0", 764 | "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", 765 | "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=" 766 | }, 767 | "create-error-class": { 768 | "version": "3.0.2", 769 | "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", 770 | "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", 771 | "requires": { 772 | "capture-stack-trace": "1.0.0" 773 | }, 774 | "dependencies": { 775 | "capture-stack-trace": { 776 | "version": "1.0.0", 777 | "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", 778 | "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" 779 | } 780 | } 781 | }, 782 | "got": { 783 | "version": "8.0.1", 784 | "resolved": "https://registry.npmjs.org/got/-/got-8.0.1.tgz", 785 | "integrity": "sha1-bX+Ls+uZ5a+RLv4moQRHZEHgjn8=", 786 | "requires": { 787 | "@sindresorhus/is": "0.6.0", 788 | "cacheable-request": "2.1.3", 789 | "decompress-response": "3.3.0", 790 | "duplexer3": "0.1.4", 791 | "get-stream": "3.0.0", 792 | "into-stream": "3.1.0", 793 | "is-retry-allowed": "1.1.0", 794 | "isurl": "1.0.0", 795 | "lowercase-keys": "1.0.0", 796 | "mimic-response": "1.0.0", 797 | "p-cancelable": "0.3.0", 798 | "p-timeout": "2.0.1", 799 | "pify": "3.0.0", 800 | "safe-buffer": "5.1.1", 801 | "timed-out": "4.0.1", 802 | "url-parse-lax": "3.0.0", 803 | "url-to-options": "1.0.1" 804 | }, 805 | "dependencies": { 806 | "@sindresorhus/is": { 807 | "version": "0.6.0", 808 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.6.0.tgz", 809 | "integrity": "sha1-OD9Faya8lseInwMyB59DWLFsWNw=" 810 | }, 811 | "cacheable-request": { 812 | "version": "2.1.3", 813 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.3.tgz", 814 | "integrity": "sha1-uTVgfdKrKBKJi++yJPZqqGxTPbs=", 815 | "requires": { 816 | "clone-response": "1.0.2", 817 | "get-stream": "3.0.0", 818 | "http-cache-semantics": "3.8.1", 819 | "keyv": "3.0.0", 820 | "lowercase-keys": "1.0.0", 821 | "normalize-url": "2.0.0", 822 | "responselike": "1.0.2" 823 | }, 824 | "dependencies": { 825 | "clone-response": { 826 | "version": "1.0.2", 827 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", 828 | "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", 829 | "requires": { 830 | "mimic-response": "1.0.0" 831 | } 832 | }, 833 | "http-cache-semantics": { 834 | "version": "3.8.1", 835 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", 836 | "integrity": "sha1-ObDhat2bYFvwqe89nar0hDtMrNI=" 837 | }, 838 | "keyv": { 839 | "version": "3.0.0", 840 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", 841 | "integrity": "sha1-RJI7o55osSp87H32wyaMAx8u83M=", 842 | "requires": { 843 | "json-buffer": "3.0.0" 844 | }, 845 | "dependencies": { 846 | "json-buffer": { 847 | "version": "3.0.0", 848 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", 849 | "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" 850 | } 851 | } 852 | }, 853 | "normalize-url": { 854 | "version": "2.0.0", 855 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.0.tgz", 856 | "integrity": "sha1-4E2KNp86TK3IUKKFT4+w+KgSAyg=", 857 | "requires": { 858 | "prepend-http": "2.0.0", 859 | "query-string": "5.0.1", 860 | "sort-keys": "2.0.0" 861 | }, 862 | "dependencies": { 863 | "prepend-http": { 864 | "version": "2.0.0", 865 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", 866 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" 867 | }, 868 | "query-string": { 869 | "version": "5.0.1", 870 | "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.0.1.tgz", 871 | "integrity": "sha1-biuG/g4IrvaC7L6G6Fg0dlQCvYg=", 872 | "requires": { 873 | "decode-uri-component": "0.2.0", 874 | "object-assign": "4.1.1", 875 | "strict-uri-encode": "1.1.0" 876 | }, 877 | "dependencies": { 878 | "decode-uri-component": { 879 | "version": "0.2.0", 880 | "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", 881 | "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" 882 | }, 883 | "object-assign": { 884 | "version": "4.1.1", 885 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 886 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 887 | }, 888 | "strict-uri-encode": { 889 | "version": "1.1.0", 890 | "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", 891 | "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" 892 | } 893 | } 894 | }, 895 | "sort-keys": { 896 | "version": "2.0.0", 897 | "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", 898 | "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", 899 | "requires": { 900 | "is-plain-obj": "1.1.0" 901 | }, 902 | "dependencies": { 903 | "is-plain-obj": { 904 | "version": "1.1.0", 905 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", 906 | "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" 907 | } 908 | } 909 | } 910 | } 911 | }, 912 | "responselike": { 913 | "version": "1.0.2", 914 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", 915 | "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", 916 | "requires": { 917 | "lowercase-keys": "1.0.0" 918 | } 919 | } 920 | } 921 | }, 922 | "decompress-response": { 923 | "version": "3.3.0", 924 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", 925 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", 926 | "requires": { 927 | "mimic-response": "1.0.0" 928 | } 929 | }, 930 | "duplexer3": { 931 | "version": "0.1.4", 932 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", 933 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" 934 | }, 935 | "get-stream": { 936 | "version": "3.0.0", 937 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", 938 | "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" 939 | }, 940 | "into-stream": { 941 | "version": "3.1.0", 942 | "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", 943 | "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", 944 | "requires": { 945 | "from2": "2.3.0", 946 | "p-is-promise": "1.1.0" 947 | }, 948 | "dependencies": { 949 | "from2": { 950 | "version": "2.3.0", 951 | "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", 952 | "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", 953 | "requires": { 954 | "inherits": "2.0.3", 955 | "readable-stream": "2.3.3" 956 | }, 957 | "dependencies": { 958 | "inherits": { 959 | "version": "2.0.3", 960 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 961 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 962 | }, 963 | "readable-stream": { 964 | "version": "2.3.3", 965 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", 966 | "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", 967 | "requires": { 968 | "core-util-is": "1.0.2", 969 | "inherits": "2.0.3", 970 | "isarray": "1.0.0", 971 | "process-nextick-args": "1.0.7", 972 | "safe-buffer": "5.1.1", 973 | "string_decoder": "1.0.3", 974 | "util-deprecate": "1.0.2" 975 | }, 976 | "dependencies": { 977 | "core-util-is": { 978 | "version": "1.0.2", 979 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 980 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 981 | }, 982 | "isarray": { 983 | "version": "1.0.0", 984 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 985 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 986 | }, 987 | "process-nextick-args": { 988 | "version": "1.0.7", 989 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 990 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" 991 | }, 992 | "string_decoder": { 993 | "version": "1.0.3", 994 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 995 | "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", 996 | "requires": { 997 | "safe-buffer": "5.1.1" 998 | } 999 | }, 1000 | "util-deprecate": { 1001 | "version": "1.0.2", 1002 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1003 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1004 | } 1005 | } 1006 | } 1007 | } 1008 | }, 1009 | "p-is-promise": { 1010 | "version": "1.1.0", 1011 | "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", 1012 | "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" 1013 | } 1014 | } 1015 | }, 1016 | "is-retry-allowed": { 1017 | "version": "1.1.0", 1018 | "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", 1019 | "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" 1020 | }, 1021 | "isurl": { 1022 | "version": "1.0.0", 1023 | "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", 1024 | "integrity": "sha1-sn9PSfPNqj6kSgpbfzRi5u3DnWc=", 1025 | "requires": { 1026 | "has-to-string-tag-x": "1.4.1", 1027 | "is-object": "1.0.1" 1028 | }, 1029 | "dependencies": { 1030 | "has-to-string-tag-x": { 1031 | "version": "1.4.1", 1032 | "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", 1033 | "integrity": "sha1-oEWrOD17SyASoAFIqwql8pAETU0=", 1034 | "requires": { 1035 | "has-symbol-support-x": "1.4.1" 1036 | }, 1037 | "dependencies": { 1038 | "has-symbol-support-x": { 1039 | "version": "1.4.1", 1040 | "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.1.tgz", 1041 | "integrity": "sha1-ZuwuN34MfXzO2wejqE13UQ/xvEw=" 1042 | } 1043 | } 1044 | }, 1045 | "is-object": { 1046 | "version": "1.0.1", 1047 | "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", 1048 | "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" 1049 | } 1050 | } 1051 | }, 1052 | "lowercase-keys": { 1053 | "version": "1.0.0", 1054 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", 1055 | "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" 1056 | }, 1057 | "mimic-response": { 1058 | "version": "1.0.0", 1059 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", 1060 | "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=" 1061 | }, 1062 | "p-cancelable": { 1063 | "version": "0.3.0", 1064 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", 1065 | "integrity": "sha1-ueEjgAvOu3rBOkeb4ZW1B7mNMPo=" 1066 | }, 1067 | "p-timeout": { 1068 | "version": "2.0.1", 1069 | "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", 1070 | "integrity": "sha1-2N0ZeVldLcATnh/ka4tkbLPN8Dg=", 1071 | "requires": { 1072 | "p-finally": "1.0.0" 1073 | }, 1074 | "dependencies": { 1075 | "p-finally": { 1076 | "version": "1.0.0", 1077 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 1078 | "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" 1079 | } 1080 | } 1081 | }, 1082 | "pify": { 1083 | "version": "3.0.0", 1084 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 1085 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" 1086 | }, 1087 | "safe-buffer": { 1088 | "version": "5.1.1", 1089 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 1090 | "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" 1091 | }, 1092 | "timed-out": { 1093 | "version": "4.0.1", 1094 | "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", 1095 | "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" 1096 | }, 1097 | "url-parse-lax": { 1098 | "version": "3.0.0", 1099 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", 1100 | "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", 1101 | "requires": { 1102 | "prepend-http": "2.0.0" 1103 | }, 1104 | "dependencies": { 1105 | "prepend-http": { 1106 | "version": "2.0.0", 1107 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", 1108 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" 1109 | } 1110 | } 1111 | }, 1112 | "url-to-options": { 1113 | "version": "1.0.1", 1114 | "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", 1115 | "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" 1116 | } 1117 | } 1118 | }, 1119 | "lodash": { 1120 | "version": "4.17.4", 1121 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", 1122 | "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" 1123 | }, 1124 | "lru-cache": { 1125 | "version": "4.1.1", 1126 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", 1127 | "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", 1128 | "requires": { 1129 | "pseudomap": "1.0.2", 1130 | "yallist": "2.1.2" 1131 | }, 1132 | "dependencies": { 1133 | "pseudomap": { 1134 | "version": "1.0.2", 1135 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 1136 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" 1137 | }, 1138 | "yallist": { 1139 | "version": "2.1.2", 1140 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 1141 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" 1142 | } 1143 | } 1144 | }, 1145 | "node-jose": { 1146 | "version": "0.11.0", 1147 | "resolved": "https://registry.npmjs.org/node-jose/-/node-jose-0.11.0.tgz", 1148 | "integrity": "sha1-WnN1gLw6ObAf95ONI5gzXEWNhYc=", 1149 | "requires": { 1150 | "base64url": "2.0.0", 1151 | "es6-promise": "4.1.1", 1152 | "lodash.assign": "4.2.0", 1153 | "lodash.clone": "4.5.0", 1154 | "lodash.fill": "3.4.0", 1155 | "lodash.flatten": "4.4.0", 1156 | "lodash.intersection": "4.4.0", 1157 | "lodash.merge": "4.6.0", 1158 | "lodash.omit": "4.5.0", 1159 | "lodash.partialright": "4.2.1", 1160 | "lodash.pick": "4.4.0", 1161 | "lodash.uniq": "4.5.0", 1162 | "long": "3.2.0", 1163 | "node-forge": "0.7.1", 1164 | "uuid": "3.1.0" 1165 | }, 1166 | "dependencies": { 1167 | "es6-promise": { 1168 | "version": "4.1.1", 1169 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz", 1170 | "integrity": "sha1-iBHpCRXZoNujYnTwskLb2nj5ySo=" 1171 | }, 1172 | "lodash.assign": { 1173 | "version": "4.2.0", 1174 | "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", 1175 | "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" 1176 | }, 1177 | "lodash.clone": { 1178 | "version": "4.5.0", 1179 | "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", 1180 | "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=" 1181 | }, 1182 | "lodash.fill": { 1183 | "version": "3.4.0", 1184 | "resolved": "https://registry.npmjs.org/lodash.fill/-/lodash.fill-3.4.0.tgz", 1185 | "integrity": "sha1-o8dK5kDQU63w3CB5+HIHiOi/74U=" 1186 | }, 1187 | "lodash.flatten": { 1188 | "version": "4.4.0", 1189 | "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", 1190 | "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" 1191 | }, 1192 | "lodash.intersection": { 1193 | "version": "4.4.0", 1194 | "resolved": "https://registry.npmjs.org/lodash.intersection/-/lodash.intersection-4.4.0.tgz", 1195 | "integrity": "sha1-ChG6Yx0OlcI8fy9Mu5ppLtF45wU=" 1196 | }, 1197 | "lodash.merge": { 1198 | "version": "4.6.0", 1199 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.0.tgz", 1200 | "integrity": "sha1-aYhLoUSsM/5plzemCG3v+t0PicU=" 1201 | }, 1202 | "lodash.omit": { 1203 | "version": "4.5.0", 1204 | "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", 1205 | "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=" 1206 | }, 1207 | "lodash.partialright": { 1208 | "version": "4.2.1", 1209 | "resolved": "https://registry.npmjs.org/lodash.partialright/-/lodash.partialright-4.2.1.tgz", 1210 | "integrity": "sha1-ATDYDoM2MmTUAHTzKbij56ihzEs=" 1211 | }, 1212 | "lodash.pick": { 1213 | "version": "4.4.0", 1214 | "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", 1215 | "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" 1216 | }, 1217 | "lodash.uniq": { 1218 | "version": "4.5.0", 1219 | "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", 1220 | "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" 1221 | }, 1222 | "long": { 1223 | "version": "3.2.0", 1224 | "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", 1225 | "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" 1226 | }, 1227 | "node-forge": { 1228 | "version": "0.7.1", 1229 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", 1230 | "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=" 1231 | } 1232 | } 1233 | }, 1234 | "oidc-token-hash": { 1235 | "version": "2.0.0", 1236 | "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-2.0.0.tgz", 1237 | "integrity": "sha1-6h9g20THipISaPn4rzc2Ksn2GE4=", 1238 | "requires": { 1239 | "base64url": "2.0.0" 1240 | } 1241 | }, 1242 | "uuid": { 1243 | "version": "3.1.0", 1244 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", 1245 | "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=" 1246 | } 1247 | } 1248 | }, 1249 | "passport": { 1250 | "version": "0.4.0", 1251 | "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.0.tgz", 1252 | "integrity": "sha1-xQlWkTR71a07XhgCOMORTRbwWBE=", 1253 | "requires": { 1254 | "passport-strategy": "1.0.0", 1255 | "pause": "0.0.1" 1256 | }, 1257 | "dependencies": { 1258 | "passport-strategy": { 1259 | "version": "1.0.0", 1260 | "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", 1261 | "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" 1262 | }, 1263 | "pause": { 1264 | "version": "0.0.1", 1265 | "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", 1266 | "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" 1267 | } 1268 | } 1269 | }, 1270 | "pem-jwk": { 1271 | "version": "1.5.1", 1272 | "resolved": "https://registry.npmjs.org/pem-jwk/-/pem-jwk-1.5.1.tgz", 1273 | "integrity": "sha1-eoY3/S9nqCflfAxC4cI8P9Us+wE=", 1274 | "requires": { 1275 | "asn1.js": "1.0.3" 1276 | } 1277 | }, 1278 | "safe-buffer": { 1279 | "version": "5.1.2", 1280 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1281 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1282 | }, 1283 | "serve-favicon": { 1284 | "version": "2.4.5", 1285 | "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.4.5.tgz", 1286 | "integrity": "sha1-SdmkaGMVOpJAaRyJPSsOfYXW1DY=", 1287 | "requires": { 1288 | "etag": "1.8.1", 1289 | "fresh": "0.5.2", 1290 | "ms": "2.0.0", 1291 | "parseurl": "1.3.2", 1292 | "safe-buffer": "5.1.1" 1293 | }, 1294 | "dependencies": { 1295 | "etag": { 1296 | "version": "1.8.1", 1297 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 1298 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 1299 | }, 1300 | "fresh": { 1301 | "version": "0.5.2", 1302 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 1303 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 1304 | }, 1305 | "ms": { 1306 | "version": "2.0.0", 1307 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1308 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1309 | }, 1310 | "parseurl": { 1311 | "version": "1.3.2", 1312 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 1313 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 1314 | }, 1315 | "safe-buffer": { 1316 | "version": "5.1.1", 1317 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 1318 | "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" 1319 | } 1320 | } 1321 | } 1322 | } 1323 | } 1324 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "identity-oidc-expressjs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "nodemon ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.18.2", 10 | "cookie-parser": "~1.4.3", 11 | "debug": "~2.6.9", 12 | "dotenv": "^4.0.0", 13 | "ejs": "~2.5.7", 14 | "express": "~4.15.5", 15 | "express-session": "^1.15.6", 16 | "morgan": "~1.9.1", 17 | "node-jose": "^0.11.0", 18 | "openid-client": "^1.19.0", 19 | "passport": "^0.4.0", 20 | "pem-jwk": "^1.5.1", 21 | "serve-favicon": "~2.4.5" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /public/images/login-gov.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/stylesheets/basscss.min.css: -------------------------------------------------------------------------------- 1 | /*! Basscss | http://basscss.com | MIT License */ 2 | body{margin:0}img{max-width:100%}svg{max-height:100%}fieldset,input,select,textarea{font-family:inherit;font-size:1rem;box-sizing:border-box;margin-top:0;margin-bottom:0}label{vertical-align:middle}input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{height:2.25rem;padding:.5rem;vertical-align:middle;-webkit-appearance:none}select{line-height:1.75;padding:.5rem}select:not([multiple]){height:2.25rem;vertical-align:middle}textarea{line-height:1.75;padding:.5rem}table{border-collapse:separate;border-spacing:0;max-width:100%;width:100%}th{text-align:left;font-weight:700}td,th{padding:.25rem 1rem;line-height:inherit}th{vertical-align:bottom}td{vertical-align:top}body{line-height:1.5;font-size:100%}body,h1,h2,h3,h4,h5,h6{font-family:Helvetica Neue,Helvetica,sans-serif}h1,h2,h3,h4,h5,h6{font-weight:700;line-height:1.25;margin-top:1em;margin-bottom:.5em}dl,ol,p,ul{margin-top:0;margin-bottom:1rem}code,pre,samp{font-family:Source Code Pro,Consolas,monospace;font-size:inherit}pre{margin-top:0;margin-bottom:1rem;overflow-x:scroll}h1{font-size:2rem}h2{font-size:1.5rem}h3{font-size:1.25rem}h4{font-size:1rem}h5{font-size:.875rem}h6{font-size:.75rem}body{color:#111;background-color:#fff}a{color:#0074d9;text-decoration:none}a:hover{text-decoration:underline}code,pre{background-color:transparent;border-radius:3px}hr{border:0;border-bottom-style:solid;border-bottom-width:1px;border-bottom-color:rgba(0,0,0,.125)}.field{border:1px solid rgba(0,0,0,.125);border-radius:3px}.field.is-focused,.field:focus{outline:none;border-color:#0074d9;box-shadow:0 0 0 2px rgba(0,116,217,.5)}.field.is-disabled,.field:disabled{background-color:rgba(0,0,0,.125);opacity:.5}.field.is-read-only,.field:-moz-read-only:not(select){background-color:rgba(0,0,0,.125)}.field.is-read-only,.field:read-only:not(select){background-color:rgba(0,0,0,.125)}.field.is-success{border-color:#2ecc40}.field.is-success.is-focused,.field.is-success:focus{box-shadow:0 0 0 2px rgba(46,204,64,.5)}.field.is-warning{border-color:#ffdc00}.field.is-warning.is-focused,.field.is-warning:focus{box-shadow:0 0 0 2px rgba(255,220,0,.5)}.field.is-error,.field:invalid{border-color:#ff4136}.field.is-error.is-focused,.field.is-error:focus,.field:invalid.is-focused,.field:invalid:focus{box-shadow:0 0 0 2px rgba(255,65,54,.5)}.table-light td,.table-light th{border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgba(0,0,0,.125)}.table-light tr:last-child td{border-bottom:0}.btn{font-family:inherit;font-size:inherit;font-weight:700;cursor:pointer;display:inline-block;line-height:1.125rem;padding:.5rem 1rem;margin:0;height:auto;border:1px solid transparent;vertical-align:middle;-webkit-appearance:none;color:inherit;background-color:transparent}.btn,.btn:hover{text-decoration:none}.btn:focus{outline:none;border-color:rgba(0,0,0,.125);box-shadow:0 0 0 3px rgba(0,0,0,.25)}::-moz-focus-inner{border:0;padding:0}.btn-primary{color:#fff;background-color:#0074d9;border-radius:3px}.btn-primary:hover{box-shadow:inset 0 0 0 20rem rgba(0,0,0,.0625)}.btn-primary:active{box-shadow:inset 0 0 0 20rem rgba(0,0,0,.125),inset 0 3px 4px 0 rgba(0,0,0,.25),0 0 1px rgba(0,0,0,.125)}.btn-primary.is-disabled,.btn-primary:disabled{opacity:.5}.btn-outline,.btn-outline:hover{border-color:currentcolor}.btn-outline{border-radius:3px}.btn-outline:hover{box-shadow:inset 0 0 0 20rem rgba(0,0,0,.0625)}.btn-outline:active{box-shadow:inset 0 0 0 20rem rgba(0,0,0,.125),inset 0 3px 4px 0 rgba(0,0,0,.25),0 0 1px rgba(0,0,0,.125)}.btn-outline.is-disabled,.btn-outline:disabled{opacity:.5}.h1{font-size:2rem}.h2{font-size:1.5rem}.h3{font-size:1.25rem}.h4{font-size:1rem}.h5{font-size:.875rem}.h6{font-size:.75rem}.font-family-inherit{font-family:inherit}.font-size-inherit{font-size:inherit}.text-decoration-none{text-decoration:none}.bold{font-weight:700}.regular{font-weight:400}.italic{font-style:italic}.caps{text-transform:uppercase;letter-spacing:.2em}.left-align{text-align:left}.center{text-align:center}.right-align{text-align:right}.justify{text-align:justify}.nowrap{white-space:nowrap}.break-word{word-wrap:break-word}.line-height-1{line-height:1}.line-height-2{line-height:1.125}.line-height-3{line-height:1.25}.line-height-4{line-height:1.5}.list-style-none{list-style:none}.underline{text-decoration:underline}.truncate{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.list-reset{list-style:none;padding-left:0}.inline{display:inline}.block{display:block}.inline-block{display:inline-block}.table{display:table}.table-cell{display:table-cell}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-auto{overflow:auto}.clearfix:after,.clearfix:before{content:" ";display:table}.clearfix:after{clear:both}.left{float:left}.right{float:right}.fit{max-width:100%}.border-box{box-sizing:border-box}.align-baseline{vertical-align:baseline}.align-top{vertical-align:top}.align-middle{vertical-align:middle}.align-bottom{vertical-align:bottom}.m0{margin:0}.mt0{margin-top:0}.mr0{margin-right:0}.mb0{margin-bottom:0}.ml0{margin-left:0}.m1{margin:.5rem}.mt1{margin-top:.5rem}.mr1{margin-right:.5rem}.mb1{margin-bottom:.5rem}.ml1{margin-left:.5rem}.m2{margin:1rem}.mt2{margin-top:1rem}.mr2{margin-right:1rem}.mb2{margin-bottom:1rem}.ml2{margin-left:1rem}.m3{margin:2rem}.mt3{margin-top:2rem}.mr3{margin-right:2rem}.mb3{margin-bottom:2rem}.ml3{margin-left:2rem}.m4{margin:4rem}.mt4{margin-top:4rem}.mr4{margin-right:4rem}.mb4{margin-bottom:4rem}.ml4{margin-left:4rem}.mxn1{margin-left:-.5rem;margin-right:-.5rem}.mxn2{margin-left:-1rem;margin-right:-1rem}.mxn3{margin-left:-2rem;margin-right:-2rem}.mxn4{margin-left:-4rem;margin-right:-4rem}.mx-auto{margin-left:auto;margin-right:auto}.p0{padding:0}.p1{padding:.5rem}.py1{padding-top:.5rem;padding-bottom:.5rem}.px1{padding-left:.5rem;padding-right:.5rem}.p2{padding:1rem}.py2{padding-top:1rem;padding-bottom:1rem}.px2{padding-left:1rem;padding-right:1rem}.p3{padding:2rem}.py3{padding-top:2rem;padding-bottom:2rem}.px3{padding-left:2rem;padding-right:2rem}.p4{padding:4rem}.py4{padding-top:4rem;padding-bottom:4rem}.px4{padding-left:4rem;padding-right:4rem}.relative{position:relative}.absolute{position:absolute}.fixed{position:fixed}.top-0{top:0}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.z1{z-index:1}.z2{z-index:2}.z3{z-index:3}.z4{z-index:4}.lg-show,.md-show,.sm-show{display:none!important}@media (min-width:40em){.sm-show{display:block!important}}@media (min-width:52em){.md-show{display:block!important}}@media (min-width:64em){.lg-show{display:block!important}}@media (min-width:40em){.sm-hide{display:none!important}}@media (min-width:52em){.md-hide{display:none!important}}@media (min-width:64em){.lg-hide{display:none!important}}.display-none{display:none!important}.hide{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}.container{max-width:64em;margin-left:auto;margin-right:auto}.col{float:left}.col,.col-right{box-sizing:border-box}.col-right{float:right}.col-1{width:8.33333%}.col-2{width:16.66667%}.col-3{width:25%}.col-4{width:33.33333%}.col-5{width:41.66667%}.col-6{width:50%}.col-7{width:58.33333%}.col-8{width:66.66667%}.col-9{width:75%}.col-10{width:83.33333%}.col-11{width:91.66667%}.col-12{width:100%}@media (min-width:40em){.sm-col{float:left;box-sizing:border-box}.sm-col-right{float:right;box-sizing:border-box}.sm-col-1{width:8.33333%}.sm-col-2{width:16.66667%}.sm-col-3{width:25%}.sm-col-4{width:33.33333%}.sm-col-5{width:41.66667%}.sm-col-6{width:50%}.sm-col-7{width:58.33333%}.sm-col-8{width:66.66667%}.sm-col-9{width:75%}.sm-col-10{width:83.33333%}.sm-col-11{width:91.66667%}.sm-col-12{width:100%}}@media (min-width:52em){.md-col{float:left;box-sizing:border-box}.md-col-right{float:right;box-sizing:border-box}.md-col-1{width:8.33333%}.md-col-2{width:16.66667%}.md-col-3{width:25%}.md-col-4{width:33.33333%}.md-col-5{width:41.66667%}.md-col-6{width:50%}.md-col-7{width:58.33333%}.md-col-8{width:66.66667%}.md-col-9{width:75%}.md-col-10{width:83.33333%}.md-col-11{width:91.66667%}.md-col-12{width:100%}}@media (min-width:64em){.lg-col{float:left;box-sizing:border-box}.lg-col-right{float:right;box-sizing:border-box}.lg-col-1{width:8.33333%}.lg-col-2{width:16.66667%}.lg-col-3{width:25%}.lg-col-4{width:33.33333%}.lg-col-5{width:41.66667%}.lg-col-6{width:50%}.lg-col-7{width:58.33333%}.lg-col-8{width:66.66667%}.lg-col-9{width:75%}.lg-col-10{width:83.33333%}.lg-col-11{width:91.66667%}.lg-col-12{width:100%}}.flex{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flex-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.flex-wrap{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.flex-center{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.flex-baseline{-webkit-box-align:baseline;-webkit-align-items:baseline;-ms-flex-align:baseline;align-items:baseline}.flex-stretch{-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch}.flex-start{-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start}.flex-end{-webkit-box-align:end;-webkit-align-items:flex-end;-ms-flex-align:end;align-items:flex-end}.flex-justify{-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.flex-auto{-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;min-width:0;min-height:0}.flex-grow{-webkit-box-flex:1;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto}.flex-none{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none}.flex-first{-webkit-box-ordinal-group:0;-webkit-order:-1;-ms-flex-order:-1;order:-1}.flex-last{-webkit-box-ordinal-group:100000;-webkit-order:99999;-ms-flex-order:99999;order:99999}@media (min-width:40em){.sm-flex{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}}@media (min-width:52em){.md-flex{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}}@media (min-width:64em){.lg-flex{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}}.border{border:1px solid rgba(0,0,0,.125)}.border-top{border-top-style:solid;border-top-width:1px;border-top-color:rgba(0,0,0,.125)}.border-right{border-right-style:solid;border-right-width:1px;border-right-color:rgba(0,0,0,.125)}.border-bottom{border-bottom-style:solid;border-bottom-width:1px;border-bottom-color:rgba(0,0,0,.125)}.border-left{border-left-style:solid;border-left-width:1px;border-left-color:rgba(0,0,0,.125)}.border-none{border:0}.rounded{border-radius:3px}.circle{border-radius:50%}.rounded-top{border-radius:3px 3px 0 0}.rounded-right{border-radius:0 3px 3px 0}.rounded-bottom{border-radius:0 0 3px 3px}.rounded-left{border-radius:3px 0 0 3px}.not-rounded{border-radius:0}.black{color:#111}.gray{color:#aaa}.silver{color:#ddd}.white{color:#fff}.aqua{color:#7fdbff}.blue{color:#0074d9}.navy{color:#001f3f}.teal{color:#39cccc}.green{color:#2ecc40}.olive{color:#3d9970}.lime{color:#01ff70}.yellow{color:#ffdc00}.orange{color:#ff851b}.red{color:#ff4136}.fuchsia{color:#f012be}.purple{color:#b10dc9}.maroon{color:#85144b}.color-inherit{color:inherit}.muted{opacity:.5}.bg-black{background-color:#111}.bg-gray{background-color:#aaa}.bg-silver{background-color:#ddd}.bg-white{background-color:#fff}.bg-aqua{background-color:#7fdbff}.bg-blue{background-color:#0074d9}.bg-navy{background-color:#001f3f}.bg-teal{background-color:#39cccc}.bg-green{background-color:#2ecc40}.bg-olive{background-color:#3d9970}.bg-lime{background-color:#01ff70}.bg-yellow{background-color:#ffdc00}.bg-orange{background-color:#ff851b}.bg-red{background-color:#ff4136}.bg-fuchsia{background-color:#f012be}.bg-purple{background-color:#b10dc9}.bg-maroon{background-color:#85144b}.bg-darken-1{background-color:rgba(0,0,0,.0625)}.bg-darken-2{background-color:rgba(0,0,0,.125)}.bg-darken-3{background-color:rgba(0,0,0,.25)}.bg-darken-4{background-color:rgba(0,0,0,.5)}.bg-lighten-1{background-color:hsla(0,0%,100%,.0625)}.bg-lighten-2{background-color:hsla(0,0%,100%,.125)}.bg-lighten-3{background-color:hsla(0,0%,100%,.25)}.bg-lighten-4{background-color:hsla(0,0%,100%,.5)} 3 | -------------------------------------------------------------------------------- /public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /routes/auth/login-gov.js: -------------------------------------------------------------------------------- 1 | var loginGov = require('../../login-gov'); 2 | 3 | var loginGovRoutes = {}; 4 | 5 | var logoutPath = '/auth/login-gov/logout'; 6 | 7 | loginGovRoutes.configure = function(app, passport) { 8 | 9 | // 10 | // LOGIN 11 | // ... app.get('/auth/login-gov/login', passport.authenticate('oidc')) 12 | // 13 | 14 | app.get('/auth/login-gov/login/loa-1', passport.authenticate('oidc-loa-1')); 15 | app.get('/auth/login-gov/login/loa-3', passport.authenticate('oidc-loa-3')); 16 | 17 | // 18 | // CALLBACK 19 | // ... app.get('/auth/login-gov/callback', passport.authenticate('oidc', {successRedirect:'/profile', failureRedirect:'/'}) ) 20 | // 21 | 22 | app.get('/auth/login-gov/callback/loa-1', passport.authenticate('oidc-loa-1', {successRedirect:'/profile', failureRedirect:'/'}) ); 23 | app.get('/auth/login-gov/callback/loa-3', passport.authenticate('oidc-loa-3', {successRedirect:'/profile', failureRedirect:'/'}) ); 24 | 25 | // 26 | // LOGOUT 27 | // 28 | 29 | // Logout from this application, but not from login.gov 30 | app.get(logoutPath, function(req, res) { 31 | req.logout(); 32 | res.redirect('/'); 33 | }); 34 | 35 | // Logout from this application and from login.gov 36 | // ... using RP-Initiated Logout 37 | // ... adapted from https://github.com/18F/fs-permit-platform/blob/6f3681a5861d96db76c279f726c23971f3e037c7/server/src/auth/passport-config.es6#L41-L56 38 | app.get('/auth/login-gov/oidc-logout', function(req, res) { 39 | if (loginGov.issuer && req.user) { 40 | var postLogoutRedirectUrl = `http://localhost:9393${logoutPath}`; // redirect to the logout path to sign the user out of this app after the response comes back, or else the user will still be signed in! 41 | var requestUrl = `${loginGov.issuer.end_session_endpoint}?id_token_hint=${req.user.token}&post_logout_redirect_uri=${postLogoutRedirectUrl}&state=${req.user.state}`; 42 | return res.redirect(requestUrl); 43 | } else { // safeguard if user manually navigates to this route, avoids "Cannot read property 'token' of undefined" 44 | req.logout(); 45 | res.redirect('/'); 46 | }; 47 | }); 48 | 49 | }; 50 | 51 | module.exports = loginGovRoutes; 52 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | router.get('/', function(req, res, next) { 5 | res.render('index', { 6 | heading: 'Login.gov OIDC Client (Express.js)' 7 | }); 8 | }); 9 | 10 | router.get('/profile', authenticate, function(req, res){ 11 | res.render('page', { 12 | heading: 'Profile Page', 13 | user: req.user 14 | }) 15 | }) 16 | 17 | router.get('/other', authenticate, function(req, res){ 18 | res.render('page', { 19 | heading: 'Other Page', 20 | user: req.user 21 | }) 22 | }) 23 | 24 | function authenticate(req, res, next) { 25 | if (req.isAuthenticated()) { 26 | console.log("AUTHENTICATED USER", req.user) 27 | return next(); 28 | } 29 | console.log("NOT AUTHENTICATED"); 30 | res.redirect('/'); 31 | } 32 | 33 | module.exports = router; 34 | -------------------------------------------------------------------------------- /routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/users', function(req, res, next) { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /views/error.ejs: -------------------------------------------------------------------------------- 1 |
<%= error.stack %>4 | -------------------------------------------------------------------------------- /views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |