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
- Detects support: It checks if navigator.credentials and PasswordCredential exist to confirm the feature works in the user’s browser.
- Saves credentials on login: When the user submits the form, it builds a PasswordCredential from the form and calls navigator.credentials.store(cred). This securely stores the username and password with the site’s origin.
- Retrieves credentials on demand: The “Auto Login” button calls navigator.credentials.get({ password: true, mediation: 'optional' }) to request stored credentials. If available, it auto-fills the form fields with cred.id and cred.password.
Why this is useful
- Better UX for return visits: Users don’t have to retype credentials every time. With optional mediation, the browser can quietly provide saved credentials when appropriate.
- Origin-scoped security: Credentials are kept in the browser’s secure store and tied to your origin, reducing exposure versus ad‑hoc localStorage solutions.
- Progressive enhancement: If the API isn’t supported, your form still works like a normal login.
Practical tips
- Use proper autocomplete attributes: autocomplete="username" and autocomplete="current-password" help the browser recognize fields.
- Only store after real auth: In production, call navigator.credentials.store() after the server confirms login success.
- Handle fallbacks gracefully: Wrap calls in feature detection and keep your traditional login flow intact.
- Consider mediation modes: 1) 'optional': Try to auto-retrieve without user prompt, 2) 'required': Always involve the user (e.g., account pickers), 3) 'silent' (deprecated in many contexts): Avoids prompts entirely, but has limited availability.
What about WebAuthn and federated logins?
CredMan also complements modern sign-in flows:
- PublicKeyCredential (WebAuthn/passkeys) for phishing-resistant, passwordless auth.
- FederatedCredential for third-party identity providers (though support varies).
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.
Credential Management API Demo
Credential Management API Demo
/* 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.

