Skip to content

Commit 8d6bb56

Browse files
feat(ui): Add Microsoft Entra SAML to self-serve SSO (#8695)
Co-authored-by: Alex Carpenter <alex.carpenter@clerk.dev>
1 parent afb75e6 commit 8d6bb56

14 files changed

Lines changed: 1335 additions & 247 deletions

File tree

.changeset/public-eggs-brush.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@clerk/localizations': patch
3+
'@clerk/shared': patch
4+
'@clerk/ui': patch
5+
---
6+
7+
Add support for Microsoft Entra SAML provider to self-serve SSO

packages/localizations/src/en-US.ts

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ export const enUS: LocalizationResource = {
243243
okta: 'Okta Workforce',
244244
customSaml: 'Custom SAML Provider',
245245
google: 'Google Workspace',
246+
microsoft: 'Microsoft Entra (formerly AD)',
246247
},
247248
warning: 'Once a provider is selected you cannot change again until the configuration is over',
248249
},
@@ -615,6 +616,127 @@ export const enUS: LocalizationResource = {
615616
},
616617
},
617618
},
619+
samlMicrosoft: {
620+
mainHeaderTitle: 'Configure Microsoft Entra',
621+
createAppStep: {
622+
headerSubtitle: 'Create a new enterprise application in your Azure portal',
623+
createAppInstructions: {
624+
title: 'Create a new enterprise application in Microsoft Entra',
625+
step1: 'Sign in to Microsoft Azure Portal and go to <bold>Enterprise applications.</bold>',
626+
step2:
627+
"Click <bold>New application.</bold> You'll be redirected to the <bold>Browse Microsoft Entra Gallery</bold> page.",
628+
step3: 'Select <bold>Create your own application.</bold>',
629+
step4: {
630+
label: 'In the modal that opens:',
631+
subSteps: {
632+
appName: 'Fill out your application name.',
633+
nonGallery:
634+
"Select <bold>Integrate any other application you don't find in the gallery (Non-gallery)</bold>.",
635+
create: 'Select <bold>Create</bold>.',
636+
},
637+
},
638+
},
639+
assignUsersInstructions: {
640+
title: 'Assign your users or groups in Microsoft',
641+
paragraph1: 'You need to assign users or groups before they can use it to log in.',
642+
step1: 'In the <bold>Getting Started</bold> section, select the <bold>Assign users and groups.</bold>',
643+
step2: "Select <bold>Add user/group.</bold> You'll be redirected to the <bold>Add Assignment page.</bold>",
644+
step3: 'Select the <bold>None Selected link.</bold>',
645+
step4:
646+
'To assign a user to the enterprise app, you can either use the search field to find a user or select the checkbox next to the user in the table.',
647+
step5:
648+
"Select <bold>Select</bold> at the bottom of the page. You'll be redirected to the <bold>Add Assignment</bold> page.",
649+
step6: 'Select <bold>Assign</bold> at the bottom of the page.',
650+
},
651+
},
652+
serviceProviderStep: {
653+
headerSubtitle: 'Add service provider configuration to Microsoft Entra',
654+
title: 'Configure service provider',
655+
step1: 'In the side navigation, open the <bold>Manage</bold> dropdown and select Single sign-on.',
656+
step2:
657+
"In the <bold>Select a single sign-on</bold> method section, select <bold>SAML</bold>. You'll be redirected to the <bold>Set up Single Sign-On with SAML</bold> page.",
658+
step3: 'Find the <bold>Basic SAML Configuration</bold> section.',
659+
step4: 'Select <bold>Edit</bold>. The <bold>Basic SAML Configuration</bold> panel will open.',
660+
step5:
661+
'Add the following <bold>Identifier (Entity ID)</bold> and <bold>Reply URL (Assertion Consumer Service URL)</bold> values. These values will be saved automatically.',
662+
step6: 'Select <bold>Save</bold> at the top of the panel. Close the panel.',
663+
serviceProviderFields: {
664+
acsUrl: {
665+
label: 'Reply URL (Assertion Consumer Service URL)',
666+
},
667+
spEntityId: {
668+
label: 'Identifier (Entity ID)',
669+
},
670+
},
671+
},
672+
identityProviderMetadataStep: {
673+
headerSubtitle: 'Configure identity provider metadata',
674+
modes: {
675+
title: 'Fill in your Microsoft Entra application details',
676+
ariaLabel: 'Configuration ',
677+
metadataUrl: 'Add via metadata',
678+
manual: 'Configure manually',
679+
},
680+
metadataUrl: {
681+
label: 'Metadata URL',
682+
placeholder: 'Paste URL here...',
683+
description:
684+
'On the <bold>SAML-based Sign-on</bold> page, find the <bold>SAML Certificates</bold> section. Add the <bold>App Federation Metadata Url</bold> below.',
685+
},
686+
manual: {
687+
description:
688+
'On the <bold>SAML-based Sign-on</bold> page, find the <bold>SAML Certificates</bold> section. Retrieve these values and add them below.',
689+
signOnUrl: {
690+
label: 'Single Sign-On URL',
691+
placeholder: 'Paste URL here...',
692+
},
693+
issuer: {
694+
label: 'Issuer',
695+
placeholder: 'Paste URL here...',
696+
},
697+
signingCertificate: {
698+
label: 'Signing certificate',
699+
uploadFile: 'Upload file',
700+
replaceFile: 'Replace file',
701+
removeFile: 'Remove file',
702+
fileUploaded: 'File uploaded',
703+
},
704+
},
705+
},
706+
attributeMappingStep: {
707+
headerSubtitle: 'Map user attributes from Microsoft Entra to your application',
708+
title: 'We expect your SAML responses to have the following specific attributes:',
709+
paragraph:
710+
"These are the defaults and probably won't need you to change them. However, many SAML configuration errors are due to incorrect attribute mappings, so it's worth double-checking. Here's how:",
711+
step1: 'On the <bold>SAML-based Sign-on</bold> page, find the <bold>Attributes & Claims</bold> section.',
712+
step2: 'Select <bold>Edit</bold>',
713+
step3: 'Verify that the above three attributes and values are present.',
714+
attributeMappingTable: {
715+
columns: {
716+
attribute: 'Attribute',
717+
claimName: 'Claim name',
718+
value: 'Value',
719+
},
720+
rows: {
721+
email: {
722+
attribute: 'Email address',
723+
claimName: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress',
724+
value: 'user.mail',
725+
},
726+
firstName: {
727+
attribute: 'First name',
728+
claimName: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname',
729+
value: 'user.givenname',
730+
},
731+
lastName: {
732+
attribute: 'Last name',
733+
claimName: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname',
734+
value: 'user.surname',
735+
},
736+
},
737+
},
738+
},
739+
},
618740
},
619741
},
620742
createOrganization: {

packages/shared/src/types/localization.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,7 @@ export type __internal_LocalizationResource = {
13091309
okta: LocalizationValue;
13101310
customSaml: LocalizationValue;
13111311
google: LocalizationValue;
1312+
microsoft: LocalizationValue;
13121313
};
13131314
warning: LocalizationValue;
13141315
};
@@ -1664,6 +1665,106 @@ export type __internal_LocalizationResource = {
16641665
};
16651666
};
16661667
};
1668+
samlMicrosoft: {
1669+
mainHeaderTitle: LocalizationValue;
1670+
createAppStep: {
1671+
headerSubtitle: LocalizationValue;
1672+
createAppInstructions: {
1673+
title: LocalizationValue;
1674+
step1: LocalizationValue;
1675+
step2: LocalizationValue;
1676+
step3: LocalizationValue;
1677+
step4: {
1678+
label: LocalizationValue;
1679+
subSteps: {
1680+
appName: LocalizationValue;
1681+
nonGallery: LocalizationValue;
1682+
create: LocalizationValue;
1683+
};
1684+
};
1685+
};
1686+
assignUsersInstructions: {
1687+
title: LocalizationValue;
1688+
paragraph1: LocalizationValue;
1689+
step1: LocalizationValue;
1690+
step2: LocalizationValue;
1691+
step3: LocalizationValue;
1692+
step4: LocalizationValue;
1693+
step5: LocalizationValue;
1694+
step6: LocalizationValue;
1695+
};
1696+
};
1697+
serviceProviderStep: {
1698+
headerSubtitle: LocalizationValue;
1699+
title: LocalizationValue;
1700+
step1: LocalizationValue;
1701+
step2: LocalizationValue;
1702+
step3: LocalizationValue;
1703+
step4: LocalizationValue;
1704+
step5: LocalizationValue;
1705+
step6: LocalizationValue;
1706+
serviceProviderFields: {
1707+
spEntityId: {
1708+
label: LocalizationValue;
1709+
};
1710+
acsUrl: {
1711+
label: LocalizationValue;
1712+
};
1713+
};
1714+
};
1715+
identityProviderMetadataStep: {
1716+
headerSubtitle: LocalizationValue;
1717+
modes: {
1718+
title: LocalizationValue;
1719+
ariaLabel: LocalizationValue;
1720+
metadataUrl: LocalizationValue;
1721+
manual: LocalizationValue;
1722+
};
1723+
metadataUrl: {
1724+
label: LocalizationValue;
1725+
placeholder: LocalizationValue;
1726+
description: LocalizationValue;
1727+
};
1728+
manual: {
1729+
description: LocalizationValue;
1730+
signOnUrl: {
1731+
label: LocalizationValue;
1732+
placeholder: LocalizationValue;
1733+
};
1734+
issuer: {
1735+
label: LocalizationValue;
1736+
placeholder: LocalizationValue;
1737+
};
1738+
signingCertificate: {
1739+
label: LocalizationValue;
1740+
uploadFile: LocalizationValue;
1741+
replaceFile: LocalizationValue;
1742+
removeFile: LocalizationValue;
1743+
fileUploaded: LocalizationValue;
1744+
};
1745+
};
1746+
};
1747+
attributeMappingStep: {
1748+
headerSubtitle: LocalizationValue;
1749+
title: LocalizationValue;
1750+
paragraph: LocalizationValue;
1751+
step1: LocalizationValue;
1752+
step2: LocalizationValue;
1753+
step3: LocalizationValue;
1754+
attributeMappingTable: {
1755+
columns: {
1756+
attribute: LocalizationValue;
1757+
claimName: LocalizationValue;
1758+
value: LocalizationValue;
1759+
};
1760+
rows: {
1761+
email: { attribute: LocalizationValue; claimName: LocalizationValue; value: LocalizationValue };
1762+
firstName: { attribute: LocalizationValue; claimName: LocalizationValue; value: LocalizationValue };
1763+
lastName: { attribute: LocalizationValue; claimName: LocalizationValue; value: LocalizationValue };
1764+
};
1765+
};
1766+
};
1767+
};
16671768
};
16681769
confirmation: {
16691770
statusSection: {

packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/index.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@ import { useConfigureSSO } from '../../ConfigureSSOContext';
66
import { Step } from '../../elements/Step';
77
import { Wizard } from '../../elements/Wizard';
88
import type { ProviderType } from '../../types';
9-
import { SamlCustomConfigureSteps, SamlGoogleConfigureSteps, SamlOktaConfigureSteps } from './saml';
9+
import {
10+
SamlCustomConfigureSteps,
11+
SamlGoogleConfigureSteps,
12+
SamlMicrosoftConfigureSteps,
13+
SamlOktaConfigureSteps,
14+
} from './saml';
1015

1116
const STEPS_BY_PROVIDER: Record<ProviderType, () => JSX.Element> = {
1217
saml_custom: SamlCustomConfigureSteps,
1318
saml_okta: SamlOktaConfigureSteps,
1419
saml_google: SamlGoogleConfigureSteps,
20+
saml_microsoft: SamlMicrosoftConfigureSteps,
1521
};
1622

1723
export const ConfigureStep = (): JSX.Element | null => {

0 commit comments

Comments
 (0)