A gentle intro to the Credential Management API

Secure Login Access with Username and Password on Mobile Device and Laptop

If you’ve ever built a login form and wished the browser could securely remember and reuse a user’s credentials without fighting autofill, the Credential Management API (CredMan) is for you. It gives you a standardized way to store, retrieve, and use credentials—reducing friction for returning users while keeping sensitive data in the browser’s credential manager.

What the demo does

Why this is useful

Practical tips

What about WebAuthn and federated logins?

CredMan also complements modern sign-in flows:

Browser support

Credential Management API support is strongest in Chromium-based browsers. Safari and Firefox have partial or differing support, especially around PasswordCredential. Always feature-detect and test across targets.

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Credential Management API Demo</title>
    <link href="style.css" rel="stylesheet" />
    <script src="credentialManagementAPI.js" defer></script>
</head>

<body>
    <h1>Credential Management API Demo</h1>
    <form id="login-form">
        <label>
            Username:
            <input type="text" name="username" autocomplete="username" required>
        </label>
        <br>
        <label>
            Password:
            <input type="password" name="password" autocomplete="current-password" required>
        </label>
        <br>
        <button type="submit">Login</button>
    </form>
    <button id="auto-login">Auto Login with Stored Credentials</button>
</body>

</html>
				
			
				
					/* style.css */

/* Reset some default browser styles */
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

/* Body and overall layout */
body {
    font-family: 'Segoe UI', Arial, sans-serif;
    background: #f6f8fa;
    color: #222;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 40px 10px;
}

/* Main heading */
h1 {
    margin-bottom: 24px;
    font-size: 2rem;
    color: #006a39;
    letter-spacing: 1px;
}

/* Form styling */
form {
    background: #fff;
    padding: 24px 32px;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
    margin-bottom: 24px;
    min-width: 280px;
    max-width: 350px;
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

label {
    font-weight: 500;
    margin-bottom: 4px;
}

input[type="text"],
input[type="password"] {
    padding: 8px 12px;
    border: 1px solid #ccc;
    border-radius: 4px;
    font-size: 1rem;
    transition: border-color 0.2s;
}

input[type="text"]:focus,
input[type="password"]:focus {
    border-color: #4298b5;
    outline: none;
}

/* Button styling */
button {
    background: #006a39;
    color: #fff;
    border: none;
    border-radius: 4px;
    padding: 10px 0;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    margin-top: 8px;
    transition: background 0.2s;
    min-width: 120px;
}

button:hover,
button:focus {
    background: #4298b5;
}

/* Secondary button (if needed) */
button.secondary {
    background: #fff;
    color: #006a39;
    border: 1px solid #006a39;
}

button.secondary:hover,
button.secondary:focus {
    background: #f2f2f2;
}

/* User info output */
#userInfo {
    margin-top: 24px;
    background: #fff;
    padding: 16px 24px;
    border-radius: 6px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
    min-width: 220px;
    max-width: 350px;
    width: 100%;
    word-break: break-word;
}

/* Responsive adjustments */
@media (max-width: 500px) {

    form,
    #userInfo {
        padding: 16px 8px;
        min-width: unset;
        max-width: 100%;
    }

    body {
        padding: 20px 2px;
    }

    h1 {
        font-size: 1.3rem;
    }
}
				
			
				
					document.addEventListener('DOMContentLoaded', () => {
	// Check for Credential Management API support
	if ('credentials' in navigator && window.PasswordCredential) {
		console.log('Credential Management API is supported!');
	} else {
		console.log('Credential Management API is not supported in this browser.');
	}

	// Handle login form submission
	const loginForm = document.querySelector('#login-form');

	loginForm.addEventListener('submit', async (e) => {
		e.preventDefault();

		const form = e.target;
		const username = form.username.value;
		const password = form.password.value;

		if (username && password) {
			try {
				// Create a PasswordCredential object from the form
				const cred = new window.PasswordCredential(form);

				// Store credentials in the browser's credential manager
				await navigator.credentials.store(cred);
				console.log('Credentials stored! Try the "Auto Login" button.');

				// Simulate successful login
				form.reset();
			} catch (err) {
				console.error('Failed to store credentials:', err);
			}
		} else {
			console.log('Please enter both username and password.');
		}
	});

	// Handle auto-login using stored credentials
	const autoLoginBtn = document.querySelector('#auto-login');
	let credentialsRequestPending = false;

	autoLoginBtn.addEventListener('click', async () => {
		try {
			if (credentialsRequestPending) {
				console.log('A credentials request is already pending.');
				return;
			}

			credentialsRequestPending = true;
			autoLoginBtn.disabled = true; // Optional: disables the button for UX

			const cred = await navigator.credentials.get({
				password: true,
				mediation: 'optional'
			});

			if (cred) {
				document.querySelector('input[name="username"]').value = cred.id;
				document.querySelector('input[name="password"]').value = cred.password;
				console.log(`Auto-filled credentials for user: ${cred.id}`);
			} else {
				console.log('No stored credentials found.');
			}
		} catch (err) {
			console.error('Failed to retrieve credentials:', err);
		} finally {
			credentialsRequestPending = false;
			autoLoginBtn.disabled = false;
		}
	});
});

				
			

Bottom line

The Credential Management API is a low-effort, high-UX win: store after successful login, retrieve on return, and let the browser do the secure heavy lifting. Start with password credentials as shown in the demo, and plan for WebAuthn to future‑proof your sign-in experience.

more posts:
Online video streaming platform and digital content management concept with media player interface, cloud library, and multimedia files on laptop, representing content distribution, video marketing
Code

Breaking into the Pipeline: Real-Time Frame Manipulation with the Insertable Streams for MediaStreamTrack API

The experimental Insertable Streams for MediaStreamTrack API closes a long-standing gap in web multimedia by treating live camera feeds as standard Web Streams. By piping individual VideoFrame objects through a TransformStream and recording the transformed output via MediaRecorder, developers can execute frame-by-frame processing—like real-time filtering, watermarking, and computer vision overlays—without relying on hidden canvas hacks.

Discover More »
Apps & Custom Software

What Building Our Own App Taught Us About Building Yours

When Hess WebTech built and launched Tericipe—an Android app that turns printed recipes into a searchable digital collection—in under three months, we had to live with every decision we usually advise clients on. From testing against real-world messy data and handling AI uncertainty to server-side payment security and post-launch maintenance, here are five crucial lessons from our own build that apply to almost any software project.

Discover More »