GKE web 应用实现 Auth0 + GitHub OAuth 2.0登录实施指南

由于 GCP 组织策略限制了 IAP 的外部访问,本指南详细说明如何将 askc-ui-dev (及后端 askc-bak-svc-dev) 的认证方案从 Google IAP 迁移到 Auth0 (集成 GitHub 登录)


认证流程概览

User Browser (AskC UI Dev) Auth0 GitHub AskC Backend Dev 访问 https://gateway.jpgcp.cloud/askc-ui-dev/ 重定向登录 (Client ID, Audience) 重定向 OAuth 授权 登录并确认授权 回调 (Authorization Code) 回调 (Authorization Code) 交换令牌 (PKCE Flow) 返回 Access Token & ID Token API 调用阶段 请求 API (Header: "Authorization: Bearer <Access Token>") 获取 JWKS 公钥 (首次/缓存失效时) 验证 Access Token 签名, Issuer, Audience 调用 /userinfo (携带 Access Token) 返回用户信息 (含 email, nickname 等) par [验证 Token] [获取用户信息] 返回数据 (200 OK) 返回错误 (401 Unauthorized) alt [验证成功] [验证失败] User Browser (AskC UI Dev) Auth0 GitHub AskC Backend Dev


第一阶段:Auth0 平台配置

1. 注册与创建租户

  1. 访问 Auth0 官网 并注册账号。
  2. 创建一个新的 Tenant (租户),例如命名为 askc-dev
  3. Region 选择离用户较近的区域(如 US 或 EU)。

2. 配置 GitHub 社交登录

  1. 在 Auth0 Dashboard 左侧菜单,点击 Authentication -> Social
  2. 点击 Create Connection ,选择 GitHub

3. 保留默认设置(使用 Auth0 的开发 Keys),或者(推荐)去 GitHub 注册 OAuth App 并填入 Client ID / Secret 以消除 Auth0 开发模式的限制。

Field Value to Provide

Homepage URL https://YOUR_DOMAIN

Authorization callback URL https://YOUR_DOMAIN/login/callback

Find your Auth0 domain name

If your Auth0 domain name is not shown above and you are not using our custom domains feature, your domain name is your tenant name, your regional subdomain (unless your tenant is in the US region and was created before June 2020), plus.auth0.com. For example, if your tenant name were exampleco-enterprises, your Auth0 domain name would be exampleco-enterprises.us.auth0.com and your callback URL would be https://exampleco-enterprises.us.auth0.com/login/callback

参考

https://marketplace.auth0.com/integrations/github-social-connection


  1. 确保 GitHub 连接处于 开启 (Enabled) 状态。

3. 创建前端应用 (Single Page Application)

  1. 点击 Applications -> Applications -> Create Application
  2. 名称:AskC UI Dev
  3. 类型:Single Page Web Applications

  1. 创建后,进入 Settings 标签页,记录以下信息:

    • Domain : (例如 dev-xyz.us.auth0.com)
    • Client ID: (一串字符)
  2. 配置 Application URIs:

    • Allowed Callback URLs : https://gateway.jpgcp.cloud/askc-ui-dev/, http://localhost:5173/ (本地开发用)
    • Allowed Logout URLs : https://gateway.jpgcp.cloud/askc-ui-dev/, http://localhost:5173/
    • Allowed Web Origins : https://gateway.jpgcp.cloud, http://localhost:5173
  3. 点击顶部的 Applications 标签页,确保 AskC UI Dev (如果已创建)或 Default App 的开关处于 开启 (绿色) 状态。否则测试连接会报错 connection is not enabled

  1. 回到 Settings 标签页底部点击 Save Changes

  2. 点击底部 Save Changes

4. 创建后端 API (API Identifier)

为了让前端能获取访问后端的 Access Token,需要定义一个 API。

  1. 点击 Applications -> APIs -> Create API
  1. Name : AskC Backend Dev

  2. Identifier (Audience): https://api.askc.dev (这是一个逻辑标识符,不需要真实存在)。

  3. Signing Algorithm : RS256

  4. 点击 Create

