Skip to content

Commit 69b56ae

Browse files
committed
Add a field to specify a list of allowed emails when using OpenID Connect auth.
1 parent a2992ae commit 69b56ae

File tree

7 files changed

+149
-7
lines changed

7 files changed

+149
-7
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const migrate_name = 'openid_allowed_users';
2+
const logger = require('../logger').migrate;
3+
4+
/**
5+
* Migrate
6+
*
7+
* @see http://knexjs.org/#Schema
8+
*
9+
* @param {Object} knex
10+
* @param {Promise} Promise
11+
* @returns {Promise}
12+
*/
13+
exports.up = function (knex/*, Promise*/) {
14+
logger.info('[' + migrate_name + '] Migrating Up...');
15+
16+
return knex.schema.table('proxy_host', function (proxy_host) {
17+
proxy_host.integer('openidc_restrict_users_enabled').notNull().unsigned().defaultTo(0);
18+
proxy_host.json('openidc_allowed_users').notNull().defaultTo([]);
19+
})
20+
.then(() => {
21+
logger.info('[' + migrate_name + '] proxy_host Table altered');
22+
});
23+
};
24+
25+
/**
26+
* Undo Migrate
27+
*
28+
* @param {Object} knex
29+
* @param {Promise} Promise
30+
* @returns {Promise}
31+
*/
32+
exports.down = function (knex/*, Promise*/) {
33+
return knex.schema.table('proxy_host', function (proxy_host) {
34+
proxy_host.dropColumn('openidc_restrict_users_enabled');
35+
proxy_host.dropColumn('openidc_allowed_users');
36+
})
37+
.then(() => {
38+
logger.info('[' + migrate_name + '] proxy_host Table altered');
39+
});
40+
};

backend/models/proxy_host.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,18 @@ class ProxyHost extends Model {
1919
this.domain_names = [];
2020
}
2121

22+
// Default for openidc_allowed_users
23+
if (typeof this.openidc_allowed_users === 'undefined') {
24+
this.openidc_allowed_users = [];
25+
}
26+
2227
// Default for meta
2328
if (typeof this.meta === 'undefined') {
2429
this.meta = {};
2530
}
2631

2732
this.domain_names.sort();
33+
this.openidc_allowed_users.sort();
2834
}
2935

3036
$beforeUpdate () {
@@ -34,6 +40,11 @@ class ProxyHost extends Model {
3440
if (typeof this.domain_names !== 'undefined') {
3541
this.domain_names.sort();
3642
}
43+
44+
// Sort openidc_allowed_users
45+
if (typeof this.openidc_allowed_users !== 'undefined') {
46+
this.openidc_allowed_users.sort();
47+
}
3748
}
3849

3950
static get name () {
@@ -45,7 +56,7 @@ class ProxyHost extends Model {
4556
}
4657

4758
static get jsonAttributes () {
48-
return ['domain_names', 'meta', 'locations'];
59+
return ['domain_names', 'meta', 'locations', 'openidc_allowed_users'];
4960
}
5061

5162
static get relationMappings () {

backend/schema/definitions.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,22 @@
243243
},
244244
"openidc_client_secret": {
245245
"type": "string"
246+
},
247+
"openidc_restrict_users_enabled": {
248+
"description": "Only allow a specific set of OpenID Connect emails to access the resource",
249+
"example": true,
250+
"type": "boolean"
251+
},
252+
"openidc_allowed_users": {
253+
"type": "array",
254+
"minItems": 0,
255+
"items": {
256+
"type": "string",
257+
"description": "Email Address",
258+
"example": "john@example.com",
259+
"format": "email",
260+
"minLength": 1
261+
}
246262
}
247263
}
248264
}

backend/schema/endpoints/proxy-hosts.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@
8282
"openidc_client_secret": {
8383
"$ref": "../definitions.json#/definitions/openidc_client_secret"
8484
},
85+
"openidc_restrict_users_enabled": {
86+
"$ref": "../definitions.json#/definitions/openidc_restrict_users_enabled"
87+
},
88+
"openidc_allowed_users": {
89+
"$ref": "../definitions.json#/definitions/openidc_allowed_users"
90+
},
8591
"enabled": {
8692
"$ref": "../definitions.json#/definitions/enabled"
8793
},
@@ -197,6 +203,12 @@
197203
"openidc_client_secret": {
198204
"$ref": "#/definitions/openidc_client_secret"
199205
},
206+
"openidc_restrict_users_enabled": {
207+
"$ref": "#/definitions/openidc_restrict_users_enabled"
208+
},
209+
"openidc_allowed_users": {
210+
"$ref": "#/definitions/openidc_allowed_users"
211+
},
200212
"enabled": {
201213
"$ref": "#/definitions/enabled"
202214
},
@@ -305,6 +317,12 @@
305317
"openidc_client_secret": {
306318
"$ref": "#/definitions/openidc_client_secret"
307319
},
320+
"openidc_restrict_users_enabled": {
321+
"$ref": "#/definitions/openidc_restrict_users_enabled"
322+
},
323+
"openidc_allowed_users": {
324+
"$ref": "#/definitions/openidc_allowed_users"
325+
},
308326
"enabled": {
309327
"$ref": "#/definitions/enabled"
310328
},
@@ -396,6 +414,12 @@
396414
"openidc_client_secret": {
397415
"$ref": "#/definitions/openidc_client_secret"
398416
},
417+
"openidc_restrict_users_enabled": {
418+
"$ref": "#/definitions/openidc_restrict_users_enabled"
419+
},
420+
"openidc_allowed_users": {
421+
"$ref": "#/definitions/openidc_allowed_users"
422+
},
399423
"enabled": {
400424
"$ref": "#/definitions/enabled"
401425
},

