Oauth登录

文章目录

OAuth 登录

OAuth 登录,就是让你通过一个已经有的账号(比如

Google、GitHub、OpenAI),授权另一个应用使用某些功能,而不需要把账号密码告诉那个应用

OAuth 的核心是:用户在官方平台确认授权,第三方应用获得有限权限的 Token,而不是拿到用户密码。

OAuth 是一个授权协议

  • 认证(Authentication):确认你是谁。
  • 授权(Authorization):确认你允许某个应用做什么。
    一、OAuth 是什么?

假设你正在使用一个第三方软件 A,它需要访问你的 GitHub 仓库。

通常有两种方式:

方式一:直接提供账号密码

你把 GitHub 的账号和密码告诉软件 A,软件 A 使用你的账号密码访问 GitHub。

问题是:软件 A 知道了你的密码,不安全。

方式二:使用 OAuth 授权

你不需要告诉软件 A 密码,而是:

  1. 软件 A 让你跳转到 GitHub 官方登录页面。
  2. 你在 GitHub 页面登录账号。
  3. GitHub 询问你:「是否允许软件 A 访问你的某些仓库?」
  4. 你点击同意。
  5. GitHub 给软件 A 一个访问凭证(Access Token)。
  6. 软件 A 使用这个凭证访问你授权的 GitHub 资源。 关键区别:软件 A 拿到的是访问凭证,不是你的 GitHub 密码。

OAuth登录完整流程

OAuth 登录和普通登录有什么区别?

举例

OAuth 授权码模式(Authorization Code Flow)的核心就是:

MyAgent 先告诉 OpenAI 自己是哪个应用、想要什么权限、授权后回到哪里 → 用户在 OpenAI 登录并同意授权 → 浏览器把授权码交给 MyAgent → MyAgent 使用授权码和 PKCE 验证材料换取 Access Token → MyAgent 使用 Token 调用获准的服务->Token过期后用 Refresh Token 换新的
用一个完整场景解释: 你开发了一个 MyAgent,用户希望通过自己的 ChatGPT

账号登录,让 MyAgent 使用获得授权的 GPT 模型。(MyAgent 想使用你的 OpenAI 账号,但它不能直接拿你的账号密码,所以它要先去 OpenAI 申请授权。)

OAuth 中的四个角色

  • 用户(Resource Owner)

    就是拥有 ChatGPT 账号的你,决定是否允许 MyAgent 获得访问权限。

  • 客户端(Client)

    就是你开发的 MyAgent。它希望代表用户调用获得授权的服务。

  • 授权服务器(Authorization Server)

    负责用户登录、确认授权、签发授权码及 Token。

  • 资源服务器(Resource Server)

    真正提供 API 服务,例如执行获得授权的 GPT 模型请求。它验证 Access Token 及权限。

整个流程

第一步:MyAgent 发起授权请求

假设你在 MyAgent 中点击「使用 OpenAI 登录」。 MyAgent 就会让浏览器打开: 前面的地址

https://auth.example.com/authorize 是 OpenAI 提供的授权入口(这里是虚构的)。

后面的参数,就是 MyAgent 告诉 OpenAI 的信息。

点击「Login with OpenAI」后,软件让浏览器 打开OpenAI 的 OAuth 授权地址。

例如(以下全部为虚构地址和示例参数):

复制代码
https://auth.example.com/authorize
  ?response_type=code
  &client_id=myagent123
  &redirect_uri=http://127.0.0.1:3000/callback
  &scope=model.access
  &state=xyz789
  &code_challenge=HASH_VALUE
  &code_challenge_method=S256
参数 作用
response_type=code 告诉服务商我要使用授权码模式
client_id 告诉服务商申请授权的是哪个应用
redirect_uri 授权完成后,浏览器应该跳回哪个地址
scope 申请哪些访问权限
state 防止别人伪造授权回调
code_challenge PKCE 验证材料,防止授权码被别人冒用
code_challenge_method=S256 这个结果是通过 SHA-256 计算的

这里有个关键点: 用户还没登录,MyAgent 就已经告诉服务商"我是谁"和"授权完成后该返回哪里"。服务商会根据已注册或支持的客户端信息检查 client_id 和回调地址
response_type=code

意思是:

「OpenAI,我希望你采用授权码模式。用户同意授权后,先给我一个授权码。」

为什么不直接给 Access Token?

因为授权码可以先交给 MyAgent,再由 MyAgent 通过另外一次请求兑换 Access Token,并完成相应的安全验证。

你暂时记住:

  • code:临时授权码。
  • access_token:真正用于访问 API 的凭证。
    client_id=myagent123

这是最重要的参数之一。

假设你开发了一个叫 MyAgent 的应用。

你想让 MyAgent 支持「使用 OpenAI 登录」。

那么通常需要先到 OpenAI 的开发者平台注册你的应用(这里假设平台支持这种注册方式)。

注册后,OpenAI 给你一个编号:

应用名称:MyAgent

应用编号:myagent123

这个编号就是 client_id。

