Перейти к содержимому
FidmosДокументация

Редиректный вход

Кроме встроенного окна есть классический путь OAuth 2.0: браузер уходит на нашу страницу входа, пользователь входит и возвращается к вам с кодом. Виджет для этого не нужен.

  • Встроенное окно (виджет) — пользователь не покидает вашу страницу, окно рисуется поверх. Нужен sdk.js и разрешённые origin.
  • Authorization Code Flow (редиректный) — эта страница; полный переход на нашу страницу и обратно. Проще на серверных приложениях без SPA, работает без виджета входа на странице.

Обе формы кончаются одинаково: у вас на бэкенде код авторизации, который вы меняете на токен.

  1. Отправьте пользователя на /oauth/authorize с параметрами запроса. Сгенерируйте PKCE, state и nonce, сохраните их в сессии.

  2. Пользователь входит на нашей странице и возвращается на ваш redirect_uri с code и state в query.

  3. Обменяйте код на токен и проверьте id_token — тем же кодом, что в примере бэкенда.

import * as client from 'openid-client';
import { ISSUER, CLIENT_ID, CLIENT_SECRET, REDIRECT_URI } from './config.js';

const config = await client.discovery(new URL(ISSUER), CLIENT_ID, CLIENT_SECRET);
const pending = new Map(); // в бою — сессия/Redis, ключ по вашему session id

// Шаг 1. Собрать URL авторизации и увести туда браузер.
export async function buildLoginUrl() {
  const codeVerifier = client.randomPKCECodeVerifier();
  const codeChallenge = await client.calculatePKCECodeChallenge(codeVerifier);
  const state = client.randomState();
  const nonce = client.randomNonce();

  const url = client.buildAuthorizationUrl(config, {
    redirect_uri: REDIRECT_URI,
    scope: 'openid profile email',
    state,
    nonce,
    code_challenge: codeChallenge,
    code_challenge_method: 'S256',
  });

  pending.set(state, { codeVerifier, nonce });
  return url.href; // сделайте res.redirect(url.href)
}

// Шаг 2. Обработать возврат: адрес запроса содержит code и state.
export async function handleCallback(incomingUrl) {
  const url = new URL(incomingUrl);
  const draft = pending.get(url.searchParams.get('state'));

  const tokens = await client.authorizationCodeGrant(config, url, {
    pkceCodeVerifier: draft.codeVerifier,
    expectedState: url.searchParams.get('state'),
    expectedNonce: draft.nonce,
    idTokenExpected: true,
  });

  return tokens.claims().sub; // парный идентификатор пользователя
}

response_type=code buildAuthorizationUrl проставит сам; code_challenge мы считаем из code_verifier и передаём явно. Адреса эндпоинтов библиотека берёт из discovery — хардкодить их не нужно.

Дальше — профиль пользователя и коды ошибок.