import type { OAuthExample } from '@/lib/oauth-examples';
export interface OneTapUrls {
apiBase: string;
frontendBase: string;
widgetUrl: string;
fedcmConfigUrl: string;
webIdentityUrl: string;
projectName: string;
}
export function buildOneTapUrls(
apiBase: string,
frontendBase: string,
projectName = 'MVK ID'
): OneTapUrls {
const base = apiBase.replace(/\/+$/, '');
const front = frontendBase.replace(/\/+$/, '');
return {
apiBase: base,
frontendBase: front,
widgetUrl: `${front}/sso-widget.js`,
fedcmConfigUrl: `${base}/fedcm/config.json`,
webIdentityUrl: `${base}/.well-known/web-identity`,
projectName
};
}
export function buildOneTapExamples(urls: OneTapUrls, clientIdPlaceholder = 'YOUR_CLIENT_ID'): OAuthExample[] {
const { apiBase, frontendBase, widgetUrl, fedcmConfigUrl, projectName } = urls;
const redirectUri = 'https://app.example.com/auth/callback';
return [
{
id: 'widget-script',
label: 'Виджет (script tag)',
language: 'html',
code: `
`
},
{
id: 'fedcm-native',
label: 'FedCM (нативный API)',
language: 'javascript',
code: `// Работает в Chrome/Edge при поддержке IdentityCredential.
// Пользователь должен быть залогинен на ${frontendBase} (FedCM cookie).
async function loginWithFedCM() {
if (!('IdentityCredential' in window)) {
throw new Error('FedCM не поддерживается в этом браузере');
}
const credential = await navigator.credentials.get({
identity: {
providers: [{
configURL: '${fedcmConfigUrl}',
clientId: '${clientIdPlaceholder}',
fields: ['name', 'email', 'picture', 'tel']
}]
},
mediation: 'optional'
});
if (!credential?.token) {
throw new Error('Пользователь отменил вход или сессия IdP отсутствует');
}
return credential.token; // OIDC id_token
}
loginWithFedCM()
.then((idToken) => fetch('/api/auth/lendry', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ idToken })
}))
.catch(console.error);`
},
{
id: 'sdk-manual',
label: 'SDK — ручной вызов',
language: 'javascript',
code: `
`
},
{
id: 'verify-backend',
label: 'Проверка токена на backend',
language: 'javascript',
code: `// Node.js — после получения id_token от FedCM или popup
import jwt from 'jsonwebtoken';
const ISSUER = '${apiBase}';
const CLIENT_ID = '${clientIdPlaceholder}';
function verifyIdToken(idToken) {
const payload = jwt.verify(idToken, process.env.IDP_JWT_SECRET, {
issuer: ISSUER,
audience: CLIENT_ID
});
return payload; // { sub, email, name, ... }
}
// Альтернатива: userinfo по access_token
async function fetchProfile(accessToken) {
const res = await fetch('${apiBase}/oauth/userinfo', {
headers: { Authorization: \`Bearer \${accessToken}\` }
});
if (!res.ok) throw new Error('userinfo failed');
return res.json();
}`
},
{
id: 'curl-fedcm',
label: 'FedCM endpoints (curl)',
language: 'bash',
code: `# Манифест FedCM
curl -s ${apiBase}/.well-known/web-identity | jq
# Конфигурация провайдера
curl -s ${apiBase}/fedcm/config.json | jq
# Список аккаунтов (нужна cookie lendry_fedcm_sess после входа на IdP)
curl -s ${apiBase}/fedcm/accounts \\
-H "Cookie: lendry_fedcm_sess=..." \\
--include
# Синхронизация FedCM cookie для уже залогиненного пользователя IdP
curl -s -X POST ${apiBase}/fedcm/session/sync \\
-H "Authorization: Bearer ACCESS_TOKEN"`
}
];
}