'use client'; import { useMemo, useState } from 'react'; import { Copy, ExternalLink } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { OAuthClient } from '@/lib/api'; import { buildOneTapExamples } from '@/lib/one-tap-examples'; import { OAuthEndpoints } from '@/lib/oauth-url'; function SnippetBlock({ code, onCopy }: { code: string; onCopy: (value: string, label: string) => void }) { return (
{code}
); } export function OAuthClientOneTapSection({ client, endpoints, frontendBase, projectName, onCopy }: { client: OAuthClient; endpoints: OAuthEndpoints; frontendBase: string; projectName: string; onCopy: (value: string, label: string) => void; }) { const primaryRedirect = client.redirectUris[0] ?? `${frontendBase}/auth/callback`; const examples = useMemo( () => buildOneTapExamples( { apiBase: endpoints.issuer, frontendBase, widgetUrl: endpoints.widgetUrl, fedcmConfigUrl: endpoints.fedcmConfigUrl, webIdentityUrl: endpoints.webIdentityUrl, fedcmDiscoverUrl: endpoints.fedcmDiscoverUrl, projectName }, client.clientId, primaryRedirect ), [client.clientId, endpoints, frontendBase, primaryRedirect, projectName] ); const [activeTab, setActiveTab] = useState(examples[0]?.id ?? 'widget-script'); return (

One Tap Login

FedCM (Chrome/Edge) и виджет sso-widget.js с popup fallback. Убедитесь, что в настройках указаны PUBLIC_API_URL и PUBLIC_FRONTEND_URL.

{examples.map((example) => ( {example.label} ))} {examples.map((example) => ( ))}

Проверка FedCM

  1. Войдите на IdP ({frontendBase}) в этом браузере.
  2. Откройте сайт клиента с виджетом — Chrome покажет нативный диалог или плашку One Tap.
  3. login_url в config.json должен быть на том же домене, что и config ( {endpoints.issuer}/auth/login), не на SSO-домене.
  4. configURL для FedCM: {endpoints.fedcmConfigUrl} (не{' '} {frontendBase}/idp-api/fedcm/config.json).
  5. При ошибке NetworkError проверьте, что PUBLIC_API_URL = {endpoints.issuer}.
Открыть sso-widget.js
); } function CopyRowCompact({ label, value, onCopy }: { label: string; value: string; onCopy: (value: string, label: string) => void; }) { return (
{label}
{value}
); }