Skip to content

Commit cdf702e

Browse files
Subvjc21
authored andcommitted
Add a field to specify a list of allowed emails when using OpenID Connect auth.
1 parent 5811345 commit cdf702e

File tree

7 files changed

+172
-30
lines changed

7 files changed

+172
-30
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
@@ -20,12 +20,18 @@ class ProxyHost extends Model {
2020
this.domain_names = [];
2121
}
2222

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

2833
this.domain_names.sort();
34+
this.openidc_allowed_users.sort();
2935
}
3036

3137
$beforeUpdate () {
@@ -35,6 +41,11 @@ class ProxyHost extends Model {
3541
if (typeof this.domain_names !== 'undefined') {
3642
this.domain_names.sort();
3743
}
44+
45+
// Sort openidc_allowed_users
46+
if (typeof this.openidc_allowed_users !== 'undefined') {
47+
this.openidc_allowed_users.sort();
48+
}
3849
}
3950

4051
static get name () {
@@ -46,7 +57,7 @@ class ProxyHost extends Model {
4657
}
4758

4859
static get jsonAttributes () {
49-
return ['domain_names', 'meta', 'locations'];
60+
return ['domain_names', 'meta', 'locations', 'openidc_allowed_users'];
5061
}
5162

5263
static get relationMappings () {

backend/schema/definitions.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,22 @@
256256
},
257257
"openidc_client_secret": {
258258
"type": "string"
259+
},
260+
"openidc_restrict_users_enabled": {
261+
"description": "Only allow a specific set of OpenID Connect emails to access the resource",
262+
"example": true,
263+
"type": "boolean"
264+
},
265+
"openidc_allowed_users": {
266+
"type": "array",
267+
"minItems": 0,
268+
"items": {
269+
"type": "string",
270+
"description": "Email Address",
271+
"example": "[email protected]",
272+
"format": "email",
273+
"minLength": 1
274+
}
259275
}
260276
}
261277
}

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
@@ -280,7 +280,7 @@
280280
<label class="custom-switch">
281281
<input type="checkbox" class="custom-switch-input" name="openidc_enabled" value="1"<%- openidc_enabled ? ' checked' : '' %>>
282282
<span class="custom-switch-indicator"></span>
283-
<span class="custom-switch-description">Use OpenID Connect authentication <span class="form-required">*</span></span>
283+
<span class="custom-switch-description">Use OpenID Connect authentication</span>
284284
</label>
285285
</div>
286286
</div>
@@ -317,6 +317,23 @@
317317
<input type="text" name="openidc_client_secret" class="form-control text-monospace" placeholder="" value="<%- openidc_client_secret %>" autocomplete="off" maxlength="255" required>
318318
</div>
319319
</div>
320+
<div class="openidc">
321+
<div class="col-sm-12 col-md-12">
322+
<div class="form-group">
323+
<label class="custom-switch">
324+
<input type="checkbox" class="custom-switch-input" name="openidc_restrict_users_enabled" value="1"<%- openidc_restrict_users_enabled ? ' checked' : '' %>>
325+
<span class="custom-switch-indicator"></span>
326+
<span class="custom-switch-description">Allow only these user emails</span>
327+
</label>
328+
</div>
329+
</div>
330+
<div class="col-sm-12 col-md-12 openidc_users">
331+
<div class="form-group">
332+
<label class="form-label">Allowed email addresses<span class="form-required">*</span></label>
333+
<input type="text" name="openidc_allowed_users" class="form-control" id="openidc_allowed_users" value="<%- openidc_allowed_users.join(',') %>" required>
334+
</div>
335+
</div>
336+
</div>
320337
</div>
321338
</div>
322339
</div>

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

