mirror of
https://github.com/cryptpad/cryptpad.git
synced 2026-09-14 11:05:41 +05:00
Restrict SSO registration
This commit is contained in:
parent
e52d9f77c1
commit
e65baebadc
@ -49,9 +49,11 @@ define([
|
||||
|
||||
Exports.ssoAuth = function (provider, cb) {
|
||||
var keys = Nacl.sign.keyPair();
|
||||
var inviteToken = window.location.hash.slice(1);
|
||||
localStorage.CP_sso_auth = JSON.stringify({
|
||||
s: Nacl.util.encodeBase64(keys.secretKey),
|
||||
p: Nacl.util.encodeBase64(keys.publicKey)
|
||||
p: Nacl.util.encodeBase64(keys.publicKey),
|
||||
token: inviteToken
|
||||
});
|
||||
ServerCommand(keys, {
|
||||
command: 'SSO_AUTH',
|
||||
|
||||
@ -56,6 +56,7 @@ define([
|
||||
h('h2', Msg.register_notes_title),
|
||||
Pages.setHTML(h('div.cp-register-notes'), Msg.register_notes)
|
||||
]),
|
||||
h('div.col-md-3.cp-closed-filler'+ssoEnabled, h('div')),
|
||||
h('div.cp-reg-form.col-md-6', [
|
||||
h('div#userForm.form-group'+ssoEnforced, [
|
||||
h('div.cp-register-instance', [
|
||||
@ -105,6 +106,7 @@ define([
|
||||
h('div.cp-register-sso', Msg.sso_register_description)
|
||||
]),
|
||||
]),
|
||||
h('div.col-md-3.cp-closed-filler'+ssoEnabled),
|
||||
])
|
||||
]);
|
||||
};
|
||||
|
||||
@ -22,6 +22,9 @@
|
||||
.cp-restricted-registration {
|
||||
display: none;
|
||||
}
|
||||
.cp-closed-filler {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&.cp-register-closed {
|
||||
div.cp-register-det {
|
||||
|
||||
@ -461,6 +461,8 @@ var setLastEviction = function (Env, Server, cb, data, unsafeKey) {
|
||||
var instanceStatus = function (Env, Server, cb) {
|
||||
cb(void 0, {
|
||||
restrictRegistration: Env.restrictRegistration,
|
||||
restrictSsoRegistration: Env.restrictSsoRegistration,
|
||||
|
||||
enableEmbedding: Env.enableEmbedding,
|
||||
launchTime: Env.launchTime,
|
||||
currentTime: +new Date(),
|
||||
|
||||
@ -111,7 +111,7 @@ Block.validateAncestorProof = function (Env, proof, _cb) {
|
||||
|
||||
Block.writeLoginBlock = function (Env, msg, _cb) {
|
||||
var cb = Util.once(Util.mkAsync(_cb));
|
||||
const { publicKey, signature, ciphertext, registrationProof, userData, inviteToken } = msg;
|
||||
const { publicKey, signature, ciphertext, registrationProof, userData, inviteToken, isSSO } = msg;
|
||||
|
||||
var previousKey;
|
||||
var validatedBlock, path;
|
||||
@ -123,9 +123,11 @@ Block.writeLoginBlock = function (Env, msg, _cb) {
|
||||
if (err || !state) { return; } // Invalid token, don't abort, check registration proof
|
||||
validatedInvite = true;
|
||||
}));
|
||||
}).nThen(function (w) {
|
||||
}).nThen(function (w) {
|
||||
if (!Env.restrictRegistration) { return; }
|
||||
if (!registrationProof && !validatedInvite) {
|
||||
var ssoAllowed = isSSO && !Env.restrictSsoRegistration
|
||||
if (!(registrationProof || validatedInvite || ssoAllowed)) {
|
||||
// we allow users with existing blocks to create new ones
|
||||
// call back with error if registration is restricted and no proof of an existing block was provided
|
||||
w.abort();
|
||||
@ -134,9 +136,9 @@ Block.writeLoginBlock = function (Env, msg, _cb) {
|
||||
});
|
||||
return cb("E_RESTRICTED");
|
||||
}
|
||||
if (!registrationProof) { return; }
|
||||
Block.validateAncestorProof(Env, registrationProof, w(function (err, provenKey) {
|
||||
if (err || !provenKey) { // double check that a key was validated
|
||||
if (validatedInvite) { return; }
|
||||
w.abort();
|
||||
Env.Log.warn('BLOCK_REJECTED_INVALID_ANCESTOR', {
|
||||
error: err,
|
||||
|
||||
@ -10,6 +10,7 @@ var Core = require("./commands/core");
|
||||
IMPLEMENTED:
|
||||
|
||||
RESTRICT_REGISTRATION(<boolean>)
|
||||
RESTRICT_SSO_REGISTRATION(<boolean>)
|
||||
UPDATE_DEFAULT_STORAGE(<number>)
|
||||
|
||||
// QUOTA MANAGEMENT
|
||||
@ -112,6 +113,7 @@ commands.ENFORCE_MFA = makeBooleanSetter('enforceMFA');
|
||||
|
||||
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['RESTRICT_REGISTRATION', [true]]], console.log)
|
||||
commands.RESTRICT_REGISTRATION = makeBooleanSetter('restrictRegistration');
|
||||
commands.RESTRICT_SSO_REGISTRATION = makeBooleanSetter('restrictSsoRegistration');
|
||||
|
||||
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['DISABLE_INTEGRATED_EVICTION', [true]]], console.log)
|
||||
commands.DISABLE_INTEGRATED_EVICTION = makeBooleanSetter('disableIntegratedEviction');
|
||||
|
||||
@ -579,6 +579,7 @@ var serveConfig = makeRouteCache(function () {
|
||||
maxUploadSize: Env.maxUploadSize,
|
||||
premiumUploadSize: Env.premiumUploadSize,
|
||||
restrictRegistration: Env.restrictRegistration,
|
||||
restrictSsoRegistration: Env.restrictSsoRegistration,
|
||||
httpSafeOrigin: Env.httpSafeOrigin,
|
||||
enableEmbedding: Env.enableEmbedding,
|
||||
fileHost: Env.fileHost,
|
||||
|
||||
@ -1495,29 +1495,81 @@ Example
|
||||
};
|
||||
|
||||
// Msg.admin_registrationHint, .admin_registrationTitle
|
||||
create['registration'] = makeAdminCheckbox({
|
||||
key: 'registration',
|
||||
getState: function () {
|
||||
return APP.instanceStatus.restrictRegistration;
|
||||
},
|
||||
query: function (val, setState) {
|
||||
sFrameChan.query('Q_ADMIN_RPC', {
|
||||
cmd: 'ADMIN_DECREE',
|
||||
data: ['RESTRICT_REGISTRATION', [val]]
|
||||
}, function (e, response) {
|
||||
if (e || response.error) {
|
||||
UI.warn(Messages.error);
|
||||
console.error(e, response);
|
||||
}
|
||||
APP.updateStatus(function () {
|
||||
setState(APP.instanceStatus.restrictRegistration);
|
||||
flushCacheNotice();
|
||||
// Msg.admin_registrationSsoTitle
|
||||
Messages.admin_registrationSsoTitle = "ALSO CLOSE SSO REGISTRATION"; // XXX
|
||||
create['registration'] = function () {
|
||||
var key = 'registration';
|
||||
|
||||
var refresh = function () {};
|
||||
|
||||
var $div = makeAdminCheckbox({
|
||||
key: 'registration',
|
||||
getState: function () {
|
||||
return APP.instanceStatus.restrictRegistration;
|
||||
},
|
||||
query: function (val, setState) {
|
||||
sFrameChan.query('Q_ADMIN_RPC', {
|
||||
cmd: 'ADMIN_DECREE',
|
||||
data: ['RESTRICT_REGISTRATION', [val]]
|
||||
}, function (e, response) {
|
||||
if (e || response.error) {
|
||||
UI.warn(Messages.error);
|
||||
console.error(e, response);
|
||||
}
|
||||
APP.updateStatus(function () {
|
||||
setState(APP.instanceStatus.restrictRegistration);
|
||||
refresh();
|
||||
flushCacheNotice();
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
var $sso = makeAdminCheckbox({
|
||||
key: 'registration-sso',
|
||||
getState: function () {
|
||||
return APP.instanceStatus.restrictSsoRegistration;
|
||||
},
|
||||
query: function (val, setState) {
|
||||
sFrameChan.query('Q_ADMIN_RPC', {
|
||||
cmd: 'ADMIN_DECREE',
|
||||
data: ['RESTRICT_SSO_REGISTRATION', [val]]
|
||||
}, function (e, response) {
|
||||
if (e || response.error) {
|
||||
UI.warn(Messages.error);
|
||||
console.error(e, response);
|
||||
}
|
||||
APP.updateStatus(function () {
|
||||
setState(APP.instanceStatus.restrictSsoRegistration);
|
||||
flushCacheNotice();
|
||||
});
|
||||
});
|
||||
}
|
||||
})();
|
||||
var ssoEnabled = ApiConfig.sso && ApiConfig.sso.list && ApiConfig.sso.list.length;
|
||||
if (ssoEnabled) {
|
||||
$sso.find('#cp-admin-registration-sso').hide();
|
||||
$sso.find('> span.cp-sidebarlayout-description').hide();
|
||||
$div.append($sso);
|
||||
}
|
||||
|
||||
refresh = () => {
|
||||
var closed = APP.instanceStatus.restrictRegistration;
|
||||
if (closed) {
|
||||
$sso.show();
|
||||
} else {
|
||||
$sso.hide();
|
||||
}
|
||||
};
|
||||
refresh();
|
||||
|
||||
|
||||
return $div;
|
||||
};
|
||||
|
||||
Messages.admin_invitationCreate = "Create invitation link"; // XXX
|
||||
Messages.admin_invitationHint = "Create invitation links to allow users to register even when registration is closed";
|
||||
Messages.admin_invitationTitle = "Invitation links";
|
||||
create['invitation'] = function () {
|
||||
var key = 'invitation';
|
||||
var $div = makeBlock(key); // Msg.admin_invitationHint, admin_invitationTitle
|
||||
@ -1610,7 +1662,9 @@ Example
|
||||
return $div;
|
||||
};
|
||||
|
||||
Messages.admin_usersAdd = "Add known user";
|
||||
Messages.admin_usersAdd = "Add known user"; // XXX
|
||||
Messages.admin_userHint = "List of known users. You can add more using the form and select automated options";
|
||||
Messages.admin_userTitle = "Known users";
|
||||
create['users'] = function () {
|
||||
var key = 'users';
|
||||
var $div = makeBlock(key); // Msg.admin_usersHint, admin_usersTitle
|
||||
|
||||
@ -34,6 +34,10 @@ define([
|
||||
var hash = window.location.hash.slice(1);
|
||||
token = hash;
|
||||
$('body').removeClass('cp-register-closed');
|
||||
} else if (Config.sso && Config.restrictRegistration && !Config.restrictSsoRegistration) {
|
||||
$('body').find('.cp-register-det').css('display', 'flex');
|
||||
$('body').find('#data').hide();
|
||||
$('body').find('#userForm').hide();
|
||||
}
|
||||
|
||||
// text and password input fields
|
||||
@ -69,7 +73,6 @@ define([
|
||||
var list = Config.sso.list.map(function (name) {
|
||||
var b = h('button.btn.btn-secondary', name);
|
||||
var $b = $(b).click(function () {
|
||||
console.log('sso register click:', name);
|
||||
$b.prop('disabled', 'disabled');
|
||||
Login.ssoAuth(name, function (err, data) {
|
||||
if (data.url) {
|
||||
|
||||
@ -33,19 +33,22 @@ define([
|
||||
secretKey: Nacl.util.decodeBase64(b64Keys.s),
|
||||
publicKey: Nacl.util.decodeBase64(b64Keys.p)
|
||||
};
|
||||
var inviteToken = b64Keys.token;
|
||||
ServerCommand(keys, {
|
||||
command: 'SSO_AUTH_CB',
|
||||
url: window.location.href
|
||||
}, function (err, data) {
|
||||
delete localStorage.CP_sso_auth;
|
||||
document.cookie = 'ssotoken=; Max-Age=-99999999;';
|
||||
if (data) { data.inviteToken = inviteToken; }
|
||||
cb(err, data);
|
||||
});
|
||||
};
|
||||
let ssoLoginRegister = function (seed, pw, jwt, name, isRegister) {
|
||||
let ssoLoginRegister = function (seed, pw, jwt, name, isRegister, inviteToken) {
|
||||
Login.loginOrRegister({
|
||||
uname: seed,
|
||||
passwd: pw,
|
||||
token: inviteToken,
|
||||
isRegister: isRegister,
|
||||
onOTP: UI.getOTPScreen,
|
||||
ssoAuth: {
|
||||
@ -97,7 +100,7 @@ define([
|
||||
hideTips: true,
|
||||
});
|
||||
setTimeout(function () { // Second timeout for the loading screen befofe Scrypt
|
||||
ssoLoginRegister(seed, pw, jwt, name, data.register);
|
||||
ssoLoginRegister(seed, pw, jwt, name, data.register, data.inviteToken);
|
||||
}, 100);
|
||||
}, 100);
|
||||
|
||||
@ -108,6 +111,10 @@ define([
|
||||
return void next('');
|
||||
}
|
||||
|
||||
if (data.register && ApiConfig.restrictSsoRegistration && !data.inviteToken) {
|
||||
return void UI.errorLoadingScreen(Messages.register_registrationIsClosed);
|
||||
}
|
||||
|
||||
// Registration and CP password disabled, continue
|
||||
if (data.register && !ApiConfig.sso.password) {
|
||||
return void next('');
|
||||
@ -130,14 +137,17 @@ define([
|
||||
|
||||
$button.click(() => {
|
||||
let pw = $pw.val();
|
||||
let warning = Messages._getKey('register_passwordTooShort', [
|
||||
Cred.MINIMUM_PASSWORD_LENGTH
|
||||
]);
|
||||
if (data.register && pw !== $pw2.val()) {
|
||||
return void UI.warn(Messages.register_passwordsDontMatch);
|
||||
}
|
||||
if (data.register && pw && !Cred.isLongEnoughPassword(pw)) {
|
||||
return void UI.warn(Messages.register_passwordTooShort);
|
||||
return void UI.warn(warning);
|
||||
}
|
||||
if (data.register && !pw && ApiConfig.sso.password === 2) {
|
||||
return void UI.warn(Messages.register_passwordTooShort);
|
||||
return void UI.warn(warning);
|
||||
}
|
||||
$button.prop('disabled', 'disabled');
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user