@@ -11,6 +11,7 @@ import { useConfigureSSO } from '../../../ConfigureSSOContext';
1111import { Step } from '../../../elements/Step' ;
1212import { useWizard , Wizard } from '../../../elements/Wizard' ;
1313import { InnerStepCounter } from '../../../elements/Wizard/InnerStepCounter' ;
14+ import { AttributeMappingTable , type AttributeMappingTableConfig } from './shared/AttributeMappingTable' ;
1415import {
1516 applySamlSubmitError ,
1617 buildSamlConfigurationPayload ,
@@ -45,6 +46,16 @@ export const SamlMicrosoftConfigureSteps = (): JSX.Element => {
4546 < SamlMicrosoftServiceProviderStep />
4647 </ Wizard . Step >
4748
49+ < Wizard . Step id = 'attribute-mapping' >
50+ < Step . Header
51+ title = { localizationKeys ( 'configureSSO.configureStep.samlMicrosoft.mainHeaderTitle' ) }
52+ description = { localizationKeys ( 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.headerSubtitle' ) }
53+ >
54+ < InnerStepCounter />
55+ </ Step . Header >
56+ < SamlMicrosoftAttributeMappingStep />
57+ </ Wizard . Step >
58+
4859 < Wizard . Step id = 'identity-provider-metadata' >
4960 < Step . Header
5061 title = { localizationKeys ( 'configureSSO.configureStep.samlMicrosoft.mainHeaderTitle' ) }
@@ -394,6 +405,134 @@ const SamlMicrosoftServiceProviderStep = (): JSX.Element => {
394405 ) ;
395406} ;
396407
408+ const MICROSOFT_ATTRIBUTE_MAPPING : AttributeMappingTableConfig = {
409+ columns : {
410+ first : localizationKeys (
411+ 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.attributeMappingTable.columns.attribute' ,
412+ ) ,
413+ second : localizationKeys (
414+ 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.attributeMappingTable.columns.claimName' ,
415+ ) ,
416+ third : localizationKeys (
417+ 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.attributeMappingTable.columns.value' ,
418+ ) ,
419+ } ,
420+ // Microsoft's default claim names are long URLs that don't fit the column;
421+ // truncate them with an ellipsis and surface the full value in a tooltip.
422+ truncateSecond : true ,
423+ rows : [
424+ {
425+ id : 'email' ,
426+ isRequired : true ,
427+ first : localizationKeys (
428+ 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.attributeMappingTable.rows.email.attribute' ,
429+ ) ,
430+ second : localizationKeys (
431+ 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.attributeMappingTable.rows.email.claimName' ,
432+ ) ,
433+ third : localizationKeys (
434+ 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.attributeMappingTable.rows.email.value' ,
435+ ) ,
436+ } ,
437+ {
438+ id : 'firstName' ,
439+ isRequired : false ,
440+ first : localizationKeys (
441+ 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.attributeMappingTable.rows.firstName.attribute' ,
442+ ) ,
443+ second : localizationKeys (
444+ 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.attributeMappingTable.rows.firstName.claimName' ,
445+ ) ,
446+ third : localizationKeys (
447+ 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.attributeMappingTable.rows.firstName.value' ,
448+ ) ,
449+ } ,
450+ {
451+ id : 'lastName' ,
452+ isRequired : false ,
453+ first : localizationKeys (
454+ 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.attributeMappingTable.rows.lastName.attribute' ,
455+ ) ,
456+ second : localizationKeys (
457+ 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.attributeMappingTable.rows.lastName.claimName' ,
458+ ) ,
459+ third : localizationKeys (
460+ 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.attributeMappingTable.rows.lastName.value' ,
461+ ) ,
462+ } ,
463+ ] ,
464+ } ;
465+
466+ const SamlMicrosoftAttributeMappingStep = ( ) : JSX . Element => {
467+ const { goNext, goPrev, isFirstStep, isLastStep } = useWizard ( ) ;
468+
469+ return (
470+ < >
471+ < Step . Body >
472+ < Step . Section sx = { theme => ( { gap : theme . space . $3 } ) } >
473+ < Heading
474+ elementDescriptor = { descriptors . configureSSOInstructionsHeading }
475+ as = 'h3'
476+ textVariant = 'subtitle'
477+ localizationKey = { localizationKeys ( 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.title' ) }
478+ />
479+
480+ < AttributeMappingTable config = { MICROSOFT_ATTRIBUTE_MAPPING } />
481+
482+ < Text
483+ as = 'p'
484+ colorScheme = 'secondary'
485+ localizationKey = { localizationKeys (
486+ 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.paragraph' ,
487+ ) }
488+ />
489+
490+ < Col
491+ elementDescriptor = { descriptors . configureSSOInstructionsList }
492+ as = 'ul'
493+ sx = { theme => ( {
494+ gap : theme . space . $1x5 ,
495+ margin : 0 ,
496+ paddingInlineStart : theme . space . $5 ,
497+ listStyleType : 'disc' ,
498+ } ) }
499+ >
500+ < Text
501+ elementDescriptor = { descriptors . configureSSOInstructionsListItem }
502+ as = 'li'
503+ colorScheme = 'secondary'
504+ localizationKey = { localizationKeys ( 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.step1' ) }
505+ />
506+ < Text
507+ elementDescriptor = { descriptors . configureSSOInstructionsListItem }
508+ as = 'li'
509+ colorScheme = 'secondary'
510+ localizationKey = { localizationKeys ( 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.step2' ) }
511+ />
512+ < Text
513+ elementDescriptor = { descriptors . configureSSOInstructionsListItem }
514+ as = 'li'
515+ colorScheme = 'secondary'
516+ localizationKey = { localizationKeys ( 'configureSSO.configureStep.samlMicrosoft.attributeMappingStep.step3' ) }
517+ />
518+ </ Col >
519+ </ Step . Section >
520+ </ Step . Body >
521+
522+ < Step . Footer >
523+ < Step . Footer . Previous
524+ onClick = { ( ) => goPrev ( ) }
525+ isDisabled = { isFirstStep }
526+ />
527+ < Step . Footer . Continue
528+ onClick = { ( ) => goNext ( ) }
529+ isDisabled = { isLastStep }
530+ />
531+ </ Step . Footer >
532+ </ >
533+ ) ;
534+ } ;
535+
397536const MICROSOFT_SAML_IDP_MODES = [ 'metadataUrl' , 'manual' ] as const satisfies readonly IdpConfigurationMode [ ] ;
398537
399538const SamlMicrosoftIdentityProviderMetadataStep = ( ) : JSX . Element => {
0 commit comments