OAuth 客户端 for TypeScript:通过 GitHub、Google 及其他提供商进行授权

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

OAuth 客户端 for TypeScript:教育网站上的授权实现



在现代 Web 开发中,OAuth(开放授权)已成为通过第三方服务对用户进行身份验证的事实标准。对于教育网站 pythonlib.ru,我们准备了一个基于 TypeScript 的通用 OAuth 客户端的描述,该客户端允许通过 GitHub、Google 和其他流行提供商实现登录。



什么是 OAuth 客户端?

OAuth 客户端是一个软件组件,用于管理从用户处获取权限以访问其在第三方服务上的数据的过程。在 TypeScript 的上下文中,此类客户端通常实现 OAuth 2.0 协议,并包括:

  • 初始化授权过程
  • 处理回调请求
  • 将 authorization code 交换为 access token
  • 更新令牌(refresh token)
  • 处理会话状态


TypeScript 上 OAuth 客户端的架构

我们的客户端基于模块化和类型安全原则构建。主要组件:



1. 提供商的配置

interface OAuthProviderConfig {  clientId: string;  clientSecret: string;  redirectUri: string;  authorizationEndpoint: string;  tokenEndpoint: string;  scopes: string[];}

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


2. 生成授权 URL

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


3. 将代码交换为令牌

async function exchangeCodeForToken(  config: OAuthProviderConfig,  code: string): Promise<OAuthTokenResponse> {  const response = await fetch(config.tokenEndpoint, {    method: 'POST',    headers: {      'Content-Type': 'application/json',      'Accept': 'application/json'    },    body: JSON.stringify({      client_id: config.clientId,      client_secret: config.clientSecret,      code: code,      redirect_uri: config.redirectUri    })  });

if (!response.ok) { throw new Error(`Token exchange failed: ${response.statusText}`); }

return response.json();}


令牌的使用

获取令牌后,必须确保其安全存储和更新。建议使用 httpOnly cookies 或服务器端会话存储。



更新 access token

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

return response.json();}


GitHub OAuth 的完整实现示例

import { randomBytes } from 'crypto';

class GitHubOAuthClient { private config: OAuthProviderConfig; private stateStore: Map<string, string> = new Map();

constructor() { this.config = { clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET!, redirec

推荐