揭秘 OAuth 2.0 - 教程与入门
OAuth - Oh! Auth。这可能是最令人困惑、难以清晰理解的主题之一。
混淆始于单词本身 O* Auth * ,也许它的意思是身份验证(或)授权?
本入门指南旨在帮助我理解清晰的 OAuth 概念,并解答以下问题:
- 为什么存在 OAuth?
- 我可以使用 OAuth 进行身份验证吗?
- 为什么趋势是社交登录 - 使用谷歌登录等?
- 如何使用 OAuth 及其不同类型。
本文最初发布于https://devansvd.com/oauth。感兴趣的话可以访问一下。
让我们开始吧!
OAuth 解决的问题
想象一下没有 OAuth 的世界,让我们举一个现实世界的例子,假设像打印服务这样的第三方应用程序需要访问存储在您的谷歌驱动器中的照片进行打印。
为了提供此访问权限,您(或)Google 需要与第三方应用程序共享您的 Google 登录凭据(电子邮件/密码)。这样他们才能访问您的照片并进行打印。没错,就是您的 Google 密码。
没人想这样,对吧?他们最终不仅可以访问你的 Google Drive,还可以冒充你,读取你存储的电子邮件、联系人,甚至信用卡/密码,基本上他们就成了你。OAuth就是为了解决这个问题而设计的。
相信我,在OAuth 出现之前的黑暗石器时代,它确实是这么运作的。例如:Yelp.com 要求你提供 Google 凭证,以便访问你存储在 Google 中的联系人,并向你的好友发送邀请。
你自己看看—— “别担心,我们不会保留你的邮箱密码或朋友的地址”。在我看来,这听起来像是虚假的承诺。
什么是 OAuth?
OAuth 2.0是一个授权框架,专门设计用于服务用户可以允许第三方应用程序对其在服务中托管的数据进行有限的访问,而无需向第三方应用程序透露其用户名和密码凭据。
它允许第三方在征得用户同意的情况下对其数据进行有限的访问,这通常类似于代表用户访问,通常称为委托访问。
OAuth 2.0 - RFC 6749明确指出它是一个授权框架。因此不应将其用于身份验证。尽管由于其便捷性,许多人还是开始使用它进行身份验证。我们将详细讨论为什么不应该将其用于身份验证,目前我们只需了解它不应该用于身份验证即可。
身份验证与授权
要理解 OAuth,需要知道身份验证和授权之间的区别。
- 身份验证 = 登录名 + 密码(您是谁)
- 授权 = 权限(允许你做什么,这就是 OAuth 的作用所在)
OAuth 如何解决这个问题?
OAuth 提供了一种授权机制,可以对受保护的 http 资源中的“允许执行的操作”进行细粒度的控制。最棒的是,它可以随时撤销。
OAuth 框架针对不同用例指定了多种授权类型。以下列出了最常见的 OAuth 授权类型。
此外,它还提供了一种定义附加类型的扩展机制,这意味着它可以根据需要进行扩展。
注意:经过几年的使用,有人发现授权码授予在与公共客户端类型一起使用时容易受到授权码拦截攻击。
为了克服这个问题,引入了RFC 7636 - 带有 PKCE(OAuth 公共客户端代码交换的证明密钥)的授权码授予,发音为“pixy”,现在只知道 pixy 存在。
一些 OAuth 技术术语
在开始之前,需要熟悉一些你经常听到的 OAuth 技术术语。使用 OAuth 通常涉及四个参与方或角色。
- 资源所有者(最终用户)
- 资源服务器(Google Drive)
- 客户端(第三方应用程序 - 打印服务)
- 授权服务器(Google身份验证服务器)
基本协议流程
OAuth协议的抽象如下,这样就解决了上述问题。
为了让客户端(第三方)访问受保护的资源(谷歌驱动器照片),
- 首先,客户端向资源所有者(最终用户)请求授权,
- 假设资源所有者(最终用户)批准授权请求,客户端收到的授权授予取决于客户端(第三方)使用的授予类型方法。
- 然后,客户端(第三方)通过向授权服务器(Google 身份验证服务器)出示收到的授权许可来请求访问令牌
- 授权服务器(Google 身份验证服务器)验证客户端并向客户端(第三方)授予访问令牌
- 客户端(第三方)使用访问令牌来访问资源服务器(谷歌驱动器)中的受保护资源。
请参阅每种授权类型流程,了解每种流程的具体工作方式。
如何使用
要使用 OAuth,首先需要通过提供客户端名称、客户端类型、服务意图和用途、重定向 URL 等向 OAuth 服务器注册客户端(第三方服务)。
客户端注册成功后,OAuth 服务器会向您提供两件事。
- 客户端 ID - 可以公开显示。
- 客户机密 - 顾名思义,必须保密且安全。
客户端类型
注册客户端(第三方服务)时,需要指定客户端类型:公共(或)机密。
- 机密(基于服务器且访问受限)
- 公开(最终用户 - 基于浏览器,本机应用程序)
注意:如果是保密客户端,则客户端 ID 和客户端密钥均为必填项,必须在请求中传递。如果是公开客户端,则只需在请求中传递客户端 ID 即可。
技术术语已经足够了,让我们详细看看每种补助类型是如何运作的,不想用理论解释来烦扰你,适当的流程图加上现实世界的例子,参考图像。
授权码授予
- 基于重定向的流需要与资源所有者用户代理(通常是浏览器或本机应用程序)进行交互。
- 支持访问令牌和刷新令牌
客户端应用程序向授权服务器的授权端点发出授权请求。资源所有者成功批准后,会在 URL 中收到一个短期授权码。然后,客户端通过向授权服务器的令牌端点提交授权码来请求访问令牌。客户端收到访问令牌后,使用该令牌访问资源服务器中受保护的资源。
请求授权端点
GET - /authorize {Authorization Endpoint}
?response_type=code // - Required
&client_id={Client ID} // - Required
&redirect_uri={Redirect URI} // - Conditionally required
&scope={Scopes} // - Optional
&state={Arbitrary String} // - Recommended to prevent csrf
HTTP/1.1
HOST: {Authorization Server}
授权端点的成功响应
HTTP/1.1 302 Found
Location: {Redirect URI}
?code={Authorization Code} // - Always included usually expires in 10 mins, Single time use
&state={Arbitrary String} // - Included if the authorization request included 'state'.
授权端点的错误响应
HTTP/1.1 302 Found
Location: {Redirect URI}
?error={Error} // Included
&error_description={Error Description} // Optional
&state={Arbitrary String} // - Included if the authorization request included 'state'.
错误可能是以下任一情况
invalid_request
unauthorized_client
access_denied
unsupported_response_type
invalid_scope
server_error
temporarily_unavailable
请求令牌端点
POST - /token {Token Endpoint} HTTP/1.1
Host: {Authorization Server}
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {Base64 encoded client_id:client_secret} // Required if confidential client
grant_type=authorization_code // - Required
&code={Authorization Code} // - Required
&redirect_uri={Redirect URI} // - Required if the authorization request included 'redirect_uri'.
&client_id={Client Id} // - Required both for public and confidential clients
&client_secret={Client Secret} // - Required for confidential client
注意:如果客户端类型为“公共”,则请求正文中必须包含 client_id。如果客户端类型为“机密”,则授权标头中必须包含 client_id 和 client_secret,根据 OAuth 服务器的不同,请求正文中可能会传递 base64 编码的 client_id:client_secret 对(或)。
建议在授权标头中使用 client_id 和 client_secret,而不是请求正文。
来自令牌端点的响应
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "{Access Token}", // - Always included
"token_type": "{Token Type}", // - Always included
"expires_in": {Lifetime In Seconds}, // - Optional
"refresh_token": "{Refresh Token}", // - Optional
"scope": "{Scopes}" // - Mandatory if granted scopes differ from the requested ones.
}
授权码授予示例
访问 Keycloak OAuth 服务器授权码授予流程的工作示例:开放授权码授予示例
使用 PKCE 授予授权码
此流程是授权授予流程的扩展。经过几年的使用,有人发现授权码授予在与公共客户端类型一起使用时容易受到授权码拦截攻击,因为公共客户端没有客户端密钥。
为了克服这个问题,引入了 RFC 7636 - 带有 PKCE(OAuth 公共客户端代码交换的证明密钥)的授权码授予(发音为“pixy”)。
建议所有客户端也在此流程中使用 PKCE 扩展,以提供更佳的安全性。有关此攻击工作原理的详细说明,请观看此YouTube 视频。
PKCE 救援
- 您的应用需要生成一个code_verifier(43 - 128 个字符的字符串)
- 请记住,会话的一部分需要存储在某处。
- 使用该code_verifier生成code_challenge
code_challenge = SHA256(code_verifier) //S256
code_challenge = code_verifier //PLAIN, not recommended
- 在授权请求中 包含code_challenge和code_challenge_method
GET /authorize?client_id=...&scope=...&response_type=code&redirect_uri=customURL &code_challenge=base64url(code_challenge)&code_challenge_method=S256
- 在令牌交换请求中 包含code_verifier :
POST /token client_id=...&redirect_uri=...&code=acode&code_verifier=verifier
请求授权端点
GET - /authorize {Authorization Endpoint}
?response_type=code // - Required
&client_id={Client ID} // - Required
&redirect_uri={Redirect URI} // - Conditionally required
&scope={Scopes} // - Optional
&state={Arbitrary String} // - Recommended to prevent csrf
&code_challenge={Challenge} // - PKCE Protection
&code_challenge_method={Method} // - PKCE Protection - S256 or PLAIN
HTTP/1.1
HOST: {Authorization Server}
授权端点的成功响应
HTTP/1.1 302 Found
Location: {Redirect URI}
?code={Authorization Code} // - Always included usually expires in 10 mins, Single time use
&state={Arbitrary String} // - Included if the authorization request included 'state'.
授权端点的错误响应
HTTP/1.1 302 Found
Location: {Redirect URI}
?error={Error} // Included
&error_description={Error Description} // Optional
&state={Arbitrary String} // - Included if the authorization request included 'state'.
错误可能是以下任一情况
invalid_request
unauthorized_client
access_denied
unsupported_response_type
invalid_scope
server_error
temporarily_unavailable
请求令牌端点
POST - /token {Token Endpoint} HTTP/1.1
Host: {Authorization Server}
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {Base64 encoded client_id:client_secret} // Required if confidential client
grant_type=authorization_code // - Required
&code={Authorization Code} // - Required
&redirect_uri={Redirect URI} // - Required if the authorization request included 'redirect_uri'.
&code_verifier={Verifier} // - Required if the authorization request included 'code_challenge'.
&client_id={Client Id} // - Required both for public and confidential clients
&client_secret={Client Secret} // - Required for confidential client
注意:如果客户端类型为“公共”,则请求正文中必须包含 client_id。如果客户端类型为“机密”,则授权标头中必须包含 client_id 和 client_secret,根据 OAuth 服务器的不同,请求正文中可能会传递 base64 编码的 client_id:client_secret 对(或)。
建议在授权标头中使用 client_id 和 client_secret,而不是请求正文。
来自令牌端点的响应
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "{Access Token}", // - Always included
"token_type": "{Token Type}", // - Always included
"expires_in": {Lifetime In Seconds}, // - Optional
"refresh_token": "{Refresh Token}", // - Optional
"scope": "{Scopes}" // - Mandatory if granted scopes differ from the requested ones.
}
使用 PKCE 授权码授予示例
访问 Keycloak OAuth 服务器的 PKCE 授权码授予流程工作示例:使用 PKCE 示例打开授权码授予
隐性授予
- 访问令牌将直接作为 Url 片段接收(https://domain.com#access_token)
- 无需授权流程等中间步骤
- 这些客户端通常使用 JavaScript 等脚本语言在浏览器中实现。
- 不建议使用隐式流程(有些服务器完全禁止这种流程),因为在 HTTP 重定向中返回访问令牌时存在固有风险,并且没有确认客户端是否已收到该令牌。
客户端应用程序向授权服务器的授权端点发出授权请求。资源所有者批准后,客户端将直接在 URL 中以 URL 片段的形式接收访问令牌。客户端使用访问令牌来访问资源服务器中受保护的资源。
隐式流程是一种简化的 OAuth 流程,以前推荐用于本机应用程序和 JavaScript 应用程序,其中访问令牌会立即返回,而无需额外的授权码交换步骤。
请求授权端点
GET - /authorize {Authorization Endpoint}
?response_type=token // - Required
&client_id={Client ID} // - Required
&redirect_uri={Redirect URI} // - Conditionally required
&scope={Scopes} // - Optional
&state={Arbitrary String} // - Recommended to prevent csrf
HTTP/1.1
HOST: {Authorization Server}
授权端点的成功响应
HTTP/1.1 302 Found
Location: {Redirect URI}
#access_token={Access Token} // - Always included
&token_type={Token Type} // - Always included
&expires_in={Lifetime In Seconds} // - Optional
&state={Arbitrary String} // - Included if the request included 'state'.
&scope={Scopes} // - Mandatory if granted scopes differ from the requested ones.
授权端点的错误响应
HTTP/1.1 302 Found
Location: {Redirect URI}
?error={Error} // Included
&error_description={Error Description} // Optional
&state={Arbitrary String} // - Included if the authorization request included 'state'.
错误可能是以下任一情况
invalid_request
unauthorized_client
access_denied
unsupported_response_type
invalid_scope
server_error
temporarily_unavailable
隐式授予示例
访问 Keycloak OAuth 服务器隐式授权流程的工作示例:打开隐式授权流程示例
资源所有者密码凭证授予
- 仅在与客户端有信任关系时使用,例如设备操作系统或高权限应用程序
- 授权服务器在启用此授权类型时应特别小心,并且仅在其他流程不可行时才允许它。
- 不建议再使用这笔补助金。
资源所有者向客户端提供用户名和密码,客户端通过包含用户名、密码、client_id 和 client_secret 的令牌端点向授权服务器请求访问令牌。授权服务器验证请求后提供访问令牌。客户端使用此访问令牌获取受保护资源的访问权限。
请求令牌端点
POST - /token {Token Endpoint} HTTP/1.1
Host: {Authorization Server}
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {Base64 encoded client_id:client_secret} // Required if confidential client
grant_type=password // - Required
&username={Username} // - Required
&password={password} // - Required
&client_id={Client Id} // - Required both for public and confidential clients
&client_secret={Client Secret} // - Required for confidential client
注意:如果客户端类型为“公共”,则请求正文中必须包含 client_id。如果客户端类型为“机密”,则授权标头中必须包含 client_id 和 client_secret,根据 OAuth 服务器的不同,请求正文中可能会传递 base64 编码的 client_id:client_secret 对(或)。
建议在授权标头中使用 client_id 和 client_secret,而不是请求正文。
来自令牌端点的响应
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "{Access Token}", // - Always included
"token_type": "{Token Type}", // - Always included
"expires_in": {Lifetime In Seconds}, // - Optional
"refresh_token": "{Refresh Token}", // - Optional
"scope": "{Scopes}" // - Mandatory if granted scopes differ from the requested ones.
}
资源所有者密码凭证授予示例
访问 Keycloak OAuth 服务器的资源所有者密码凭证授予流程的工作示例:打开资源所有者密码凭证授予示例
客户端凭证授予
- 通常称为机器到机器流,仅由服务器使用。
- 仅限保密客户使用
- 此流程中没有资源所有者交互。
- 规范规定客户端凭证流不应该发出刷新令牌。
客户端通过提供 client_id 和 client_secret 向授权服务器的令牌端点请求访问令牌。如果授权服务器向客户端颁发了有效的访问令牌,则客户端将使用此访问令牌访问资源服务器中受保护的资源。
请求令牌端点
POST - /token {Token Endpoint} HTTP/1.1
Host: {Authorization Server}
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {Base64 encoded client_id:client_secret} // Required if confidential client
grant_type=client_credentials // - Required
&client_id={Client Id} // - Required both for public and confidential clients
&client_secret={Client Secret} // - Required for confidential client
注意:如果客户端类型为“公共”,则请求正文中必须包含 client_id。如果客户端类型为“机密”,则授权标头中必须包含 client_id 和 client_secret,根据 OAuth 服务器的不同,请求正文中可能会传递 base64 编码的 client_id:client_secret 对(或)。
建议在授权标头中使用 client_id 和 client_secret,而不是请求正文。
来自令牌端点的响应
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "{Access Token}", // - Always included
"token_type": "{Token Type}", // - Always included
"expires_in": {Lifetime In Seconds}, // - Optional
"scope": "{Scopes}" // - Mandatory if granted scopes differ from the requested ones.
}
客户端凭证授予示例
访问 Keycloak OAuth 服务器的客户端凭证授予流程工作示例:打开客户端凭证授予流程示例
刷新令牌授予
- 用于刷新过期的访问令牌
当客户端持有的访问令牌过期时,客户端向授权服务器的令牌端点出示刷新令牌并请求新的访问令牌,然后使用此访问令牌来访问资源服务器中受保护的资源。
请求令牌端点
POST - /token {Token Endpoint} HTTP/1.1
Host: {Authorization Server}
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {Base64 encoded client_id:client_secret} // Required if confidential client
grant_type=refresh_token // - Required
&refresh_token={Refresh Token} // - Required
&client_id={Client Id} // - Required both for public and confidential clients
&client_secret={Client Secret} // - Required for confidential client
注意:如果客户端类型为“公共”,则请求正文中必须包含 client_id。如果客户端类型为“机密”,则授权标头中必须包含 client_id 和 client_secret,根据 OAuth 服务器的不同,请求正文中可能会传递 base64 编码的 client_id:client_secret 对(或)。
建议在授权标头中使用 client_id 和 client_secret,而不是请求正文。
来自令牌端点的响应
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "{Access Token}", // - Always included
"token_type": "{Token Type}", // - Always included
"expires_in": {Lifetime In Seconds}, // - Optional
"refresh_token": "{Refresh Token}", // - Optional
"scope": "{Scopes}" // - Mandatory if granted scopes differ from the requested ones.
}
刷新令牌授予示例
访问 Keycloak OAuth 服务器的刷新令牌授予流程工作示例:打开刷新令牌授予流程示例
存在其他补助类型吗?
是的,OAuth 授予类型在设计上是可扩展的。
示例:设备代码授权类型 -urn:ietf:params:oauth:grant-type:device_code.
设备代码授予
假设一台电视需要显示你谷歌云盘中的照片,但它只有遥控器,无法输入登录信息,在这种情况下无法使用任何其他流程。因此,OAuth扩展了设备代码授权,以支持此类机制。设备代码授权类型 -urn:ietf:params:oauth:grant-type:device_code.
这些设备被称为输入约束设备。例如:电视、打印机、扬声器等。
Televison 向授权服务器的设备端点发送设备请求,授权服务器返回唯一的device_code
、user_code
、和。用户需要在其任何设备(例如手机、笔记本电脑、平板电脑等)上访问verification_uri
授权服务器提供的验证网址并输入用户代码 (user_code),然后使用其凭据登录并获得批准。与此同时,Television 应用程序会按照授权服务器指定的间隔持续轮询令牌端点。它会经常看到错误。用户成功登录后,授权服务器的令牌端点会将 access_token 和 refresh_token 返回给 Televison 应用程序。像往常一样,使用 access_token,Television 应用程序可以访问您的 Google Drive 并显示照片。interval
expires_in
authorization_pending
向设备端点发出请求
POST - /device {Device Endpoint} HTTP/1.1
Host: {Authorization Server}
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {Base64 encoded client_id:client_secret} // Required if confidential client
&client_id={Client Id} // - Required both for public and confidential clients
&client_secret={Client Secret} // - Required for confidential client
注意:如果客户端类型为“公共”,则请求正文中必须包含 client_id。如果客户端类型为“机密”,则授权标头中必须包含 client_id 和 client_secret,根据 OAuth 服务器的不同,请求正文中可能会传递 base64 编码的 client_id:client_secret 对(或)。
建议在授权标头中使用 client_id 和 client_secret,而不是请求正文。
来自设备端点的响应
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"device_code": "{Device code}", // - Always included
"user_code": "{User code}", // - Always included
"verification_uri": "{Verification URL}", // - Always included
"interval": 5, // - Always included
"expires_in": 1800 // - Always included
}
轮询令牌端点
POST - /token {Token Endpoint} HTTP/1.1
Host: {Authorization Server}
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {Base64 encoded client_id:client_secret} // Required if confidential client
grant_type=urn:ietf:params:oauth:grant-type:device_code // - Required
&client_id={Client Id} // - Required both for public and confidential clients
&client_secret={Client Secret} // - Required for confidential client
注意:如果客户端类型为“公共”,则请求正文中必须包含 client_id。如果客户端类型为“机密”,则授权标头中必须包含 client_id 和 client_secret,根据 OAuth 服务器的不同,请求正文中可能会传递 base64 编码的 client_id:client_secret 对(或)。
建议在授权标头中使用 client_id 和 client_secret,而不是请求正文。
来自令牌端点的响应
HTTP/1.1 400 Bad Request
{
"error": "authorization_pending"
}
用户登录后来自令牌端点的响应
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "{Access Token}", // - Always included
"token_type": "{Token Type}", // - Always included
"expires_in": {Lifetime In Seconds}, // - Optional
"scope": "{Scopes}" // - Mandatory if granted scopes differ from the requested ones.
}
访问此 URL以了解如何使用 Google 设备代码 API 登录电视。
操场
要快速体验所有 OAuth 授权类型,请访问 OAuth Playground - https://www.oauth.com/playground
OAuth 的问题 - 直接用作身份验证协议
颁发的 access_token 没有关于向谁颁发令牌的信息,即目标受众,也没有确定目标受众是否正确接收令牌的机制 -这有点像将 access_token 或授权码扔过墙。
要存储关于登录用户的信息(例如UserId ),需要额外的 API 调用,这会增加网络延迟。有些系统会使用辅助令牌 (id_token) 或 JWT,其中包含用户拥有的客户端信息(例如UserId )。尽管 OAuth 本身并未对此进行任何定义。
然而,一些人开始使用 OAuth 2.0 进行身份验证(而不是授权),并且 OAuth 身份验证迅速流行起来。
从 OpenID 团队的角度来看,基于 OAuth 的身份验证不够安全,但他们不得不承认,人们更喜欢 OAuth 身份验证。因此,OpenID 团队决定在 OAuth 2.0 的基础上定义一个新的规范——OpenID Connect。
是的,这让人们更加困惑了。
有关为什么不应该使用 OAuth 进行身份验证的更多陷阱,请转到oauth.net 常见陷阱。
根据建议 - 建议仅将 OAuth 用于授权目的,而不是用于身份验证。对于身份验证,最好使用专门为此目的构建的“OpenID Connect”。
为什么会出现使用社交账户登录的趋势?
社交登录通常使用 OAuth 标准实现。社交登录提供商看到了机会,他们提供了一种解决方案,让用户无需记住每次访问网站的登录凭据。由于用户已经拥有 Google、Facebook 等提供商的帐户,因此只需使用其选项(使用 Google 登录)即可登录。
优点:
- 无需记住访问过的每个网站的登录凭据。
- 预先验证的电子邮件地址,减少虚假用户帐户的机会。
- 加快注册流程——可以从社交登录返回的个人资料数据中快速获取有关用户的信息,而无需手动输入。
缺点:
- 可能会无意中导致某些图书馆、学校或工作场所出于生产力原因屏蔽社交网络服务的第三方网站变得无用。
- 由于攻击者使用复杂的手段来破解这些身份验证机制,这些登录信息也成为欺诈和账户滥用的新前沿。
我想我可以说这是对 OAuth 的一次实验。
请随意分享您的想法和反馈。
我叫Devan
- Aka devansvd。
参考
- https://tools.ietf.org/html/rfc6749
- https://tools.ietf.org/html/rfc7636
- https://tools.ietf.org/html/rfc8628
- https://oauth.net/2/
- https://medium.com/@darutk/diagrams-and-movies-of-all-the-oauth-2-0-flows-194f3c3ade85
- https://www.youtube.com/watch?v=Gtbm5Fut-j8&list=PLcX_9uDXp_CQuUK3BOddGVqqujZ4nxMPw&index=2
- https://oauth.net/articles/authentication/#common-pitfalls
- http://www.thread-safe.com/2012/01/problem-with-oauth-for-authentication.html
- https://stackoverflow.com/questions/33702826/oauth-authorization-vs-authentication
- https://stackoverflow.com/questions/6556522/authentication-versus-authorization
- https://en.wikipedia.org/wiki/Social_login
- https://www.youtube.com/watch?v=Ou_nbvl2SXI
- https://alexbilbie.com/2016/04/oauth-2-device-flow-grant