Skip to content

Commit a3a789b

Browse files
authored
Merge pull request #1710 from status-im/gh-oauth-orgs
2 parents 8af3638 + 0d1cd1d commit a3a789b

File tree

6 files changed

+58
-4
lines changed

6 files changed

+58
-4
lines changed

app.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@
8080
"description": "GitHub API client secret",
8181
"required": false
8282
},
83+
"CMD_GITHUB_ORGANIZATIONS": {
84+
"description": "GitHub whitelist of orgs",
85+
"required": false
86+
},
87+
"CMD_GITHUB_SCOPES": {
88+
"description": "GitHub OAuth API scopes",
89+
"required": false
90+
},
8391
"CMD_BITBUCKET_CLIENTID": {
8492
"description": "Bitbucket API client id",
8593
"required": false

config.json.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
"github": {
5555
"clientID": "change this",
5656
"clientSecret": "change this"
57+
"organizations": ["names of github organizations allowed, optional"],
58+
"scopes": ["defaults to 'read:user' scope for auth user"],
5759
},
5860
"gitlab": {
5961
"baseURL": "change this",

lib/auth/github/index.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
'use strict'
22

33
const Router = require('express').Router
4+
const request = require('request')
45
const passport = require('passport')
56
const GithubStrategy = require('passport-github').Strategy
7+
const { InternalOAuthError } = require('passport-oauth2')
68
const config = require('../../config')
79
const response = require('../../response')
810
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
911
const { URL } = require('url')
12+
const { promisify } = require('util')
13+
14+
const rp = promisify(request)
1015

1116
const githubAuth = module.exports = Router()
1217

@@ -15,20 +20,47 @@ function githubUrl (path) {
1520
}
1621

1722
passport.use(new GithubStrategy({
23+
scope: (config.github.organizations ?
24+
config.github.scopes.concat(['read:org']) : config.github.scope),
1825
clientID: config.github.clientID,
1926
clientSecret: config.github.clientSecret,
2027
callbackURL: config.serverURL + '/auth/github/callback',
2128
authorizationURL: githubUrl('login/oauth/authorize'),
2229
tokenURL: githubUrl('login/oauth/access_token'),
2330
userProfileURL: githubUrl('api/v3/user')
24-
}, passportGeneralCallback))
31+
}, async (accessToken, refreshToken, profile, done) => {
32+
if (!config.github.organizations) {
33+
return passportGeneralCallback(accessToken, refreshToken, profile, done)
34+
}
35+
const { statusCode, body: data } = await rp({
36+
url: `https://api.github.com/user/orgs`,
37+
method: 'GET', json: true, timeout: 2000,
38+
headers: {
39+
'Authorization': `token ${accessToken}`,
40+
'User-Agent': 'nodejs-http'
41+
}
42+
})
43+
if (statusCode != 200) {
44+
return done(InternalOAuthError(
45+
`Failed to query organizations for user: ${profile.username}`
46+
))
47+
}
48+
const orgs = data.map(({login}) => login)
49+
for (const org of orgs) {
50+
if (config.github.organizations.includes(org)) {
51+
return passportGeneralCallback(accessToken, refreshToken, profile, done)
52+
}
53+
}
54+
return done(InternalOAuthError(
55+
`User orgs not whitelisted: ${profile.username} (${orgs.join(',')})`
56+
))
57+
}))
2558

2659
githubAuth.get('/auth/github', function (req, res, next) {
2760
setReturnToFromReferer(req)
2861
passport.authenticate('github')(req, res, next)
2962
})
3063

31-
// github auth callback
3264
githubAuth.get('/auth/github/callback',
3365
passport.authenticate('github', {
3466
successReturnToOrRedirect: config.serverURL + '/',

lib/config/default.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ module.exports = {
115115
github: {
116116
enterpriseURL: undefined, // if you use github.com, not need to specify
117117
clientID: undefined,
118-
clientSecret: undefined
118+
clientSecret: undefined,
119+
organizations: [],
120+
scopes: ['read:user']
119121
},
120122
gitlab: {
121123
baseURL: undefined,

lib/config/environment.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ module.exports = {
6969
github: {
7070
enterpriseURL: process.env.CMD_GITHUB_ENTERPRISE_URL,
7171
clientID: process.env.CMD_GITHUB_CLIENTID,
72-
clientSecret: process.env.CMD_GITHUB_CLIENTSECRET
72+
clientSecret: process.env.CMD_GITHUB_CLIENTSECRET,
73+
organizations: toArrayConfig(process.env.CMD_GITHUB_ORGANIZATIONS),
74+
scopes: toArrayConfig(process.env.CMD_GITHUB_SCOPES),
7375
},
7476
bitbucket: {
7577
clientID: process.env.CMD_BITBUCKET_CLIENTID,

scalingo.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@
8080
"description": "GitHub API client secret",
8181
"required": false
8282
},
83+
"CMD_GITHUB_ORGANIZATIONS": {
84+
"description": "GitHub whitelist of orgs",
85+
"required": false
86+
},
87+
"CMD_GITHUB_SCOPES": {
88+
"description": "GitHub OAuth API scopes",
89+
"required": false
90+
},
8391
"CMD_BITBUCKET_CLIENTID": {
8492
"description": "Bitbucket API client id",
8593
"required": false

0 commit comments

Comments
 (0)