提示 :创建 API 后,您可能会在 Applications 列表中看到一个自动生成的 AskC Backend Dev (Test Application)。这是 Auth0 自动创建用于后端测试的 M2M 应用,您可以安全地忽略它。


第二阶段:前端代码修改 (askc-ui)

1. 安装依赖

bash 复制代码
npm install @auth0/auth0-spa-js

2. 添加环境变量

.env (本地开发) 和 Cloud Build 配置中添加:

properties 复制代码
VITE_AUTH0_DOMAIN=dev-xyz.us.auth0.com
VITE_AUTH0_CLIENT_ID=你的ClientID
VITE_AUTH0_AUDIENCE=https://api.askc.dev
VITE_USE_AUTH0=true  # 用于区分 Prod(IAP) 和 Dev(Auth0)

3. 封装 Auth 服务 (src/services/auth.ts)

创建一个统一的 Auth 接口,根据环境切换 IAP 或 Auth0 实现。

typescript 复制代码
import { Auth0Client, createAuth0Client } from '@auth0/auth0-spa-js';

let auth0: Auth0Client | null = null;

export const initAuth = async () => {
  if (import.meta.env.VITE_USE_AUTH0 !== 'true') return;

  auth0 = await createAuth0Client({
    domain: import.meta.env.VITE_AUTH0_DOMAIN,
    clientId: import.meta.env.VITE_AUTH0_CLIENT_ID,
    authorizationParams: {
      redirect_uri: window.location.origin + import.meta.env.VITE_BASE_PATH,
      audience: import.meta.env.VITE_AUTH0_AUDIENCE
    },
    cacheLocation: 'localstorage' // 避免刷新丢失登录态
  });

  // 处理回调
  if (location.search.includes("code=") && location.search.includes("state=")) {
    await auth0.handleRedirectCallback();
    window.history.replaceState({}, document.title, window.location.pathname);
  }
};

export const login = async () => {
  if (auth0) await auth0.loginWithRedirect();
  else window.location.reload(); // IAP 自动处理重定向
};

export const logout = async () => {
  if (auth0) {
    await auth0.logout({ 
        logoutParams: { returnTo: window.location.origin + import.meta.env.VITE_BASE_PATH } 
    });
  }
};

export const getToken = async () => {
  if (auth0) return await auth0.getTokenSilently();
  return null; // IAP 不需要前端传 Token (由 Cookie 处理)
};

export const getUser = async () => {
  if (auth0) return await auth0.getUser();
  return null;
};

4. 修改 API 调用 (src/services/api.ts)

在发送请求前,获取 Token 并注入 Header。

typescript 复制代码
import { getToken } from './auth';

// ... inside functions
const token = await getToken();
const headers: HeadersInit = {
  'Content-Type': 'application/json',
};
if (token) {
  headers['Authorization'] = `Bearer ${token}`;
}

const response = await fetch(API_URL, {
  // ...
  headers: headers,
  // ...
});

5. 修改入口 (src/chat-app.ts)

connectedCallback 或初始化逻辑中调用 initAuth(),并检查登录状态。如果未登录且是 Auth0 模式,显示登录按钮或自动跳转。


第三阶段:后端代码修改 (askc-backend)

1. 安装依赖

bash 复制代码
pip install "python-jose[cryptography]"

2. 添加环境变量

src/configs/config.py 和 Helm Values 中添加:

  • AUTH_PROVIDER: iap (Prod) 或 auth0 (Dev)
  • AUTH0_DOMAIN: dev-xyz.us.auth0.com
  • AUTH0_AUDIENCE: https://api.askc.dev

3. 实现 Auth0 验证逻辑 (src/services/auth_service.py)

后端获取用户信息分为两步,都在 auth_service.py 中实现:

  1. 验证 Token (verify_token) : 接收前端发来的 Access Token (JWT),使用 Auth0 的公钥 (JWKS) 验证其签名、有效期 (exp)、签发者 (iss) 和受众 (aud)。这一步只确认 Token 的合法性,不关心其中的用户信息。如果验证失败,则拒绝请求。
  2. 获取用户信息 (get_user_info) : 在 Token 验证通过后,使用该 Token 作为凭证,去调用 Auth0 的 /userinfo API 接口。这个接口会返回与该 Token 关联的用户的完整信息,包括 email, nickname, picture 等。
