'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
- Войдите на IdP ({frontendBase}) в этом браузере.
- Откройте сайт клиента с виджетом — Chrome покажет нативный диалог или плашку One Tap.
-
login_url в config.json должен быть на том же домене, что и config (
{endpoints.issuer}/auth/login), не на SSO-домене.
-
configURL для FedCM: {endpoints.fedcmConfigUrl} (не{' '}
{frontendBase}/idp-api/fedcm/config.json).
-
При ошибке 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}
);
}