Files
IdP/apps/docs/lib/oauth-examples.ts
2026-06-25 23:48:57 +03:00

183 lines
5.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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: `<?php
// composer require jumbojett/openid-connect-php
require 'vendor/autoload.php';
use Jumbojett\\OpenIDConnectClient;
$issuer = '${API_BASE}'; // PUBLIC_API_URL из админки Lendry ID
$clientId = getenv('OAUTH_CLIENT_ID');
$clientSecret = getenv('OAUTH_CLIENT_SECRET');
$redirectUri = 'https://app.example.com/oauth/callback';
$oidc = new OpenIDConnectClient($issuer, $clientId, $clientSecret);
$oidc->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');