Lines changed: 60 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,34 @@ module.exports = Mn.View.extend({
2121
locationsCollection: new ProxyLocationModel.Collection(),
2222

2323
ui: {
24-
form: 'form',
25-
domain_names: 'input[name="domain_names"]',
26-
forward_host: 'input[name="forward_host"]',
27-
buttons: '.modal-footer button',
28-
cancel: 'button.cancel',
29-
save: 'button.save',
30-
add_location_btn: 'button.add_location',
31-
locations_container: '.locations_container',
32-
le_error_info: '#le-error-info',
33-
certificate_select: 'select[name="certificate_id"]',
34-
access_list_select: 'select[name="access_list_id"]',
35-
ssl_forced: 'input[name="ssl_forced"]',
36-
hsts_enabled: 'input[name="hsts_enabled"]',
37-
hsts_subdomains: 'input[name="hsts_subdomains"]',
38-
http2_support: 'input[name="http2_support"]',
39-
dns_challenge_switch: 'input[name="meta[dns_challenge]"]',
40-
dns_challenge_content: '.dns-challenge',
41-
dns_provider: 'select[name="meta[dns_provider]"]',
42-
credentials_file_content: '.credentials-file-content',
43-
dns_provider_credentials: 'textarea[name="meta[dns_provider_credentials]"]',
44-
propagation_seconds: 'input[name="meta[propagation_seconds]"]',
45-
forward_scheme: 'select[name="forward_scheme"]',
46-
letsencrypt: '.letsencrypt',
47-
openidc_enabled: 'input[name="openidc_enabled"]',
48-
openidc: '.openidc'
24+
form: 'form',
25+
domain_names: 'input[name="domain_names"]',
26+
forward_host: 'input[name="forward_host"]',
27+
buttons: '.modal-footer button',
28+
cancel: 'button.cancel',
29+
save: 'button.save',
30+
add_location_btn: 'button.add_location',
31+
locations_container: '.locations_container',
32+
le_error_info: '#le-error-info',
33+
certificate_select: 'select[name="certificate_id"]',
34+
access_list_select: 'select[name="access_list_id"]',
35+
ssl_forced: 'input[name="ssl_forced"]',
36+
hsts_enabled: 'input[name="hsts_enabled"]',
37+
hsts_subdomains: 'input[name="hsts_subdomains"]',
38+
http2_support: 'input[name="http2_support"]',
39+
dns_challenge_switch: 'input[name="meta[dns_challenge]"]',
40+
dns_challenge_content: '.dns-challenge',
41+
dns_provider: 'select[name="meta[dns_provider]"]',
42+
credentials_file_content: '.credentials-file-content',
43+
dns_provider_credentials: 'textarea[name="meta[dns_provider_credentials]"]',
44+
propagation_seconds: 'input[name="meta[propagation_seconds]"]',
45+
forward_scheme: 'select[name="forward_scheme"]',
46+
letsencrypt: '.letsencrypt',
47+
openidc_enabled: 'input[name="openidc_enabled"]',
48+
openidc_restrict_users_enabled: 'input[name="openidc_restrict_users_enabled"]',
49+
openidc_allowed_users: 'input[name="openidc_allowed_users"]',
50+
openidc: '.openidc',
51+
openidc_users: '.openidc_users',
4952
},
5053

5154
regions: {
@@ -135,9 +138,18 @@ module.exports = Mn.View.extend({
135138
let checked = this.ui.openidc_enabled.prop('checked');
136139

137140
if (checked) {
138-
this.ui.openidc.show().find('input').prop('required', true);
141+
this.ui.openidc.show().find('input').prop('disabled', false);
139142
} else {
140-
this.ui.openidc.hide().find('input').prop('required', false);
143+
this.ui.openidc.hide().find('input').prop('disabled', true);
144+
}
145+
},
146+
147+
'change @ui.openidc_restrict_users_enabled': function () {
148+
let checked = this.ui.openidc_restrict_users_enabled.prop('checked');
149+
if (checked) {
150+
this.ui.openidc_users.show().find('input').prop('disabled', false);
151+
} else {
152+
this.ui.openidc_users.hide().find('input').prop('disabled', true);
141153
}
142154
},
143155

@@ -180,6 +192,13 @@ module.exports = Mn.View.extend({
180192
data.hsts_subdomains = !!data.hsts_subdomains;
181193
data.ssl_forced = !!data.ssl_forced;
182194
data.openidc_enabled = data.openidc_enabled === '1';
195+
data.openidc_restrict_users_enabled = data.openidc_restrict_users_enabled === '1';
196+
197+
if (data.openidc_restrict_users_enabled) {
198+
if (typeof data.openidc_allowed_users === 'string' && data.openidc_allowed_users) {
199+
data.openidc_allowed_users = data.openidc_allowed_users.split(',');
200+
}
201+
}
183202

184203
if (typeof data.meta === 'undefined') data.meta = {};
185204
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree == 1;
@@ -365,8 +384,21 @@ module.exports = Mn.View.extend({
365384
});
366385

367386
// OpenID Connect
368-
this.ui.openidc.hide().find('input').prop('required', false);
387+
this.ui.openidc_allowed_users.selectize({
388+
delimiter: ',',
389+
persist: false,
390+
maxOptions: 15,
391+
create: function (input) {
392+
return {
393+
value: input,
394+
text: input
395+
};
396+
}
397+
});
398+
this.ui.openidc.hide().find('input').prop('disabled', true);
399+
this.ui.openidc_users.hide().find('input').prop('disabled', true);
369400
this.ui.openidc_enabled.trigger('change');
401+
this.ui.openidc_restrict_users_enabled.trigger('change');
370402
},
371403

372404
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)