frontend/js/app/nginx/proxy/form.ejs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@
187187
<label class="custom-switch">
188188
<input type="checkbox" class="custom-switch-input" name="openidc_enabled" value="1"<%- openidc_enabled ? ' checked' : '' %>>
189189
<span class="custom-switch-indicator"></span>
190-
<span class="custom-switch-description">Use OpenID Connect authentication <span class="form-required">*</span></span>
190+
<span class="custom-switch-description">Use OpenID Connect authentication</span>
191191
</label>
192192
</div>
193193
</div>
@@ -224,6 +224,23 @@
224224
<input type="text" name="openidc_client_secret" class="form-control text-monospace" placeholder="" value="<%- openidc_client_secret %>" autocomplete="off" maxlength="255" required>
225225
</div>
226226
</div>
227+
<div class="openidc">
228+
<div class="col-sm-12 col-md-12">
229+
<div class="form-group">
230+
<label class="custom-switch">
231+
<input type="checkbox" class="custom-switch-input" name="openidc_restrict_users_enabled" value="1"<%- openidc_restrict_users_enabled ? ' checked' : '' %>>
232+
<span class="custom-switch-indicator"></span>
233+
<span class="custom-switch-description">Allow only these user emails</span>
234+
</label>
235+
</div>
236+
</div>
237+
<div class="col-sm-12 col-md-12 openidc_users">
238+
<div class="form-group">
239+
<label class="form-label">Allowed email addresses<span class="form-required">*</span></label>
240+
<input type="text" name="openidc_allowed_users" class="form-control" id="openidc_allowed_users" value="<%- openidc_allowed_users.join(',') %>" required>
241+
</div>
242+
</div>
243+
</div>
227244
</div>
228245
</div>
229246
</div>

frontend/js/app/nginx/proxy/form.js

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ module.exports = Mn.View.extend({
3636
forward_scheme: 'select[name="forward_scheme"]',
3737
letsencrypt: '.letsencrypt',
3838
openidc_enabled: 'input[name="openidc_enabled"]',
39-
openidc: '.openidc'
39+
openidc_restrict_users_enabled: 'input[name="openidc_restrict_users_enabled"]',
40+
openidc_allowed_users: 'input[name="openidc_allowed_users"]',
41+
openidc: '.openidc',
42+
openidc_users: '.openidc_users'
4043
},
4144

4245
regions: {
@@ -97,9 +100,18 @@ module.exports = Mn.View.extend({
97100
let checked = this.ui.openidc_enabled.prop('checked');
98101

99102
if (checked) {
100-
this.ui.openidc.show().find('input').prop('required', true);
103+
this.ui.openidc.show().find('input').prop('disabled', false);
101104
} else {
102-
this.ui.openidc.hide().find('input').prop('required', false);
105+
this.ui.openidc.hide().find('input').prop('disabled', true);
106+
}
107+
},
108+
109+
'change @ui.openidc_restrict_users_enabled': function () {
110+
let checked = this.ui.openidc_restrict_users_enabled.prop('checked');
111+
if (checked) {
112+
this.ui.openidc_users.show().find('input').prop('disabled', false);
113+
} else {
114+
this.ui.openidc_users.hide().find('input').prop('disabled', true);
103115
}
104116
},
105117

@@ -141,11 +153,18 @@ module.exports = Mn.View.extend({
141153
data.hsts_subdomains = !!data.hsts_subdomains;
142154
data.ssl_forced = !!data.ssl_forced;
143155
data.openidc_enabled = data.openidc_enabled === '1';
156+
data.openidc_restrict_users_enabled = data.openidc_restrict_users_enabled === '1';
157+
158+
if (data.openidc_restrict_users_enabled) {
159+
if (typeof data.openidc_allowed_users === 'string' && data.openidc_allowed_users) {
160+
data.openidc_allowed_users = data.openidc_allowed_users.split(',');
161+
}
162+
}
144163

145164
if (typeof data.domain_names === 'string' && data.domain_names) {
146165
data.domain_names = data.domain_names.split(',');
147166
}
148-
167+
149168
// Check for any domain names containing wildcards, which are not allowed with letsencrypt
150169
if (data.certificate_id === 'new') {
151170
let domain_err = false;
@@ -287,8 +306,21 @@ module.exports = Mn.View.extend({
287306
});
288307

289308
// OpenID Connect
290-
this.ui.openidc.hide().find('input').prop('required', false);
309+
this.ui.openidc_allowed_users.selectize({
310+
delimiter: ',',
311+
persist: false,
312+
maxOptions: 15,
313+
create: function (input) {
314+
return {
315+
value: input,
316+
text: input
317+
};
318+
}
319+
});
320+
this.ui.openidc.hide().find('input').prop('disabled', true);
321+
this.ui.openidc_users.hide().find('input').prop('disabled', true);
291322
this.ui.openidc_enabled.trigger('change');
323+
this.ui.openidc_restrict_users_enabled.trigger('change');
292324
},
293325

294326
initialize: function (options) {

frontend/js/models/proxy-host.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ const model = Backbone.Model.extend({
2828
openidc_auth_method: 'client_secret_post',
2929
openidc_client_id: '',
3030
openidc_client_secret: '',
31+
openidc_restrict_users_enabled: false,
32+
openidc_allowed_users: [],
3133
enabled: true,
3234
meta: {},
3335
// The following are expansions:

0 commit comments

Comments
 (0)