python 复制代码
from fastapi import HTTPException, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import jwt # or jose
# ... 实现 Verify JWT 逻辑,从 https://{DOMAIN}/.well-known/jwks.json 获取公钥 ...

4. 更新 user_router.py

修改 /me 和其他受保护接口的依赖注入。

python 复制代码
async def get_current_user(
    request: Request, 
    token: HTTPAuthorizationCredentials = Depends(HTTPBearer(auto_error=False))
):
    provider = os.getenv("AUTH_PROVIDER", "iap")
    
    if provider == "auth0":
        if not token:
            raise HTTPException(401, "Missing Bearer Token")
        # 验证 Auth0 Token
        payload = verify_auth0_token(token.credentials)
        # 映射到内部 User 结构
        return {"email": payload["email"], "idp_user_id": payload["sub"], ...}
        
    else:
        # 现有的 IAP 逻辑
        return get_current_user_from_iap(request)

第四阶段:基础设施配置修改

1. 修改 Helm Values (helm/values-dev.yaml)

为 Dev 环境配置环境变量,并关闭 IAP。

yaml 复制代码
env:
  AUTH_PROVIDER: "auth0"
  AUTH0_DOMAIN: "dev-xyz.us.auth0.com"
  AUTH0_AUDIENCE: "https://api.askc.dev"

# 关键:关闭 IAP,因为我们改用应用层验证
iap:
  enabled: false 

2. 修改 Cloud Build (cloudbuild-askc-ui-dev.yaml)

注入前端构建参数。

yaml 复制代码
args:
  - '--build-arg'
  - 'VITE_USE_AUTH0=true'
  - '--build-arg'
  - 'VITE_AUTH0_DOMAIN=dev-xyz.us.auth0.com'
  # ... 其他参数 ...

3. 修改 Gateway (gateway_configs/httproute.yaml)

更新 /askc-ui-dev/askc-bak-svc-dev 的路由规则。

由于 IAP 在 Helm 中被禁用了,Service 名称可能会变回 askc-ui-dev-service (没有 -iap 后缀)。
务必检查部署后的 Service 名称,并更新 HTTPRoute 指向正确的 Service。


第五阶段:部署与验证

  1. 部署后端 : 提交 askc-backend 的 Dev 构建。
  2. 部署前端 : 提交 askc-ui 的 Dev 构建。
  3. 应用路由 : 更新并 Apply httproute.yaml
  4. 测试 :
    • 访问 https://gateway.jpgcp.cloud/askc-ui-dev/
    • 应该会被重定向到 Auth0 登录页(或点击登录按钮)。
    • 使用 GitHub 登录。
    • 登录成功后,前端应能获取 Token 并请求后端 API。

效果

当访问https://gateway.jpgcp.cloud/askc-ui-dev/

时会重定向到auth0登陆页

点结continue with Github 就会重定向到 github登录页, 此处需要魔法

登陆就会返回你的web app

相关推荐
前端小端长17 小时前
项目里满是if-else?用这5招优化if-else让你的代码清爽到飞起
开发语言·前端·javascript
胡萝卜3.017 小时前
现代C++特性深度探索:模板扩展、类增强、STL更新与Lambda表达式
服务器·开发语言·前端·c++·人工智能·lambda·移动构造和移动赋值
AI_567817 小时前
Vue3组件通信的实战指南
前端·javascript·vue.js
烤麻辣烫17 小时前
黑马大事件学习-16 (前端主页面)
前端·css·vue.js·学习
Dragon Wu17 小时前
TanStack Query(React Query) 使用总结
前端·react.js·前端框架·react
鹏多多17 小时前
flutter-使用EventBus实现组件间数据通信
android·前端·flutter
UpgradeLink17 小时前
Electron项目使用electron-updater与UpgradeLink接入参考
开发语言·前端·javascript·笔记·electron·用户运营
程序员祥云17 小时前
技能特⻓回答
前端·面试
xiaoxue..17 小时前
React 新手村通关指南:状态、组件与魔法 UI
前端·javascript·react.js·ui