以后 MyAgent 发起授权请求时,带上:

client_id=myagent123

OpenAI 收到请求就知道:

「哦,这是编号为 myagent123 的应用在申请授权。」

注意两点:

第一,client_id 是应用的编号,不是你个人账号的编号。

第二,client_id 不属于密码。 任何人都可能看到这个编号,它不能单独证明请求方一定是合法应用。
redirect_uri=http://127.0.0.1:3000/callback

这个参数告诉 OpenAI:

「用户完成授权以后,请让浏览器跳转到这个地址。」

/callback

是 MyAgent 专门用来接收授权结果的路径。

假设 MyAgent 在你的电脑上启动了一个本地服务,监听 3000 端口。

当你完成登录和授权后,OpenAI 就让浏览器跳转到:

http://127.0.0.1:3000/callback?code=abc123

这样,浏览器就会将授权码送到 MyAgent 的本地服务。


scope=model.access

意思是:

「我想申请哪些权限?」

举个例子:

假设 OpenAI 提供以下权限:

权限(假设) 作用

model.access 调用 AI 模型

profile.read 读取用户基本信息

files.read 读取用户文件

MyAgent 如果只需要调用 AI 模型,就可以申请:

scope=model.access

当然,这些权限名称都是我们假设的。实际有哪些权限,取决于服务商。
state=xyz789

这个参数是为了防止别人伪造授权回调。

假设 MyAgent 发起登录时,随机生成了:

state=xyz789

MyAgent 会把这个值保存在本地。

当 OpenAI 授权完成后,浏览器跳转到:

http://127.0.0.1:3000/callback

?code=abc123

&state=xyz789

MyAgent 收到后就会检查:

自己保存的 state:xyz789

收到的 state: xyz789

两者相同 ✓

如果不一样,就拒绝这次回调。

你可以把 state 理解为 MyAgent 给这一次登录申请设置的随机编号。

注意:真正使用时,每次登录都应该重新随机生成,而不是一直使用 xyz789。
code_challenge=HASH_VALUE

这个参数涉及一个叫 PKCE 的安全机制。

你可以先理解一个问题:

假设 MyAgent 完成授权后,OpenAI 返回:

code=abc123

如果这个授权码被别人偷走了怎么办?

为了降低这个风险,MyAgent 会在发起登录之前做两件事。

第一步:生成一个随机秘密值。

code_verifier = 一长串随机字符

这个值保存在 MyAgent 本地,不会在最初的授权请求中发送出去。

第二步:根据这个秘密值计算一个结果。

code_challenge = SHA256(code_verifier)

这里为方便理解省略了 Base64URL 编码步骤。

MyAgent 把计算结果 code_challenge 告诉 OpenAI。

等到 MyAgent 拿着授权码去换 Access Token 时,还必须提供最初那个 code_verifier。

OpenAI 就能检查:

「这个人提供的秘密值,是否能够计算出之前提交的 code_challenge?」

如果一致,才可能继续发放 Token。

因此,别人即使偷走授权码,如果不知道 code_verifier,一般也无法成功兑换 Access Token。
code_challenge_method=S256

这个参数比较简单。

它告诉 OpenAI:

「我是用 SHA-256 计算 code_challenge 的。」

实际计算方式是:

S256 就是这种计算方式的名称

MyAgent 还没登录,OpenAI 怎么就知道它是谁?

这里其实存在两个不同的身份:

  • 应用身份:MyAgent 是哪个应用?
  • 用户身份:当前是谁在使用 MyAgent?
    这两个身份的确定时间不同。

为什么点击登录会打开浏览器?

因为需要通过 OpenAI 官方控制的网页验证你的身份,并完成授权。

服务商通常通过网页让用户登录和确认授权,所以需要浏览器访问这个网址。

登录界面就是 OpenAI 自己开发的前端页面,浏览器负责把这个页面展示出来。

浏览器输入网址,发送的是什么请求?get

假设你在浏览器地址栏输入:

https://example.com/login 然后按回车。

浏览器通常会自动发送一个 HTTP GET请求:

GET /login HTTP/1.1

Host: example.com

这个请求被发送到 example.com 的服务器。

浏览器通过 GET 向服务器请求网页资源,获取 HTML、CSS、JavaScript 后,由浏览器运行这些前端代码并显示界面。

Nginx 本身没有前端代码,但你可以把打包好的前端代码放在服务器的某个目录下,然后配置 Nginx 去这个目录查找文件。

Nginx 不需要懂 Vue、React,它只需要知道:前端文件存放在哪里,收到请求后应该返回哪个文件。

在 Vue、React 前后端分离架构中,前端代码本身不会直接接收浏览器发出的 HTTP GET 请求。

你可以这样理解:

  • Nginx:接收浏览器发送的 GET 请求。
  • 前端代码(Vue、React):由浏览器下载并执行,负责显示页面、处理用户交互和切换路由。




第二步:用户在服务商页面登录

浏览器打开刚才的授权链接。

你看到的是服务商自己的登录页面,而不是 MyAgent 收集账号密码。

