OAuth-Client für TypeScript: Authentifizierung über GitHub, Google und andere Anbieter

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

OAuth-Client für TypeScript: Implementierung der Authentifizierung auf einer Bildungswebsite

\n\n

In der modernen Webentwicklung ist OAuth (Open Authorization) zum De-facto-Standard für die Authentifizierung von Benutzern über Drittanbieterdienste geworden. Für die Bildungswebsite pythonlib.ru haben wir eine Beschreibung eines universellen OAuth-Clients in TypeScript vorbereitet, der die Anmeldung über GitHub, Google und andere gängige Anbieter ermöglicht.

\n\n

Was ist ein OAuth-Client?

\n

Ein OAuth-Client ist eine Softwarekomponente, die den Prozess der Einholung von Berechtigungen eines Benutzers für den Zugriff auf seine Daten bei einem Drittanbieterdienst verwaltet. Im Kontext von TypeScript implementiert ein solcher Client in der Regel das OAuth 2.0-Protokoll und umfasst:

\n
    \n
  • Initialisierung des Autorisierungsprozesses
  • \n
  • Verarbeitung von Callback-Anfragen
  • \n
  • Austausch des Autorisierungscodes gegen ein Access Token
  • \n
  • Aktualisierung von Token (Refresh Token)
  • \n
  • Arbeit mit dem Sitzungszustand
  • \n
\n\n

Architektur des OAuth-Clients in TypeScript

\n

Unser Client basiert auf den Prinzipien der Modularität und Typsicherheit. Die Hauptkomponenten:

\n\n

1. Konfiguration des Anbieters

\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. Generierung der Autorisierungs-URL

\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. Austausch des Codes gegen ein 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

Arbeit mit Token

\n

Nach Erhalt der Token muss deren sichere Speicherung und Aktualisierung gewährleistet werden. Es wird empfohlen, httpOnly-Cookies oder serverseitige Sitzungsspeicher zu verwenden.

\n\n

Aktualisierung des 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

Vollständiges Implementierungsbeispiel für 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                    

Empfehlungen