commit
fe5de27885
@ -86,14 +86,27 @@ export const QuotaBarTypes = Object.freeze({
|
||||
export const BINDING_POST = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST";
|
||||
export const BINDING_REDIRECT =
|
||||
"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect";
|
||||
export const SSO_NAME_ID_FORMAT =
|
||||
"urn:oasis:names:tc:SAML:2.0:nameid-format:transient";
|
||||
export const SSO_NAME_ID_FORMAT = [
|
||||
"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified",
|
||||
"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
||||
"urn:oasis:names:tc:SAML:2.0:nameid-format:entity",
|
||||
"urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
|
||||
"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
|
||||
"urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted",
|
||||
"urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified",
|
||||
"urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName",
|
||||
"urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName",
|
||||
"urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos",
|
||||
];
|
||||
export const SSO_GIVEN_NAME = "givenName";
|
||||
export const SSO_SN = "sn";
|
||||
export const SSO_EMAIL = "email";
|
||||
export const SSO_LOCATION = "location";
|
||||
export const SSO_TITLE = "title";
|
||||
export const SSO_PHONE = "phone";
|
||||
export const SSO_SIGNING = "signing";
|
||||
export const SSO_ENCRYPT = "encrypt";
|
||||
export const SSO_SIGNING_ENCRYPT = "signing and encrypt";
|
||||
|
||||
export const DEFAULT_SELECT_TIMEZONE = {
|
||||
key: "UTC",
|
||||
|
@ -41,6 +41,9 @@ const Certificates = (props) => {
|
||||
spEncryptAlgorithm,
|
||||
spDecryptAlgorithm,
|
||||
isLoadingXml,
|
||||
isDisabledSpSigning,
|
||||
isDisabledSpEncrypt,
|
||||
isDisabledIdpSigning,
|
||||
} = props;
|
||||
|
||||
let prefix = "";
|
||||
@ -139,7 +142,7 @@ const Certificates = (props) => {
|
||||
{provider === "IdentityProvider" && (
|
||||
<>
|
||||
<SsoComboBox
|
||||
isDisabled={idpCertificates.length === 0}
|
||||
isDisabled={isDisabledIdpSigning}
|
||||
labelText={t("idpSigningAlgorithm")}
|
||||
name="idpVerifyAlgorithm"
|
||||
options={verifyAlgorithmsOptions}
|
||||
@ -152,7 +155,7 @@ const Certificates = (props) => {
|
||||
{provider === "ServiceProvider" && (
|
||||
<>
|
||||
<SsoComboBox
|
||||
isDisabled={spCertificates.length === 0}
|
||||
isDisabled={isDisabledSpSigning}
|
||||
labelText={t("spSigningAlgorithm")}
|
||||
name="spSigningAlgorithm"
|
||||
options={verifyAlgorithmsOptions}
|
||||
@ -161,7 +164,7 @@ const Certificates = (props) => {
|
||||
/>
|
||||
|
||||
<SsoComboBox
|
||||
isDisabled={spCertificates.length === 0}
|
||||
isDisabled={isDisabledSpEncrypt}
|
||||
labelText={t("StandardDecryptionAlgorithm")}
|
||||
name={"spEncryptAlgorithm"}
|
||||
options={decryptAlgorithmsOptions}
|
||||
@ -193,6 +196,9 @@ export default inject(({ ssoStore }) => {
|
||||
spEncryptAlgorithm,
|
||||
spDecryptAlgorithm,
|
||||
isLoadingXml,
|
||||
isDisabledSpSigning,
|
||||
isDisabledSpEncrypt,
|
||||
isDisabledIdpSigning,
|
||||
} = ssoStore;
|
||||
|
||||
return {
|
||||
@ -207,5 +213,8 @@ export default inject(({ ssoStore }) => {
|
||||
spEncryptAlgorithm,
|
||||
spDecryptAlgorithm,
|
||||
isLoadingXml,
|
||||
isDisabledSpSigning,
|
||||
isDisabledSpEncrypt,
|
||||
isDisabledIdpSigning,
|
||||
};
|
||||
})(observer(Certificates));
|
||||
|
@ -27,8 +27,8 @@ const CertificatesTable = (props) => {
|
||||
console.log(prefix, index);
|
||||
const onEdit = () => {
|
||||
prefix === "sp"
|
||||
? setSpCertificate(certificate, index)
|
||||
: setIdpCertificate(certificate);
|
||||
? setSpCertificate(certificate, index, true)
|
||||
: setIdpCertificate(certificate, index, true);
|
||||
};
|
||||
|
||||
const onDelete = () => {
|
||||
|
@ -44,11 +44,15 @@ const CheckboxSet = (props) => {
|
||||
spSignLogoutRequests,
|
||||
spSignLogoutResponses,
|
||||
spEncryptAssertions,
|
||||
enableSso,
|
||||
setCheckbox,
|
||||
isLoadingXml,
|
||||
isDisabledSpSigning,
|
||||
isDisabledSpEncrypt,
|
||||
isDisabledIdpSigning,
|
||||
} = props;
|
||||
|
||||
const isDisabled =
|
||||
prefix === "sp" ? isDisabledSpSigning : isDisabledIdpSigning;
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<Checkbox
|
||||
@ -58,7 +62,7 @@ const CheckboxSet = (props) => {
|
||||
: "sp-sign-auth-requests"
|
||||
}
|
||||
className="checkbox-input"
|
||||
isDisabled={!enableSso || isLoadingXml}
|
||||
isDisabled={isDisabled}
|
||||
onChange={setCheckbox}
|
||||
label={prefix === "idp" ? t("idpAuthRequest") : t("spAuthRequest")}
|
||||
name={checkboxesNames[prefix][0]}
|
||||
@ -74,7 +78,7 @@ const CheckboxSet = (props) => {
|
||||
: "sp-sign-logout-requests"
|
||||
}
|
||||
className="checkbox-input"
|
||||
isDisabled={!enableSso || isLoadingXml}
|
||||
isDisabled={isDisabled}
|
||||
onChange={setCheckbox}
|
||||
label={
|
||||
prefix === "idp" ? t("idpSignExitRequest") : t("spSignExitRequest")
|
||||
@ -92,7 +96,7 @@ const CheckboxSet = (props) => {
|
||||
: "sp-sign-logout-responses"
|
||||
}
|
||||
className="checkbox-input"
|
||||
isDisabled={!enableSso || isLoadingXml}
|
||||
isDisabled={isDisabled}
|
||||
onChange={setCheckbox}
|
||||
label={
|
||||
prefix === "idp"
|
||||
@ -112,7 +116,7 @@ const CheckboxSet = (props) => {
|
||||
<Checkbox
|
||||
id="sp-encrypt-assertions"
|
||||
className="checkbox-input"
|
||||
isDisabled={!enableSso || isLoadingXml}
|
||||
isDisabled={isDisabledSpEncrypt}
|
||||
onChange={setCheckbox}
|
||||
label={t("spDecryptStatements")}
|
||||
name={checkboxesNames[prefix][3]}
|
||||
@ -133,9 +137,10 @@ export default inject(({ ssoStore }) => {
|
||||
spSignLogoutRequests,
|
||||
spSignLogoutResponses,
|
||||
spEncryptAssertions,
|
||||
enableSso,
|
||||
setCheckbox,
|
||||
isLoadingXml,
|
||||
isDisabledSpSigning,
|
||||
isDisabledSpEncrypt,
|
||||
isDisabledIdpSigning,
|
||||
} = ssoStore;
|
||||
|
||||
return {
|
||||
@ -146,8 +151,9 @@ export default inject(({ ssoStore }) => {
|
||||
spSignLogoutRequests,
|
||||
spSignLogoutResponses,
|
||||
spEncryptAssertions,
|
||||
enableSso,
|
||||
setCheckbox,
|
||||
isLoadingXml,
|
||||
isDisabledSpSigning,
|
||||
isDisabledSpEncrypt,
|
||||
isDisabledIdpSigning,
|
||||
};
|
||||
})(observer(CheckboxSet));
|
||||
|
@ -19,6 +19,9 @@ import {
|
||||
SSO_TITLE,
|
||||
SSO_PHONE,
|
||||
SSO_NAME_ID_FORMAT,
|
||||
SSO_SIGNING,
|
||||
SSO_ENCRYPT,
|
||||
SSO_SIGNING_ENCRYPT,
|
||||
} from "../helpers/constants";
|
||||
import isEqual from "lodash/isEqual";
|
||||
|
||||
@ -41,11 +44,11 @@ class SsoFormStore {
|
||||
sloUrlPost = "";
|
||||
sloUrlRedirect = "";
|
||||
sloBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST";
|
||||
nameIdFormat = SSO_NAME_ID_FORMAT;
|
||||
nameIdFormat = SSO_NAME_ID_FORMAT[0];
|
||||
|
||||
idpCertificate = "";
|
||||
idpPrivateKey = null;
|
||||
idpAction = "signing";
|
||||
idpAction = SSO_SIGNING;
|
||||
idpCertificates = [];
|
||||
|
||||
// idpCertificateAdvanced
|
||||
@ -59,7 +62,7 @@ class SsoFormStore {
|
||||
|
||||
spCertificate = "";
|
||||
spPrivateKey = "";
|
||||
spAction = "signing";
|
||||
spAction = SSO_SIGNING;
|
||||
spCertificates = [];
|
||||
|
||||
// spCertificateAdvanced
|
||||
@ -126,6 +129,7 @@ class SsoFormStore {
|
||||
|
||||
defaultSettings = null;
|
||||
editIndex = 0;
|
||||
isEdit = false;
|
||||
|
||||
isInit = false;
|
||||
|
||||
@ -191,6 +195,8 @@ class SsoFormStore {
|
||||
closeIdpModal = () => {
|
||||
this.idpCertificate = "";
|
||||
this.idpPrivateKey = "";
|
||||
this.editIndex = 0;
|
||||
this.isEdit = false;
|
||||
this.idpIsModalVisible = false;
|
||||
};
|
||||
|
||||
@ -199,6 +205,7 @@ class SsoFormStore {
|
||||
this.spPrivateKey = "";
|
||||
this.spIsModalVisible = false;
|
||||
this.editIndex = 0;
|
||||
this.isEdit = false;
|
||||
};
|
||||
|
||||
setComboBoxOption = (option) => {
|
||||
@ -638,33 +645,77 @@ class SsoFormStore {
|
||||
return array.filter((item, index, array) => array.indexOf(item) == index);
|
||||
};
|
||||
|
||||
setSpCertificate = (certificate, index) => {
|
||||
setSpCertificate = (certificate, index, isEdit) => {
|
||||
this.spCertificate = certificate.crt;
|
||||
this.spPrivateKey = certificate.key;
|
||||
this.spAction = certificate.action;
|
||||
this.editIndex = index;
|
||||
this.isEdit = isEdit;
|
||||
this.spIsModalVisible = true;
|
||||
};
|
||||
|
||||
setIdpCertificate = (certificate) => {
|
||||
setIdpCertificate = (certificate, index, isEdit) => {
|
||||
this.idpCertificate = certificate.crt;
|
||||
this.idpPrivateKey = certificate.key;
|
||||
this.idpAction = certificate.action;
|
||||
this.editIndex = index;
|
||||
this.isEdit = isEdit;
|
||||
this.idpIsModalVisible = true;
|
||||
};
|
||||
|
||||
resetSpCheckboxes = (action) => {
|
||||
if (action === SSO_SIGNING_ENCRYPT) {
|
||||
this.spSignAuthRequests = false;
|
||||
this.spSignLogoutRequests = false;
|
||||
this.spSignLogoutResponses = false;
|
||||
this.spEncryptAssertions = false;
|
||||
}
|
||||
if (action === SSO_SIGNING) {
|
||||
this.spSignAuthRequests = false;
|
||||
this.spSignLogoutRequests = false;
|
||||
this.spSignLogoutResponses = false;
|
||||
}
|
||||
if (action === SSO_ENCRYPT) {
|
||||
this.spEncryptAssertions = false;
|
||||
}
|
||||
};
|
||||
|
||||
resetIdpCheckboxes = () => {
|
||||
this.idpVerifyAuthResponsesSign = false;
|
||||
this.idpVerifyLogoutRequestsSign = false;
|
||||
this.idpVerifyLogoutResponsesSign = false;
|
||||
};
|
||||
|
||||
delSpCertificate = (action) => {
|
||||
this.resetSpCheckboxes(action);
|
||||
this.spCertificates = this.spCertificates.filter(
|
||||
(certificate) => certificate.action !== action
|
||||
);
|
||||
};
|
||||
|
||||
delIdpCertificate = (cert) => {
|
||||
this.resetIdpCheckboxes();
|
||||
this.idpCertificates = this.idpCertificates.filter(
|
||||
(certificate) => certificate.crt !== cert
|
||||
);
|
||||
};
|
||||
|
||||
checkSpCertificateExist = () => {
|
||||
if (
|
||||
this.spAction === SSO_SIGNING_ENCRYPT &&
|
||||
this.spCertificates.length > 0 &&
|
||||
!this.isEdit
|
||||
)
|
||||
return true;
|
||||
|
||||
return this.spCertificates.find(
|
||||
(item) =>
|
||||
(item.action === this.spAction ||
|
||||
item.action === SSO_SIGNING_ENCRYPT) &&
|
||||
!this.isEdit
|
||||
);
|
||||
};
|
||||
|
||||
addSpCertificate = async (t) => {
|
||||
const data = [
|
||||
{
|
||||
@ -674,12 +725,7 @@ class SsoFormStore {
|
||||
},
|
||||
];
|
||||
|
||||
if (
|
||||
this.spCertificates.find(
|
||||
(item, index) =>
|
||||
item.action === this.spAction && this.editIndex !== index
|
||||
)
|
||||
) {
|
||||
if (this.checkSpCertificateExist()) {
|
||||
toastr.error(t("CertificateExist"));
|
||||
return;
|
||||
}
|
||||
@ -693,10 +739,16 @@ class SsoFormStore {
|
||||
return;
|
||||
}
|
||||
const newCertificates = res.data;
|
||||
newCertificates.map((cert) => {
|
||||
this.spCertificates = [...this.spCertificates, cert];
|
||||
this.checkedSpBoxes(cert);
|
||||
});
|
||||
if (this.isEdit) {
|
||||
this.spCertificates[this.editIndex] = newCertificates[0];
|
||||
this.checkedSpBoxes(newCertificates[0]);
|
||||
} else {
|
||||
newCertificates.map((cert) => {
|
||||
this.spCertificates = [...this.spCertificates, cert];
|
||||
this.checkedSpBoxes(cert);
|
||||
});
|
||||
}
|
||||
|
||||
this.isCertificateLoading = false;
|
||||
this.closeSpModal();
|
||||
} catch (err) {
|
||||
@ -707,14 +759,14 @@ class SsoFormStore {
|
||||
};
|
||||
|
||||
checkedSpBoxes = (cert) => {
|
||||
if (cert.action === "signing") {
|
||||
if (cert.action === SSO_SIGNING) {
|
||||
this.spSignAuthRequests = true;
|
||||
this.spSignLogoutRequests = true;
|
||||
}
|
||||
if (cert.action === "encrypt") {
|
||||
if (cert.action === SSO_ENCRYPT) {
|
||||
this.spEncryptAssertions = true;
|
||||
}
|
||||
if (cert.action === "signing and encrypt") {
|
||||
if (cert.action === SSO_SIGNING_ENCRYPT) {
|
||||
this.spSignAuthRequests = true;
|
||||
this.spSignLogoutRequests = true;
|
||||
this.spEncryptAssertions = true;
|
||||
@ -730,7 +782,11 @@ class SsoFormStore {
|
||||
},
|
||||
];
|
||||
|
||||
if (this.idpCertificates.find((item) => item.crt === this.idpCertificate)) {
|
||||
if (
|
||||
this.idpCertificates.find(
|
||||
(item) => item.crt === this.idpCertificate && !this.isEdit
|
||||
)
|
||||
) {
|
||||
toastr.error(t("CertificateExist"));
|
||||
return;
|
||||
}
|
||||
@ -744,10 +800,15 @@ class SsoFormStore {
|
||||
return;
|
||||
}
|
||||
const newCertificates = res.data;
|
||||
newCertificates.map((cert) => {
|
||||
this.idpCertificates = [...this.idpCertificates, cert];
|
||||
this.checkedIdpBoxes(cert);
|
||||
});
|
||||
if (this.isEdit) {
|
||||
this.idpCertificates[this.editIndex] = newCertificates[0];
|
||||
this.checkedIdpBoxes(newCertificates[0]);
|
||||
} else {
|
||||
newCertificates.map((cert) => {
|
||||
this.idpCertificates = [...this.idpCertificates, cert];
|
||||
this.checkedIdpBoxes(cert);
|
||||
});
|
||||
}
|
||||
this.isCertificateLoading = false;
|
||||
this.closeIdpModal();
|
||||
} catch (err) {
|
||||
@ -824,6 +885,27 @@ class SsoFormStore {
|
||||
const currentSettings = this.getSettings();
|
||||
return !isEqual(currentSettings, this.defaultSettings);
|
||||
}
|
||||
|
||||
get isDisabledIdpSigning() {
|
||||
if (!this.enableSso || this.isLoadingXml) return true;
|
||||
return this.idpCertificates.length === 0;
|
||||
}
|
||||
|
||||
get isDisabledSpSigning() {
|
||||
if (!this.enableSso || this.isLoadingXml) return true;
|
||||
return !this.spCertificates.some(
|
||||
(cert) =>
|
||||
cert.action === SSO_SIGNING || cert.action === SSO_SIGNING_ENCRYPT
|
||||
);
|
||||
}
|
||||
|
||||
get isDisabledSpEncrypt() {
|
||||
if (!this.enableSso || this.isLoadingXml) return true;
|
||||
return !this.spCertificates.some(
|
||||
(cert) =>
|
||||
cert.action === SSO_ENCRYPT || cert.action === SSO_SIGNING_ENCRYPT
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SsoFormStore;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import styled from "styled-components";
|
||||
import styled, { css } from "styled-components";
|
||||
import commonInputStyles from "./common-input-styles";
|
||||
import Input from "./input";
|
||||
import Base from "../themes/base";
|
||||
@ -24,15 +24,19 @@ const StyledTextInput = styled(Input).attrs((props) => ({
|
||||
${commonInputStyles}
|
||||
-webkit-appearance: ${(props) => props.theme.textInput.appearance};
|
||||
|
||||
background-color: ${(props) => props.theme.input.backgroundColor};
|
||||
-webkit-text-fill-color: ${(props) =>
|
||||
props?.value.length > 0
|
||||
? props.theme.text.color
|
||||
: props.theme.textInput.placeholderColor} !important;
|
||||
caret-color: ${(props) => props.theme.text.color};
|
||||
-webkit-background-clip: text !important;
|
||||
box-shadow: inset 0 0 20px 20px
|
||||
${(props) => props.theme.input.backgroundColor} !important;
|
||||
${(props) =>
|
||||
!props.isDisabled &&
|
||||
css`
|
||||
background-color: ${(props) => props.theme.input.backgroundColor};
|
||||
-webkit-text-fill-color: ${(props) =>
|
||||
props?.value.length > 0
|
||||
? props.theme.text.color
|
||||
: props.theme.textInput.placeholderColor} !important;
|
||||
caret-color: ${(props) => props.theme.text.color};
|
||||
-webkit-background-clip: text !important;
|
||||
box-shadow: inset 0 0 20px 20px
|
||||
${(props) => props.theme.input.backgroundColor} !important;
|
||||
`}
|
||||
|
||||
display: ${(props) => props.theme.textInput.display};
|
||||
font-family: ${(props) => props.theme.fontFamily};
|
||||
|
5
packages/login/index.d.ts
vendored
5
packages/login/index.d.ts
vendored
@ -108,6 +108,10 @@ declare global {
|
||||
message: string | undefined;
|
||||
}
|
||||
|
||||
interface ISSOSettings {
|
||||
hideAuthPage: boolean;
|
||||
}
|
||||
|
||||
interface IInitialState {
|
||||
portalSettings?: IPortalSettings;
|
||||
buildInfo?: IBuildInfo;
|
||||
@ -116,6 +120,7 @@ declare global {
|
||||
match?: MatchType;
|
||||
currentColorScheme?: ITheme;
|
||||
isAuth?: boolean;
|
||||
ssoSettings?: ISSOSettings;
|
||||
logoUrls: ILogoUrl[];
|
||||
error?: IError;
|
||||
}
|
||||
|
@ -59,6 +59,13 @@ app.get("*", async (req: ILoginRequest, res: Response, next) => {
|
||||
|
||||
try {
|
||||
initialState = await getInitialState(query);
|
||||
const hideAuthPage = initialState?.ssoSettings?.hideAuthPage;
|
||||
const ssoUrl = initialState?.capabilities?.ssoUrl;
|
||||
|
||||
if (hideAuthPage && ssoUrl && query.skipssoredirect !== "true") {
|
||||
res.redirect(ssoUrl);
|
||||
return next();
|
||||
}
|
||||
|
||||
if (initialState.isAuth && url !== "/login/error") {
|
||||
res.redirect("/");
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
getCapabilities,
|
||||
getAppearanceTheme,
|
||||
getLogoUrls,
|
||||
getCurrentSsoSettings
|
||||
} from "@docspace/common/api/settings";
|
||||
import { checkIsAuthenticated } from "@docspace/common/api/user";
|
||||
import { TenantStatus } from "@docspace/common/constants";
|
||||
@ -51,8 +52,9 @@ export const getInitialState = async (
|
||||
providers: ProvidersType,
|
||||
capabilities: ICapabilities,
|
||||
availableThemes: IThemes,
|
||||
isAuth: any,
|
||||
logoUrls: any;
|
||||
isAuth: boolean,
|
||||
logoUrls: ILogoUrl[],
|
||||
ssoSettings: ISSOSettings;
|
||||
|
||||
const baseSettings = [
|
||||
getSettings(),
|
||||
@ -65,6 +67,7 @@ export const getInitialState = async (
|
||||
getAuthProviders(),
|
||||
getCapabilities(),
|
||||
checkIsAuthenticated(),
|
||||
getCurrentSsoSettings(),
|
||||
];
|
||||
|
||||
[portalSettings, buildInfo, availableThemes, logoUrls] = await Promise.all(
|
||||
@ -72,7 +75,7 @@ export const getInitialState = async (
|
||||
);
|
||||
|
||||
if (portalSettings.tenantStatus !== TenantStatus.PortalRestore)
|
||||
[providers, capabilities, isAuth] = await Promise.all(settings);
|
||||
[providers, capabilities, isAuth, ssoSettings] = await Promise.all(settings);
|
||||
|
||||
const currentColorScheme = availableThemes.themes.find((theme) => {
|
||||
return availableThemes.selected === theme.id;
|
||||
@ -87,6 +90,7 @@ export const getInitialState = async (
|
||||
currentColorScheme,
|
||||
isAuth,
|
||||
logoUrls,
|
||||
ssoSettings
|
||||
};
|
||||
|
||||
return initialState;
|
||||
|
Loading…
Reference in New Issue
Block a user