diff --git a/services/web/app/src/Features/Subscription/GroupSSOHandler.js b/services/web/app/src/Features/Subscription/GroupSSOHandler.js
index 0b880119ab..bb6335a604 100644
--- a/services/web/app/src/Features/Subscription/GroupSSOHandler.js
+++ b/services/web/app/src/Features/Subscription/GroupSSOHandler.js
@@ -5,17 +5,17 @@ const SAMLIdentityManager = require('../User/SAMLIdentityManager')
const { User } = require('../../models/User')
const Errors = require('../Errors/Errors')
-async function canEnrollInSubscription(userId, subscription) {
- const ssoEnabled = await isSSOEnabled(subscription)
- if (!ssoEnabled) {
- return false
+async function checkUserCanEnrollInSubscription(userId, subscription) {
+ const ssoConfig = await SSOConfig.findById(subscription?.ssoConfig).exec()
+ if (!ssoConfig?.enabled) {
+ throw new Errors.SAMLGroupSSODisabledError()
}
const userIsMember = subscription.member_ids.some(
memberId => memberId.toString() === userId.toString()
)
if (!userIsMember) {
- return false
+ throw new Errors.SAMLGroupSSOLoginIdentityNotFoundError()
}
const user = await User.findOne(
@@ -27,9 +27,8 @@ async function canEnrollInSubscription(userId, subscription) {
enrollment => enrollment.groupId.toString() === subscription._id.toString()
)
if (userIsEnrolled) {
- return false
+ throw new Errors.SAMLIdentityExistsError()
}
- return true
}
async function enrollInSubscription(
@@ -39,15 +38,8 @@ async function enrollInSubscription(
userIdAttribute,
auditLog
) {
- const canEnroll = await canEnrollInSubscription(userId, subscription)
- if (!canEnroll) {
- throw new Errors.SubscriptionNotFoundError(
- 'cannot enroll user in SSO subscription',
- {
- info: { userId, subscription },
- }
- )
- }
+ await checkUserCanEnrollInSubscription(userId, subscription)
+
const providerId = `ol-group-subscription-id:${subscription._id.toString()}`
const userBySamlIdentifier = await SAMLIdentityManager.getUser(
@@ -86,15 +78,9 @@ async function enrollInSubscription(
)
}
-async function isSSOEnabled(subscription) {
- const ssoConfig = await SSOConfig.findById(subscription.ssoConfig).exec()
- return ssoConfig?.enabled
-}
-
module.exports = {
promises: {
- canEnrollInSubscription,
+ checkUserCanEnrollInSubscription,
enrollInSubscription,
- isSSOEnabled,
},
}
diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json
index 948258b0f1..42ecfcfaac 100644
--- a/services/web/frontend/extracted-translations.json
+++ b/services/web/frontend/extracted-translations.json
@@ -990,6 +990,12 @@
"revoke_invite": "",
"right": "",
"role": "",
+ "saml_auth_error": "",
+ "saml_invalid_signature_error": "",
+ "saml_login_disabled_error": "",
+ "saml_login_failure": "",
+ "saml_login_identity_mismatch_error": "",
+ "saml_login_identity_not_found_error": "",
"save": "",
"save_or_cancel-cancel": "",
"save_or_cancel-or": "",
@@ -1116,8 +1122,11 @@
"sso_is_enabled": "",
"sso_is_enabled_explanation_1": "",
"sso_is_enabled_explanation_2": "",
+ "sso_link_currently_signed_in": "",
"sso_link_error": "",
"sso_link_invite_has_been_sent_to_email": "",
+ "sso_link_now_or_later": "",
+ "sso_link_your_group_uses_sso": "",
"sso_logs": "",
"sso_not_active": "",
"start_a_free_trial": "",
diff --git a/services/web/frontend/stories/subscription/sso/sso-link-interstitial.stories.tsx b/services/web/frontend/stories/subscription/sso/sso-link-interstitial.stories.tsx
new file mode 100644
index 0000000000..3c86a6ea2a
--- /dev/null
+++ b/services/web/frontend/stories/subscription/sso/sso-link-interstitial.stories.tsx
@@ -0,0 +1,27 @@
+import { useMeta } from '../../hooks/use-meta'
+import SSOLinkConfirm from '../../../../modules/managed-users/frontend/js/components/sso-link-confirm'
+
+export const LinkConfirmInterstitial = () => {
+ return