Federated Credential Management (FedCM) API — a brief primer

data security concept, mobile application access, login and pass
Federated Credential Management (FedCM) is a browser-mediated sign-in API that enables “Sign in with…” flows without relying on third-party cookies. It standardizes the login experience, reduces cross-site tracking signals, and helps identity providers and relying parties deliver more reliable, privacy-preserving authentication.

The Federated Credential Management (FedCM) API is a web platform feature designed to modernize how users sign in with an identity provider (IdP) (for example, “Sign in with …”) while improving privacy, security, and user experience compared to older federated-login patterns.

Why it exists

Traditional “Sign in with …” flows often rely on third-party cookies, hidden iframes, and cross-site redirects. As browsers increasingly restrict third-party cookies and cross-site tracking techniques, those legacy approaches become brittle and privacy-sensitive.

FedCM provides a browser-mediated way for a site (the relying party, or RP) to request a federated sign-in from an IdP, with the browser presenting a standardized UI and controlling how identity information is shared.

What it changes

With FedCM:

				
					<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>FedCM API Demo</title>
    <link href="style.css" rel="stylesheet" />
    <script type="wphb-delay-type" src="federatedCredentialManagement_API.js" defer></script>
</head>
    
<body>
    <div class="container">
        <h1>FedCM API Demo (Relying Party)</h1>
        <p>
            This demo simulates a website (Relying Party - RP) initiating a federated sign-in flow
            using the FedCM API. It will attempt to communicate with a hypothetical Identity Provider (IdP).
        </p>
        <p class="warning">
            <strong>Important:</strong> FedCM is an experimental technology. You need a browser that supports it
            (e.g., Chrome, Edge with flags enabled, or Firefox Nightly).
            The `configURL` and `clientId` below are placeholders; a real IdP would provide these.
        </p>
    
        <button id="signInButton">Sign in with FedCM</button>
    
        <div id="status" class="info">
            Click the "Sign in with FedCM" button to begin.
        </div>
    
        <h2>Result:</h2>
        <pre id="result"></pre>
    </div>

</body>

</html>
				
			
				
					body {
    font-family: sans-serif;
    margin: 2em;
    background-color: #f4f4f4;
    color: #333;
}

.container {
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

h1 {
    color: #2c3e50;
    text-align: center;
}
button {
    display: block;
    margin: 20px auto;
    padding: 10px 20px;
    font-size: 1em;
    background-color: #3498db;
    color: white;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.3s ease;
}

button:hover {
    background-color: #2980b9;
}

#status,
#result {
    margin-top: 20px;
    padding: 15px;
    border-radius: 5px;
    background-color: #ecf0f1;
    border: 1px solid #bdc3c7;
    white-space: pre-wrap;
    /* Preserve whitespace and line breaks */
    word-break: break-all;
    /* Break long words */
}
.success {
    background-color: #d4edda;
    border-color: #28a745;
    color: #155724;
}

.error {
    background-color: #f8d7da;
    border-color: #dc3545;
    color: #721c24;
}

.info {
    background-color: #e2e3e5;
    border-color: #6c757d;
    color: #383d41;
}

.warning {
    background-color: #fff3cd;
    border-color: #ffc107;
    color: #856404;
}
				
			
				
					const signInButton = document.querySelector('#signInButton');
const statusDiv = document.querySelector('#status');
const resultPre = document.querySelector('#result');

// Function to update the status and result displays
const updateDisplay = (type, message, data = null) => {
	statusDiv.className = type;
	statusDiv.textContent = message;
	if (data) {
		resultPre.textContent = JSON.stringify(data, null, 2);
	} else {
		resultPre.textContent = '';
	}
};

// Basic check for FedCM availability on page load
if ('credentials' in navigator && 'get' in navigator.credentials) {
	updateDisplay(
		'info',
		'FedCM API appears to be available. Click the button to test. ' +
			'Remember to replace placeholder `configURL` and `clientId`.'
	);
} else {
	updateDisplay(
		'error',
		'FedCM API is not natively supported in this browser environment.'
	);
}