用户完成登录后,服务商知道:

登录的用户:张三

申请授权的应用:MyAgent

申请的权限:model.access(示例)

如果用户同意,服务商就会记录这次授权,并签发一个临时授权码。

这里要注意:登录成功不一定等于授权成功。用户可能拒绝授权,服务商也可能因策略限制而拒绝请求。

第三步:生成授权码,并通过回调返回

假设服务商生成:

Authorization Code = ABC123

它怎么把授权码发给 MyAgent?

答案就是Callback(回调)。

在 OAuth 授权码模式中,授权服务器通常给浏览器返回一个HTTP 重定向响应:

HTTP/1.1 302 Found

Location: http://127.0.0.1:3000/callback?code=ABC123\&state=xyz789

浏览器看到 Location,就自动访问这个地址。

注意:

不是服务商服务器直接给 MyAgent 发一条 TCP消息,而是浏览器按照重定向地址去访问 MyAgent。 如果 MyAgent 在你的电脑上运行,并监听:

127.0.0.1:3000

那么浏览器向这个本地端口发送 HTTP 请求,MyAgent 就可以收到: code = ABC123 state = xyz789

所以回调的本质就是: 授权服务器通知浏览器跳转到应用提前指定的地址,并通过这次跳转把授权结果带回来。

第四步:为什么不直接返回 Access Token?

这是整个 OAuth 设计最重要的安全思想。 假设服务商直接在浏览器跳转 URL 中返回 Access Token:

http://127.0.0.1:3000/callback

?access_token=SECRET_TOKEN 那么一旦这个 Token 因浏览器历史、日志、恶意软件或其他渠道泄漏,攻击者就可能直接拿去请求 API。 所以授权码模式采用两次交换:

第五步:MyAgent 使用授权码换 Token

MyAgent 接收到授权码后,会直接向服务商的 Token Endpoint 发送 HTTPS 请求。

示例:

复制代码
POST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
client_id=myagent123&
code=ABC123&
redirect_uri=http://127.0.0.1:3000/callback&
code_verifier=ORIGINAL_RANDOM_SECRET

其中最重要的是: code=ABC123:证明 MyAgent 已经通过前面的授权流程拿到了授权码。 code_verifier:PKCE

使用的原始随机秘密,证明兑换授权码的客户端掌握了发起授权请求时生成的验证材料。

code_verifier:证明兑换授权码的一方掌握最初生成的 PKCE 秘密值。

第一次用 code_challenge 提前设定验证条件,第二次用 code_verifier 证明自己掌握原始秘密,两次匹配成功,才能通过 PKCE 验证。

对于需要客户端密钥的机密客户端,还需要相应的客户端认证,例如

client_secret。本地 CLI 这种公开客户端通常不能安全地保存一个固定客户端密钥,因此经常使用 PKCE。PKCE 全称是 Proof Key for Code Exchange,中文可以理解为"授权码交换证明机制"。

服务商检查通过后,返回类似: { "access_token": "ACCESS_123", "refresh_token":

"REFRESH_456", "token_type": "Bearer", "expires_in": 3600 }

以上值都只是示例;Refresh Token 不保证每次都下发。 这四个字段分别表示:

字段 意思
access_token 真正调用受保护 API 使用的凭证
refresh_token 用来获取新 Access Token 的凭证
token_type Token 的使用类型,示例是 Bearer
expires_in Access Token 的有效期(单位:秒)

至此,MyAgent 才真正拿到了可用于获授权 API 请求的 Access Token

四、为什么还需要 Refresh Token?

PKCE 又是什么?为什么有授权码还不够?

小测试

Authorization Code 是一次性兑换凭证,Callback 是让授权结果回到应用的机制,Access Token 是访问服务的凭证,Refresh Token 是更新访问凭证的工具,而 PKCE 是保证授权码兑换过程安全的重要机制。

相关推荐
无障碍研究院1 小时前
2026TADC|韩冰、王永兴:解锁座舱无障碍量产落地新范式
人工智能·智能汽车·无障碍
闭包不眠1 小时前
手机拍的证件照怎么压缩到20k?3种方法(2026)
图像处理·人工智能·计算机视觉·智能手机·html
Q一件事1 小时前
岩性含义及石漠化易感性说明
人工智能
lovingsoft2 小时前
AI 开发的软件质量如何保证?一套可落地的 LLM 应用质量工程体系(QA 视角)
人工智能
小易测试笔记2 小时前
如何选择适合的半导体静电放电测试设备,易捷测试 Hanwa中国区代理提供哪些支持?
人工智能
益莱储中国2 小时前
益莱储任命 Vincent Kwa为亚太区副总裁兼总经理
大数据·人工智能
鬼手点金2 小时前
上下文:Agent 的眼睛
java·前端·人工智能·git·深度学习
具身AGI2 小时前
一块远程显卡服务一队机器人,瓶颈不在模型
人工智能·机器人
hzxxxz2 小时前
AI任务分流链路:从3层可验证路由到判断力留痕
人工智能