export interface OAuthExample { id: string; label: string; language: string; code: string; } export function buildOAuthExamples(apiBase: string): OAuthExample[] { const API_BASE = apiBase.replace(/\/+$/, ''); return [ { id: 'javascript', label: 'JavaScript', language: 'javascript', code: `// Authorization Code Flow — стандартный OIDC (RFC 6749) const clientId = 'YOUR_CLIENT_ID'; const redirectUri = 'https://app.example.com/oauth/callback'; const scope = 'openid profile email'; const state = crypto.randomUUID(); // Шаг 1: перенаправить пользователя на IdP const authorizeUrl = new URL('${API_BASE}/oauth/authorize'); authorizeUrl.searchParams.set('client_id', clientId); authorizeUrl.searchParams.set('redirect_uri', redirectUri); authorizeUrl.searchParams.set('response_type', 'code'); authorizeUrl.searchParams.set('scope', scope); authorizeUrl.searchParams.set('state', state); window.location.href = authorizeUrl.toString(); // OIDC Discovery // GET ${API_BASE}/.well-known/openid-configuration // Шаг 2: обменять code на токены (на backend!) const tokenResponse = await fetch('${API_BASE}/oauth/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'authorization_code', code: 'AUTHORIZATION_CODE', client_id: clientId, client_secret: 'YOUR_CLIENT_SECRET', redirect_uri: redirectUri }) }); const tokens = await tokenResponse.json(); // tokens.access_token, tokens.id_token, tokens.refresh_token // Шаг 3: получить профиль const profile = await fetch('${API_BASE}/oauth/userinfo', { headers: { Authorization: \`Bearer \${tokens.access_token}\` } }).then((r) => r.json());` }, { id: 'php', label: 'PHP (OIDC)', language: 'php', code: `setRedirectURL($redirectUri); $oidc->addScope(['openid', 'profile', 'email']); // Библиотека сама использует discovery, client_id, redirect_uri, response_type=code $oidc->authenticate(); $sub = $oidc->requestUserInfo('sub'); $name = $oidc->requestUserInfo('name'); $email = $oidc->requestUserInfo('email'); // userId передавать НЕ нужно — IdP определяет пользователя после входа` }, { id: 'typescript-next', label: 'Next.js', language: 'typescript', code: `// app/api/oauth/callback/route.ts import { NextRequest, NextResponse } from 'next/server'; const ISSUER = '${API_BASE}'; export async function GET(request: NextRequest) { const code = request.nextUrl.searchParams.get('code'); if (!code) return NextResponse.redirect('/login?error=oauth'); const tokenRes = await fetch(\`\${ISSUER}/oauth/token\`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'authorization_code', code, client_id: process.env.OAUTH_CLIENT_ID!, client_secret: process.env.OAUTH_CLIENT_SECRET!, redirect_uri: process.env.OAUTH_REDIRECT_URI! }) }); const tokens = await tokenRes.json(); const response = NextResponse.redirect('/dashboard'); response.cookies.set('access_token', tokens.access_token, { httpOnly: true, secure: true }); return response; }` }, { id: 'python', label: 'Python', language: 'python', code: `import requests API_BASE = '${API_BASE}' CLIENT_ID = 'YOUR_CLIENT_ID' CLIENT_SECRET = 'YOUR_CLIENT_SECRET' REDIRECT_URI = 'https://app.example.com/oauth/callback' discovery = requests.get(f'{API_BASE}/.well-known/openid-configuration', timeout=15).json() # Authorization URL — стандартные параметры, userId не нужен authorize_url = ( f"{discovery['authorization_endpoint']}" f"?client_id={CLIENT_ID}" f"&redirect_uri={requests.utils.quote(REDIRECT_URI, safe='')}" f"&response_type=code" f"&scope=openid%20profile%20email" f"&state=random-state" ) token_response = requests.post( discovery['token_endpoint'], data={ 'grant_type': 'authorization_code', 'code': 'AUTHORIZATION_CODE', 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET, 'redirect_uri': REDIRECT_URI, }, timeout=15, ) tokens = token_response.json() profile = requests.get( discovery['userinfo_endpoint'], headers={'Authorization': f"Bearer {tokens['access_token']}"}, timeout=15, ).json()` }, { id: 'curl', label: 'cURL', language: 'bash', code: `# OIDC Discovery curl ${API_BASE}/.well-known/openid-configuration # Authorization (браузер пользователя, стандартный OIDC) open "${API_BASE}/oauth/authorize?client_id=CLIENT_ID&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback&response_type=code&scope=openid%20profile%20email&state=xyz" # Обмен code на токены (form-urlencoded) curl -X POST ${API_BASE}/oauth/token \\ -H "Content-Type: application/x-www-form-urlencoded" \\ -d "grant_type=authorization_code" \\ -d "code=AUTHORIZATION_CODE" \\ -d "client_id=CLIENT_ID" \\ -d "client_secret=CLIENT_SECRET" \\ -d "redirect_uri=https://app.example.com/callback" # UserInfo curl ${API_BASE}/oauth/userinfo \\ -H "Authorization: Bearer ACCESS_TOKEN"` } ]; } /** @deprecated Используйте buildOAuthExamples(apiBase) */ export const oauthExamples = buildOAuthExamples('http://localhost:3000');