// Add event listener to the sign-in button
signInButton.addEventListener('click', async () => {
	updateDisplay('info', 'Attempting to sign in with FedCM...');
	resultPre.textContent = 'Waiting for FedCM API response...';

	// Check if FedCM API is available in the browser
	if (!('credentials' in navigator) || !('get' in navigator.credentials)) {
		updateDisplay(
			'error',
			'FedCM API not available in this browser. Please use a compatible browser ' +
				'(e.g., Chrome or Edge with experimental flags enabled, or Firefox Nightly).'
		);
		return;
	}

	try {
		// The core of the FedCM API: navigator.credentials.get()
		// This call triggers the browser's FedCM UI to show available accounts
		// from registered Identity Providers (IdPs).
		const credential = await navigator.credentials.get({
			identity: {
				// 'providers' is an array of Identity Provider configurations.
				// In a real application, these would be provided by the IdP.
				providers: [
					{
						// configURL: The URL to the IdP's well-known configuration file
						// (e.g., `https://idp.example/.well-known/web-identity/v1`).
						// This JSON file describes the IdP's endpoints and capabilities.
						// REPLACE WITH A REAL IDP'S CONFIG URL.
						configURL: 'https://idp.example/fedcm.json', // Placeholder URL

						// clientId: Your Relying Party's unique client ID,
						// registered with the Identity Provider.
						// REPLACE WITH YOUR ACTUAL CLIENT ID FROM THE IDP.
						clientId: 'YOUR_RP_CLIENT_ID_GOES_HERE', // Placeholder Client ID

						// nonce: A cryptographically strong, randomly generated string.
						// It's used to prevent replay attacks and is typically sent
						// to the IdP and included in the returned ID token.
						// Recommended for enhanced security.
						nonce: crypto.randomUUID(), // Generates a unique nonce

						// Optional: The 'context' can be 'signin', 'signup', 'use', or 'reload'.
						// This provides a hint to the IdP about the user's intent.
						context: 'signin'
					}
				]
			}
		});

		// Check the type of credential received.
		// For FedCM, it should be an 'IdentityCredential'.
		if (credential.type === 'identity') {
			// An IdentityCredential object contains the ID token.
			const identityCredential = credential;

			updateDisplay(
				'success',
				'Successfully received IdentityCredential from FedCM!',
				{
					id: identityCredential.id,
					protocol: identityCredential.protocol,
					token: identityCredential.token // This is the JWT from the IdP
					// In a real app, you would send this 'token' to your backend
					// for verification and user session creation.
				}
			);
			console.log('Identity Credential:', identityCredential);
			alert(
				'Sign-in successful via FedCM! Check console for details and the received token.'
			);

			// In a real application, you would now send `identityCredential.token`
			// to your backend server for verification and user session establishment.
			// Example (conceptual, requires backend endpoint):
			/*
                    const response = await fetch('/api/verify-fedcm-token', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                        },
                        body: JSON.stringify({ token: identityCredential.token }),
                    });
                    const backendResult = await response.json();
                    console.log('Backend verification result:', backendResult);
                    */
		} else {
			updateDisplay(
				'warning',
				'Received an unexpected credential type: ' + credential.type,
				credential
			);
			console.warn('Unexpected credential type:', credential);
		}
	} catch (error) {
		// Handle various types of errors that can occur during the FedCM flow.
		// These include user cancellation, IdP errors, browser errors, etc.
		updateDisplay(
			'error',
			'FedCM API error: ' + error.name + ' - ' + error.message,
			{
				name: error.name,
				message: error.message
				// If it's an IdentityCredentialError, it might have more details
				// idpError: error.idpError // (Not always present, depends on IdP implementation)
			}
		);
		console.error('FedCM API call failed:', error);
		alert('FedCM sign-in failed. Check the console for error details.');
	}
});

				
			

Benefits at a glance

Share the Post:

Related Posts

small_c_popup.png

Need help?

Let's have a chat...


Login

Jump Back In!

Here at Webolution Designs, we love to learn. This includes sharing things we have learned with you. 

Register

Begin Your Learning Journey Today!

Come back inside to continue your learning journey.