diff --git a/.changeset/add-linkedin-microsoft-idp.md b/.changeset/add-linkedin-microsoft-idp.md
new file mode 100644
index 00000000..fbc66847
--- /dev/null
+++ b/.changeset/add-linkedin-microsoft-idp.md
@@ -0,0 +1,10 @@
+---
+'@forgerock/login-widget': minor
+---
+
+Add LinkedIn and Microsoft Entra ID as OOTB identity providers in the SelectIdP callback.
+
+- LinkedIn: matches `buttonDisplayName` containing `'LinkedIn'`, renders branded button with `#0077b5` background and the LinkedIn "in" logo.
+- Microsoft/Entra ID: matches `buttonDisplayName` containing `'Microsoft'`, renders branded button with `#0072c6` background and the 4-color Microsoft squares logo.
+- Dark mode variants for both providers follow the existing pattern (white background, brand-color text).
+- Unknown providers continue to render nothing — no change to existing fallback behavior.
diff --git a/core/components/icons/linkedin-icon.svelte b/core/components/icons/linkedin-icon.svelte
new file mode 100644
index 00000000..f0a4e6f9
--- /dev/null
+++ b/core/components/icons/linkedin-icon.svelte
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/core/components/icons/microsoft-icon.svelte b/core/components/icons/microsoft-icon.svelte
new file mode 100644
index 00000000..dac5cd0f
--- /dev/null
+++ b/core/components/icons/microsoft-icon.svelte
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/core/journey/callbacks/select-idp/select-idp.mock.ts b/core/journey/callbacks/select-idp/select-idp.mock.ts
index 3c68a9da..7556cc9f 100644
--- a/core/journey/callbacks/select-idp/select-idp.mock.ts
+++ b/core/journey/callbacks/select-idp/select-idp.mock.ts
@@ -1,6 +1,6 @@
/**
*
- * Copyright © 2025 Ping Identity Corporation. All right reserved.
+ * Copyright © 2025-2026 Ping Identity Corporation. All right reserved.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
@@ -60,6 +60,36 @@ export const multipleProvidersLocalAuthFormStep = {
iconBackground: '#4184f3',
},
},
+ {
+ provider: 'linkedin-web',
+ uiConfig: {
+ buttonCustomStyle:
+ 'background-color: #0077b5; color: white; border-color: #0077b5;',
+ buttonImage: '',
+ buttonClass: '',
+ buttonCustomStyleHover:
+ 'background-color: #006097; color: white; border-color: #006097;',
+ buttonDisplayName: 'LinkedIn',
+ iconClass: '',
+ iconFontColor: 'white',
+ iconBackground: '#0077b5',
+ },
+ },
+ {
+ provider: 'microsoft-web',
+ uiConfig: {
+ buttonCustomStyle:
+ 'background-color: #0072c6; color: white; border-color: #0072c6;',
+ buttonImage: '',
+ buttonClass: '',
+ buttonCustomStyleHover:
+ 'background-color: #005a9e; color: white; border-color: #005a9e;',
+ buttonDisplayName: 'Microsoft',
+ iconClass: '',
+ iconFontColor: 'white',
+ iconBackground: '#0072c6',
+ },
+ },
{ provider: 'localAuthentication' },
],
},
@@ -136,6 +166,36 @@ export const multipleProvidersLocalAuthNoFormStep = {
iconBackground: '#4184f3',
},
},
+ {
+ provider: 'linkedin-web',
+ uiConfig: {
+ buttonCustomStyle:
+ 'background-color: #0077b5; color: white; border-color: #0077b5;',
+ buttonImage: '',
+ buttonClass: '',
+ buttonCustomStyleHover:
+ 'background-color: #006097; color: white; border-color: #006097;',
+ buttonDisplayName: 'LinkedIn',
+ iconClass: '',
+ iconFontColor: 'white',
+ iconBackground: '#0077b5',
+ },
+ },
+ {
+ provider: 'microsoft-web',
+ uiConfig: {
+ buttonCustomStyle:
+ 'background-color: #0072c6; color: white; border-color: #0072c6;',
+ buttonImage: '',
+ buttonClass: '',
+ buttonCustomStyleHover:
+ 'background-color: #005a9e; color: white; border-color: #005a9e;',
+ buttonDisplayName: 'Microsoft',
+ iconClass: '',
+ iconFontColor: 'white',
+ iconBackground: '#0072c6',
+ },
+ },
{ provider: 'localAuthentication' },
],
},
@@ -200,6 +260,36 @@ export const multipleProvidersNoLocalAuthStep = {
iconBackground: '#4184f3',
},
},
+ {
+ provider: 'linkedin-web',
+ uiConfig: {
+ buttonCustomStyle:
+ 'background-color: #0077b5; color: white; border-color: #0077b5;',
+ buttonImage: '',
+ buttonClass: '',
+ buttonCustomStyleHover:
+ 'background-color: #006097; color: white; border-color: #006097;',
+ buttonDisplayName: 'LinkedIn',
+ iconClass: '',
+ iconFontColor: 'white',
+ iconBackground: '#0077b5',
+ },
+ },
+ {
+ provider: 'microsoft-web',
+ uiConfig: {
+ buttonCustomStyle:
+ 'background-color: #0072c6; color: white; border-color: #0072c6;',
+ buttonImage: '',
+ buttonClass: '',
+ buttonCustomStyleHover:
+ 'background-color: #005a9e; color: white; border-color: #005a9e;',
+ buttonDisplayName: 'Microsoft',
+ iconClass: '',
+ iconFontColor: 'white',
+ iconBackground: '#0072c6',
+ },
+ },
],
},
{ name: 'value', value: '' },
@@ -327,6 +417,74 @@ export const singleProviderNoLocalAuthStep = {
],
};
+export const singleLinkedInProviderStep = {
+ authId:
+ 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdXRoSW5kZXhWYWx1ZSI6IlNvY2lhbExvZ2luLXdlYiIsIm90ayI6ImFpMzZ2NHZwZ243c2JnZGo1YTN2aHZiM3V0IiwiYXV0aEluZGV4VHlwZSI6InNlcnZpY2UiLCJyZWFsbSI6Ii9hbHBoYSIsInNlc3Npb25JZCI6IipBQUpUU1FBQ01ESUFCSFI1Y0dVQUNFcFhWRjlCVlZSSUFBSlRNUUFDTURFLipleUowZVhBaU9pSktWMVFpTENKamRIa2lPaUpLVjFRaUxDSmhiR2NpT2lKSVV6STFOaUo5LlpYbEtNR1ZZUVdsUGFVcExWakZSYVV4RFNteGliVTFwVDJsS1FrMVVTVFJSTUVwRVRGVm9WRTFxVlRKSmFYZHBXVmQ0YmtscWIybGFSMng1U1c0d0xpNW5hRmRCWlVweVRtOTNYekZFY1RJNU4wUkhka2gzTGxJemVsWlJiblJWVkZFMVozWmFjVVZJTkdVMWJUTlFiRUZOVjNwU1RWZzNTV0ZVYld4c1RqRlpjakZQY0U5T1EySlViVEEyTFRsVlQwbDBNbEpQY0RsV2NXWlNUM2xtYWtSWldGWnhTV0l4UVZGdlpreFFRamhPVG10ak1Xb3pMVXBhUVVkNFlrRlRXRTR5U1daaVdFSlVOVlp3Y2xCMWVHMDNOMGcwV2tKSlNYcHRVek5mWVU1clJtRkNSbkJEYzNOUWNteERWM1F3YWxVNVMxTlFRVUpFUkhkRVRFbFRiMnBET1hCQ1NGbzVTRUZxTWxsUlRVUmFialk1VWpORE0xYzBNekZCYTB4d1ZWTmpSSFZEUkdacFEzVm5hVTlDYzJaemR6Tk1OWGt3TVhoZk5rUkVTMnBwT0ZWSGRIVkZWa3B4VGxGcVVUaExWMEZGZFZWSFNVbEthVkZIWjFOa2F6bHRXR1F3ZFhJeU5GcFFNV2hZVkROWVIxWnlaMmc0U2pGU2RUVlZaWFk0WjBobk5FTTNjR2R2ZEVoUFIyVnBWMk5QUTBoSlpXSndTalJWWm5odU1XVnVkVEpaVjFaSFVWTTFiMFo1WVRGalZWSlBPVTA0TUdadVZFTTJZVGh2YkV4c09XVkhZbFE1TkUxVFJYZG5NVk5QTFc1MGJsaHliR1J6TWxvMmVXMXlhR2hxTlc4MGRucEhTV1JvWDIxMU5rVkROMUpMWTFReFlXZGtkRXRUWDBZdFFXaHBZMVpCUWtGc1JrdDZTWGxSTFRRdExUSmpRMDFXWVRoRFRVbHlVV0U1YXpjMlRrWk9Sak5IY2twaGJIZFpiVzlrUnpGc0xWRnRRVmQyZVZrelRVSnJRa1l4UmxKMmFuaDZMVkZHZUd4d1J6SlJOR1p6VkZSVkxYVjFhakl5VWpneWJqQkhhVnBVZDFkbVZVbE9WV2x0VUdWSWVrSnBZbEU1TjJ4dlYwaHZkMUoxVEV3NE5rUjZOVTFVZDB0eFNUQTJNak42V0UweVJuVkJTRUp0V1ROc1NHdHhkWEptWnpOTmRrUjRZVE5mVTNFMmRXZEdPWG8wU2xCVVp6UTRWWE5rUWtwdVduZEdlRlF4TXpoTFdGbFphMUV5Y0dvdU4wWkhRa2QwZG5STE1FRlVibWxHY1ZacVIwTlJady5xa1NtUTM1X253X0lCUU11RlRueW5NMTN1NmFoTGR2bkVYRVhSaTNFSFBjIiwiZXhwIjoxNjY5OTc3OTg1LCJpYXQiOjE2Njk5Nzc2ODV9.iV-WX2dk_8oTug-zlou7SvL29CwfaCSlzR5N0huRsxc',
+ callbacks: [
+ {
+ type: 'SelectIdPCallback',
+ output: [
+ {
+ name: 'providers',
+ value: [
+ {
+ provider: 'linkedin-web',
+ uiConfig: {
+ buttonCustomStyle:
+ 'background-color: #0077b5; color: white; border-color: #0077b5;',
+ buttonImage: '',
+ buttonClass: '',
+ buttonCustomStyleHover:
+ 'background-color: #006097; color: white; border-color: #006097;',
+ buttonDisplayName: 'LinkedIn',
+ iconClass: '',
+ iconFontColor: 'white',
+ iconBackground: '#0077b5',
+ },
+ },
+ ],
+ },
+ { name: 'value', value: '' },
+ ],
+ input: [{ name: 'IDToken1', value: '' }],
+ },
+ ],
+};
+
+export const singleMicrosoftProviderStep = {
+ authId:
+ 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdXRoSW5kZXhWYWx1ZSI6IlNvY2lhbExvZ2luLXdlYiIsIm90ayI6ImFpMzZ2NHZwZ243c2JnZGo1YTN2aHZiM3V0IiwiYXV0aEluZGV4VHlwZSI6InNlcnZpY2UiLCJyZWFsbSI6Ii9hbHBoYSIsInNlc3Npb25JZCI6IipBQUpUU1FBQ01ESUFCSFI1Y0dVQUNFcFhWRjlCVlZSSUFBSlRNUUFDTURFLipleUowZVhBaU9pSktWMVFpTENKamRIa2lPaUpLVjFRaUxDSmhiR2NpT2lKSVV6STFOaUo5LlpYbEtNR1ZZUVdsUGFVcExWakZSYVV4RFNteGliVTFwVDJsS1FrMVVTVFJSTUVwRVRGVm9WRTFxVlRKSmFYZHBXVmQ0YmtscWIybGFSMng1U1c0d0xpNW5hRmRCWlVweVRtOTNYekZFY1RJNU4wUkhka2gzTGxJemVsWlJiblJWVkZFMVozWmFjVVZJTkdVMWJUTlFiRUZOVjNwU1RWZzNTV0ZVYld4c1RqRlpjakZQY0U5T1EySlViVEEyTFRsVlQwbDBNbEpQY0RsV2NXWlNUM2xtYWtSWldGWnhTV0l4UVZGdlpreFFRamhPVG10ak1Xb3pMVXBhUVVkNFlrRlRXRTR5U1daaVdFSlVOVlp3Y2xCMWVHMDNOMGcwV2tKSlNYcHRVek5mWVU1clJtRkNSbkJEYzNOUWNteERWM1F3YWxVNVMxTlFRVUpFUkhkRVRFbFRiMnBET1hCQ1NGbzVTRUZxTWxsUlRVUmFialk1VWpORE0xYzBNekZCYTB4d1ZWTmpSSFZEUkdacFEzVm5hVTlDYzJaemR6Tk1OWGt3TVhoZk5rUkVTMnBwT0ZWSGRIVkZWa3B4VGxGcVVUaExWMEZGZFZWSFNVbEthVkZIWjFOa2F6bHRXR1F3ZFhJeU5GcFFNV2hZVkROWVIxWnlaMmc0U2pGU2RUVlZaWFk0WjBobk5FTTNjR2R2ZEVoUFIyVnBWMk5QUTBoSlpXSndTalJWWm5odU1XVnVkVEpaVjFaSFVWTTFiMFo1WVRGalZWSlBPVTA0TUdadVZFTTJZVGh2YkV4c09XVkhZbFE1TkUxVFJYZG5NVk5QTFc1MGJsaHliR1J6TWxvMmVXMXlhR2hxTlc4MGRucEhTV1JvWDIxMU5rVkROMUpMWTFReFlXZGtkRXRUWDBZdFFXaHBZMVpCUWtGc1JrdDZTWGxSTFRRdExUSmpRMDFXWVRoRFRVbHlVV0U1YXpjMlRrWk9Sak5IY2twaGJIZFpiVzlrUnpGc0xWRnRRVmQyZVZrelRVSnJRa1l4UmxKMmFuaDZMVkZHZUd4d1J6SlJOR1p6VkZSVkxYVjFhakl5VWpneWJqQkhhVnBVZDFkbVZVbE9WV2x0VUdWSWVrSnBZbEU1TjJ4dlYwaHZkMUoxVEV3NE5rUjZOVTFVZDB0eFNUQTJNak42V0UweVJuVkJTRUp0V1ROc1NHdHhkWEptWnpOTmRrUjRZVE5mVTNFMmRXZEdPWG8wU2xCVVp6UTRWWE5rUWtwdVduZEdlRlF4TXpoTFdGbFphMUV5Y0dvdU4wWkhRa2QwZG5STE1FRlVibWxHY1ZacVIwTlJady5xa1NtUTM1X253X0lCUU11RlRueW5NMTN1NmFoTGR2bkVYRVhSaTNFSFBjIiwiZXhwIjoxNjY5OTc3OTg1LCJpYXQiOjE2Njk5Nzc2ODV9.iV-WX2dk_8oTug-zlou7SvL29CwfaCSlzR5N0huRsxc',
+ callbacks: [
+ {
+ type: 'SelectIdPCallback',
+ output: [
+ {
+ name: 'providers',
+ value: [
+ {
+ provider: 'microsoft-web',
+ uiConfig: {
+ buttonCustomStyle:
+ 'background-color: #0072c6; color: white; border-color: #0072c6;',
+ buttonImage: '',
+ buttonClass: '',
+ buttonCustomStyleHover:
+ 'background-color: #005a9e; color: white; border-color: #005a9e;',
+ buttonDisplayName: 'Microsoft',
+ iconClass: '',
+ iconFontColor: 'white',
+ iconBackground: '#0072c6',
+ },
+ },
+ ],
+ },
+ { name: 'value', value: '' },
+ ],
+ input: [{ name: 'IDToken1', value: '' }],
+ },
+ ],
+};
+
export const docsExample = {
type: 'SelectIdPCallback',
output: [
diff --git a/core/journey/callbacks/select-idp/select-idp.stories.js b/core/journey/callbacks/select-idp/select-idp.stories.js
index 7587a6fc..388bddba 100644
--- a/core/journey/callbacks/select-idp/select-idp.stories.js
+++ b/core/journey/callbacks/select-idp/select-idp.stories.js
@@ -10,10 +10,16 @@
import { callbackType } from '@forgerock/journey-client';
import { createJourneyStep } from '$journey/_utilities/step.mock';
-import { singleProviderNoLocalAuthStep } from './select-idp.mock';
+import {
+ singleLinkedInProviderStep,
+ singleMicrosoftProviderStep,
+ singleProviderNoLocalAuthStep,
+} from './select-idp.mock';
import Input from './select-idp.story.svelte';
const singleProviderNoLocalAuth = createJourneyStep(singleProviderNoLocalAuthStep);
+const singleLinkedInProvider = createJourneyStep(singleLinkedInProviderStep);
+const singleMicrosoftProvider = createJourneyStep(singleMicrosoftProviderStep);
export default {
argTypes: {
@@ -32,3 +38,17 @@ export const Base = {
localAuth: true,
},
};
+
+export const LinkedIn = {
+ args: {
+ socialCallback: singleLinkedInProvider.getCallbackOfType(callbackType.SelectIdPCallback),
+ localAuth: false,
+ },
+};
+
+export const Microsoft = {
+ args: {
+ socialCallback: singleMicrosoftProvider.getCallbackOfType(callbackType.SelectIdPCallback),
+ localAuth: false,
+ },
+};
diff --git a/core/journey/callbacks/select-idp/select-idp.svelte b/core/journey/callbacks/select-idp/select-idp.svelte
index d0cf56c0..db0783bc 100644
--- a/core/journey/callbacks/select-idp/select-idp.svelte
+++ b/core/journey/callbacks/select-idp/select-idp.svelte
@@ -14,6 +14,8 @@
import AppleIcon from '../../../components/icons/apple-icon.svelte';
import FacebookIcon from '../../../components/icons/facebook-icon.svelte';
import GoogleIcon from '../../../components/icons/google-icon.svelte';
+ import LinkedinIcon from '../../../components/icons/linkedin-icon.svelte';
+ import MicrosoftIcon from '../../../components/icons/microsoft-icon.svelte';
import type { SelectIdPCallback } from '@forgerock/journey-client/types';
import type { z } from 'zod';
@@ -107,6 +109,28 @@
{idp.text}
+ {:else if idp.text.toUpperCase().includes('LINKEDIN')}
+
+ {:else if idp.text.toUpperCase().includes('MICROSOFT')}
+
{/if}
{/each}
diff --git a/themes/default/journey.cjs b/themes/default/journey.cjs
index eabd297a..0e0e1297 100644
--- a/themes/default/journey.cjs
+++ b/themes/default/journey.cjs
@@ -71,6 +71,44 @@ module.exports = function (theme) {
opacity: `0.1`,
},
},
+ '.button-linkedin': {
+ '--border-color':
+ 'hsl(var(--tw-colors-secondary-light-hs),var(--tw-colors-secondary-light-l))',
+ borderColor: `var(--border-color, ${theme('colors.secondary.light')})`,
+ backgroundColor: '#0077b5',
+ color: theme('colors.white'),
+ '&:hover::before, &:focus::before': {
+ opacity: `0.1`,
+ },
+ },
+ '.button-linkedin_dark': {
+ '--border-color':
+ 'hsl(var(--tw-colors-secondary-light-hs),var(--tw-colors-secondary-light-l))',
+ borderColor: `var(--border-color, ${theme('colors.secondary.light')})`,
+ backgroundColor: theme('colors.white'),
+ color: '#0077b5',
+ '&:hover::before, &:focus::before': {
+ opacity: `0.1`,
+ },
+ },
+ '.button-microsoft': {
+ '--border-color': '#8C8C8C',
+ borderColor: `var(--border-color, #8C8C8C)`,
+ backgroundColor: theme('colors.white'),
+ color: theme('colors.black'),
+ '&:hover::before, &:focus::before': {
+ opacity: `0.1`,
+ },
+ },
+ '.button-microsoft_dark': {
+ '--border-color': '#8C8C8C',
+ borderColor: `var(--border-color, #8C8C8C)`,
+ backgroundColor: theme('colors.white'),
+ color: theme('colors.black'),
+ '&:hover::before, &:focus::before': {
+ opacity: `0.1`,
+ },
+ },
'.input-policies': {
'--font-size': 'var(--tw-font-size-sm-type)',
fontSize: `var(--font-size, ${theme('fontSize.sm')})`,