Skip to content

Node.js Express 集成教程

本教程介绍如何使用 Node.js + Express 框架通过 Authorization Code Flow 集成 Code Bird Cloud 进行用户认证。

前置条件

  • Node.js 18 或更高版本
  • npm 或 pnpm 包管理器
  • 已在 Code Bird Cloud 管理后台创建 Traditional 类型的应用,并获取 Client ID 和 Client Secret
  • 已配置 Redirect URI 为 http://localhost:3000/callback

安装依赖

bash
npm install express openid-client express-session
依赖包说明
expressWeb 框架
openid-clientOIDC 客户端库,支持自动发现、授权码流程、令牌管理
express-sessionSession 中间件,用于存储 state 和 nonce

完整代码示例

javascript
import express from 'express';
import * as client from 'openid-client';

const app = express();

const ISSUER = 'https://your-domain.com';
const CLIENT_ID = process.env.CLIENT_ID;
const CLIENT_SECRET = process.env.CLIENT_SECRET;
const REDIRECT_URI = 'http://localhost:3000/callback';

let oidcConfig;

async function initOIDC() {
  oidcConfig = await client.discovery(new URL(ISSUER), CLIENT_ID, CLIENT_SECRET);
}

app.get('/login', (req, res) => {
  const state = client.randomState();
  const nonce = client.randomNonce();

  // Store state and nonce in session
  req.session = { state, nonce };

  const authUrl = client.buildAuthorizationUrl(oidcConfig, {
    redirect_uri: REDIRECT_URI,
    scope: 'openid profile email offline_access',
    state,
    nonce,
  });

  res.redirect(authUrl.href);
});

app.get('/callback', async (req, res) => {
  try {
    const tokens = await client.authorizationCodeGrant(
      oidcConfig,
      new URL(req.url, 'http://localhost:3000'),
      {
        expectedState: req.session.state,
        expectedNonce: req.session.nonce,
      },
    );

    const { access_token, id_token, refresh_token } = tokens;
    const userInfo = await client.fetchUserInfo(oidcConfig, access_token);

    res.json({ message: 'Login successful', user: userInfo });
  } catch (err) {
    res.status(500).json({ error: 'Authentication failed' });
  }
});

app.post('/refresh', async (req, res) => {
  try {
    const tokens = await client.refreshTokenGrant(oidcConfig, req.body.refresh_token);
    res.json(tokens);
  } catch (err) {
    res.status(500).json({ error: 'Token refresh failed' });
  }
});

initOIDC().then(() => {
  app.listen(3000, () => console.log('Server running at http://localhost:3000'));
});

代码说明

OIDC 初始化

client.discovery() 会自动调用 Code Bird Cloud 的 /.well-known/openid-configuration 端点,获取所有必要的端点地址和配置信息。初始化只需执行一次。

登录路由 /login

  1. 生成随机的 statenonce 值,存储到 Session 中
  2. 构建授权 URL,包含 client_idredirect_uriscopestatenonce
  3. 将用户重定向到 Code Bird Cloud 的登录页面

回调路由 /callback

  1. 用户在 Code Bird Cloud 完成认证后,携带授权码重定向回此路由
  2. client.authorizationCodeGrant() 自动完成授权码换取令牌的过程,并验证 statenonce
  3. 使用 Access Token 获取用户信息

令牌刷新路由 /refresh

当 Access Token 过期时,使用 Refresh Token 获取新的令牌对。需要在初始授权请求的 scope 中包含 offline_access 才会返回 Refresh Token。

运行

bash
# 设置环境变量
export CLIENT_ID="your_client_id"
export CLIENT_SECRET="your_client_secret"

# 启动服务
node app.js

访问 http://localhost:3000/login 开始登录流程。

相关文档

Released under the MIT License.