Cliente OAuth para TypeScript: autorización a través de GitHub, Google y otros proveedores

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Cliente OAuth para TypeScript: implementación de autorización en un sitio educativo

\n\n

En el desarrollo web moderno, OAuth (Open Authorization) se ha convertido en el estándar de facto para la autenticación de usuarios a través de servicios de terceros. Para el sitio educativo pythonlib.ru hemos preparado una descripción de un cliente OAuth universal en TypeScript, que permite implementar el inicio de sesión a través de GitHub, Google y otros proveedores populares.

\n\n

¿Qué es un cliente OAuth?

\n

Un cliente OAuth es un componente de software que gestiona el proceso de obtención de permisos del usuario para acceder a sus datos en un servicio de terceros. En el contexto de TypeScript, dicho cliente generalmente implementa el protocolo OAuth 2.0 e incluye:

\n
    \n
  • Inicialización del proceso de autorización
  • \n
  • Manejo de solicitudes de callback
  • \n
  • Intercambio de authorization code por access token
  • \n
  • Actualización de tokens (refresh token)
  • \n
  • Trabajo con el estado de la sesión
  • \n
\n\n

Arquitectura del cliente OAuth en TypeScript

\n

Nuestro cliente está construido sobre los principios de modularidad y seguridad de tipos. Componentes principales:

\n\n

1. Configuración del proveedor

\n
interface OAuthProviderConfig {\n  clientId: string;\n  clientSecret: string;\n  redirectUri: string;\n  authorizationEndpoint: string;\n  tokenEndpoint: string;\n  scopes: string[];\n}\n\nconst githubConfig: OAuthProviderConfig = {\n  clientId: process.env.GITHUB_CLIENT_ID!,\n  clientSecret: process.env.GITHUB_CLIENT_SECRET!,\n  redirectUri: 'https://pythonlib.ru/auth/callback/github',\n  authorizationEndpoint: 'https://github.com/login/oauth/authorize',\n  tokenEndpoint: 'https://github.com/login/oauth/access_token',\n  scopes: ['read:user', 'user:email']\n};
\n\n

2. Generación de URL para autorización

\n
function generateAuthUrl(config: OAuthProviderConfig, state: string): string {\n  const params = new URLSearchParams({\n    client_id: config.clientId,\n    redirect_uri: config.redirectUri,\n    scope: config.scopes.join(' '),\n    state: state,\n    response_type: 'code'\n  });\n  \n  return `${config.authorizationEndpoint}?${params.toString()}`;\n}
\n\n

3. Intercambio de código por token

\n
async function exchangeCodeForToken(\n  config: OAuthProviderConfig,\n  code: string\n): Promise<OAuthTokenResponse> {\n  const response = await fetch(config.tokenEndpoint, {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n      'Accept': 'application/json'\n    },\n    body: JSON.stringify({\n      client_id: config.clientId,\n      client_secret: config.clientSecret,\n      code: code,\n      redirect_uri: config.redirectUri\n    })\n  });\n\n  if (!response.ok) {\n    throw new Error(`Token exchange failed: ${response.statusText}`);\n  }\n\n  return response.json();\n}
\n\n

Trabajo con tokens

\n

Después de obtener los tokens, es necesario garantizar su almacenamiento seguro y actualización. Se recomienda usar httpOnly cookies o almacenamiento de sesiones en el servidor.

\n\n

Actualización del access token

\n
async function refreshAccessToken(\n  config: OAuthProviderConfig,\n  refreshToken: string\n): Promise<OAuthTokenResponse> {\n  const response = await fetch(config.tokenEndpoint, {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json'\n    },\n    body: JSON.stringify({\n      client_id: config.clientId,\n      client_secret: config.clientSecret,\n      refresh_token: refreshToken,\n      grant_type: 'refresh_token'\n    })\n  });\n\n  return response.json();\n}
\n\n

Ejemplo completo de implementación para GitHub OAuth

\n
import { randomBytes } from 'crypto';\n\nclass GitHubOAuthClient {\n  private config: OAuthProviderConfig;\n  private stateStore: Map<string, string> = new Map();\n\n  constructor() {\n    this.config = {\n      clientId: process.env.GITHUB_CLIENT_ID!,\n      clientSecret: process.env.GITHUB_CLIENT_SECRET!,\n      redirec                    

Recommendations