mirror of
https://github.com/openstf/stf
synced 2025-10-04 18:29:17 +02:00
Add an OAuth2 auth provider.
This commit is contained in:
parent
2ff16baf7a
commit
af09fc084a
3 changed files with 175 additions and 0 deletions
92
lib/cli.js
92
lib/cli.js
|
@ -329,6 +329,98 @@ program
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
program
|
||||||
|
.command('auth-oauth2')
|
||||||
|
.description('start OAuth 2.0 auth client')
|
||||||
|
.option('-p, --port <port>'
|
||||||
|
, 'port (or $PORT)'
|
||||||
|
, Number
|
||||||
|
, process.env.PORT || 7120)
|
||||||
|
.option('-s, --secret <secret>'
|
||||||
|
, 'secret (or $SECRET)'
|
||||||
|
, String
|
||||||
|
, process.env.SECRET)
|
||||||
|
.option('-i, --ssid <ssid>'
|
||||||
|
, 'session SSID (or $SSID)'
|
||||||
|
, String
|
||||||
|
, process.env.SSID || 'ssid')
|
||||||
|
.option('-a, --app-url <url>'
|
||||||
|
, 'URL to app'
|
||||||
|
, String)
|
||||||
|
.option('--oauth-authorization-url <url>'
|
||||||
|
, 'OAuth 2.0 authorization URL (or $OAUTH_AUTHORIZATION_URL)'
|
||||||
|
, String
|
||||||
|
, process.env.OAUTH_AUTHORIZATION_URL)
|
||||||
|
.option('--oauth-token-url <url>'
|
||||||
|
, 'OAuth 2.0 token URL (or $OAUTH_TOKEN_URL)'
|
||||||
|
, String
|
||||||
|
, process.env.OAUTH_TOKEN_URL)
|
||||||
|
.option('--oauth-userinfo-url <url>'
|
||||||
|
, 'OAuth 2.0 token URL (or $OAUTH_USERINFO_URL)'
|
||||||
|
, String
|
||||||
|
, process.env.OAUTH_USERINFO_URL)
|
||||||
|
.option('--oauth-client-id <id>'
|
||||||
|
, 'OAuth 2.0 client ID (or $OAUTH_CLIENT_ID)'
|
||||||
|
, String
|
||||||
|
, process.env.OAUTH_CLIENT_ID)
|
||||||
|
.option('--oauth-client-secret <value>'
|
||||||
|
, 'OAuth 2.0 client secret (or $OAUTH_CLIENT_SECRET)'
|
||||||
|
, String
|
||||||
|
, process.env.OAUTH_CLIENT_SECRET)
|
||||||
|
.option('--oauth-callback-url <url>'
|
||||||
|
, 'OAuth 2.0 callback URL (or $OAUTH_CALLBACK_URL)'
|
||||||
|
, String
|
||||||
|
, process.env.OAUTH_CALLBACK_URL)
|
||||||
|
.option('--oauth-scope <scope>'
|
||||||
|
, 'Space-separated OAuth 2.0 scope (or $OAUTH_SCOPE)'
|
||||||
|
, String
|
||||||
|
, process.env.OAUTH_SCOPE)
|
||||||
|
.action(function(options) {
|
||||||
|
if (!options.secret) {
|
||||||
|
this.missingArgument('--secret')
|
||||||
|
}
|
||||||
|
if (!options.appUrl) {
|
||||||
|
this.missingArgument('--app-url')
|
||||||
|
}
|
||||||
|
if (!options.oauthAuthorizationUrl) {
|
||||||
|
this.missingArgument('--oauth-authorization-url')
|
||||||
|
}
|
||||||
|
if (!options.oauthTokenUrl) {
|
||||||
|
this.missingArgument('--oauth-token-url')
|
||||||
|
}
|
||||||
|
if (!options.oauthUserinfoUrl) {
|
||||||
|
this.missingArgument('--oauth-userinfo-url')
|
||||||
|
}
|
||||||
|
if (!options.oauthClientId) {
|
||||||
|
this.missingArgument('--oauth-client-id')
|
||||||
|
}
|
||||||
|
if (!options.oauthClientSecret) {
|
||||||
|
this.missingArgument('--oauth-client-secret')
|
||||||
|
}
|
||||||
|
if (!options.oauthCallbackUrl) {
|
||||||
|
this.missingArgument('--oauth-callback-url')
|
||||||
|
}
|
||||||
|
if (!options.oauthScope) {
|
||||||
|
this.missingArgument('--oauth-scope')
|
||||||
|
}
|
||||||
|
|
||||||
|
require('./units/auth/oauth2')({
|
||||||
|
port: options.port
|
||||||
|
, secret: options.secret
|
||||||
|
, ssid: options.ssid
|
||||||
|
, appUrl: options.appUrl
|
||||||
|
, oauth: {
|
||||||
|
authorizationURL: options.oauthAuthorizationUrl
|
||||||
|
, tokenURL: options.oauthTokenUrl
|
||||||
|
, userinfoURL: options.oauthUserinfoUrl
|
||||||
|
, clientID: options.oauthClientId
|
||||||
|
, clientSecret: options.oauthClientSecret
|
||||||
|
, callbackURL: options.oauthCallbackUrl
|
||||||
|
, scope: options.oauthScope.split(/\s+/)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
program
|
program
|
||||||
.command('auth-mock')
|
.command('auth-mock')
|
||||||
.description('start mock auth client')
|
.description('start mock auth client')
|
||||||
|
|
51
lib/units/auth/oauth2/index.js
Normal file
51
lib/units/auth/oauth2/index.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
var http = require('http')
|
||||||
|
|
||||||
|
// @todo Figure something out
|
||||||
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"
|
||||||
|
|
||||||
|
var express = require('express')
|
||||||
|
var passport = require('passport')
|
||||||
|
|
||||||
|
var logger = require('../../../util/logger')
|
||||||
|
var urlutil = require('../../../util/urlutil')
|
||||||
|
var jwtutil = require('../../../util/jwtutil')
|
||||||
|
var Strategy = require('./strategy')
|
||||||
|
|
||||||
|
module.exports = function(options) {
|
||||||
|
var log = logger.createLogger('auth-oauth2')
|
||||||
|
, app = express()
|
||||||
|
, server = http.createServer(app)
|
||||||
|
|
||||||
|
app.set('strict routing', true)
|
||||||
|
app.set('case sensitive routing', true)
|
||||||
|
|
||||||
|
function verify(accessToken, refreshToken, profile, done) {
|
||||||
|
done(null, profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
passport.use(new Strategy(options.oauth, verify))
|
||||||
|
|
||||||
|
app.use(passport.initialize())
|
||||||
|
app.use(passport.authenticate('oauth2', {
|
||||||
|
failureRedirect: '/auth/oauth/'
|
||||||
|
, session: false
|
||||||
|
}))
|
||||||
|
|
||||||
|
app.get(
|
||||||
|
'/auth/oauth/callback'
|
||||||
|
, function(req, res) {
|
||||||
|
res.redirect(urlutil.addParams(options.appUrl, {
|
||||||
|
jwt: jwtutil.encode({
|
||||||
|
payload: {
|
||||||
|
email: req.user.email
|
||||||
|
, name: req.user.email.split('@', 1).join('')
|
||||||
|
}
|
||||||
|
, secret: options.secret
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
server.listen(options.port)
|
||||||
|
log.info('Listening on port %d', options.port)
|
||||||
|
}
|
32
lib/units/auth/oauth2/strategy.js
Normal file
32
lib/units/auth/oauth2/strategy.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
var util = require('util')
|
||||||
|
|
||||||
|
var oauth2 = require('passport-oauth2')
|
||||||
|
|
||||||
|
function Strategy(options, verify) {
|
||||||
|
oauth2.Strategy.call(this, options, verify)
|
||||||
|
if (!options.authorizationURL) {
|
||||||
|
throw new TypeError('OAuth2Strategy requires a userinfoURL option')
|
||||||
|
}
|
||||||
|
this._userinfoURL = options.userinfoURL
|
||||||
|
this._oauth2.useAuthorizationHeaderforGET(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(Strategy, oauth2.Strategy)
|
||||||
|
|
||||||
|
Strategy.prototype.userProfile = function(accessToken, callback) {
|
||||||
|
this._oauth2.get(this._userinfoURL, accessToken, function(err, data) {
|
||||||
|
if (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
return callback(null, JSON.parse(data))
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Strategy
|
Loading…
Add table
Add a link
Reference in a new issue