Embed sign-in in 5 minutes
This page takes you from a blank page to the moment your backend has the user’s token.
1. Add the SDK
Section titled “1. Add the SDK”Add the tag to the page that holds the sign-in button:
<script src="https://id.fidmos.com/js/sdk.js" data-client-id="YOUR_CLIENT_ID"></script>With the data-client-id attribute the SDK warms the window up in advance — it opens instantly.
npm install fidmos-idnpm install fidmos-id2. Open the sign-in window
Section titled “2. Open the sign-in window”On the client, call login with clientId and redirectUri. The window opens over your page
instantly, starts the sign-in flow on its own and, when done, returns the authorization code to
onSuccess.
The SDK is added via the tag in step 1 — call the window.FidmosID global directly:
window.FidmosID.login({
clientId: 'YOUR_CLIENT_ID',
redirectUri: 'https://partner.example/callback',
scope: 'openid profile email',
onSuccess: async ({ code, state, codeVerifier }) => {
// exchange code for a token on your backend: POST /login/callback
await fetch('/login/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code, state, codeVerifier }),
});
location.assign('/logged-in');
},
onCancel: () => {
// the user closed the window; cancellation is not counted as an error
},
onError: ({ code }) => {
// code: 'invalid_arguments' | 'already_open' | 'unavailable'
},
});import { login } from 'fidmos-id';
export function LoginButton() {
const signIn = () =>
login({
clientId: 'YOUR_CLIENT_ID',
redirectUri: 'https://partner.example/callback',
scope: 'openid profile email',
onSuccess: async ({ code, state, codeVerifier }) => {
// exchange code for a token on your backend: POST /login/callback
await fetch('/login/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code, state, codeVerifier }),
});
location.assign('/logged-in');
},
onError: ({ code }) => {
// code: 'invalid_arguments' | 'already_open' | 'unavailable'
},
});
return <button onClick={signIn}>Sign in with Fidmos</button>;
}<script setup>
import { login } from 'fidmos-id';
function signIn() {
login({
clientId: 'YOUR_CLIENT_ID',
redirectUri: 'https://partner.example/callback',
scope: 'openid profile email',
onSuccess: async ({ code, state, codeVerifier }) => {
// exchange code for a token on your backend: POST /login/callback
await fetch('/login/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code, state, codeVerifier }),
});
location.assign('/logged-in');
},
onError: ({ code }) => {
// code: 'invalid_arguments' | 'already_open' | 'unavailable'
},
});
}
</script>
<template>
<button @click="signIn">Sign in with Fidmos</button>
</template>A full breakdown of the call shape on each stack (button busy state, component) is in the widget contract.
3. Exchange the code for a token
Section titled “3. Exchange the code for a token”On your backend, exchange the received code for a token with a regular OAuth2 request — using the
code_verifier that arrived in onSuccess (the codeVerifier field) and your client_secret.
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=RECEIVED_CODE&
redirect_uri=https://partner.example/callback&
client_id=YOUR_CLIENT_ID&
client_secret=YOUR_CLIENT_SECRET&
code_verifier=CODE_VERIFIER_FROM_ONSUCCESSThe response contains access_token, refresh_token and id_token (an OIDC JWT). Refreshing the
token, reading the profile through UserInfo and the discovery endpoint addresses are in
exchange code for token.
4. Find out who signed in
Section titled “4. Find out who signed in”The user identifier is the sub field from id_token or from the
GET /oauth/userinfo response. It is pairwise: stable for your client, and
you use it to recognize the person on their next sign-in.
A full description of requests and responses is in the API reference.