OAuth2.0 & OpenID Connect解析

Introduction

OAuth2是一个授权框架, 可以使一个应用程序获取其他HTTP服务, 比如Facebook, 的用户账号的部分权限。 当一个第三方应用程序想要访问用户账号时, OAuth2会把验证的过程委托给含有用户账号信息的应用程序。OAuth2提供了Web, Desktop applications, mobile devices的授权流。

OAuth Roles

OAuth定义了四种角色:

  • Resource Owner
  • Client
  • Resource Server
  • Authorization Server

Resource Owner(资源拥有者):User
资源拥有者, 即授权应用程序访问他们账号的用户。 应用程序对用户账号的权限为授权后的token中scope字段指定的范围。

Resource / Authorization Server(资源提供者/授权服务器): API
资源提供者提供被保护的用户账号的信息, 授权服务器验证用户(资源拥有者)的身份信息, 然后签发access token给应用程序。

Client(客户端): Application
Client即想要访问用户账号的应用程序。 在应用程序访问用户账号之前, 必须获得用户的授权。

Abstract Protocol Flow

  1. 应用程序请求用户授权访问被保护的用户资源。
  2. 如果用户授权应用程序, 则应用程序会获得一个授权。
  3. 应用程序向授权服务器(authorization server)表明自己的身份以及用户的授权并请求access token。
  4. 如果应用程序的身份验证通过并且用户的授权有效, 则授权服务器(authorization server)会签发一个access token给应用程序, 授权完成。
  5. 应用程序向资源服务器(resource server)发起请求并展示access token。
  6. 如果access token有效, resource server会提供被保护的资源给应用程序。

在使用OAuth之前, 必须向Authorization Server注册应用程序(application), 注册时需要提供Application name, Application Website, Redirect URI or Callback URL.

应用程序注册完成后, Authorization Server会生成客户端账号信息(client identifier和client secret)。 Client ID是一个公共的字符串被service用来唯一区别应用程序, 以及被用来构建authorization URL; Client secret被用来当应用程序请求访问用户账号时验证应用程序的身份, client secret不能被公开。

Authorization Grant

OAuth2定义了四种授权类型:

  • Authorization Code: 应用于server-side应用程序
  • Implicit: 应用于手机App或Web应用程序
  • Resource Owner Password Credentials: 应用于可信应用程序
  • Client Credentials: 应用于应用程序API访问

Authorization Code
授权类型authorization code是使用最广泛的因为它是面向服务端应用, 并且源代码不会公开, 因此不会暴露client secret。 它是基于重定向的, 表明应用程序必须可以和用户代理交互并接受通过用户代理展示的授权码。

授权过程如下:

  1. 应用程序发起授权请求
    授权请求链接类似:
https://cloud.digitalocean.com/v1/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read
  1. 用户授权应用程序
  2. Authorization Server生成授权码
    用户点击"Authorize Aplication" 授权应用程序后, Authorization server会重定向用户代理到应用程序注册时指定的重定向url, 重定向链接中包含授权码:
https://dropletbook.com/callback?code=AUTHORIZATION_CODE
  1. 应用程序使用授权码请求Access Token
    应用程序通过API访问请求access token, 请求携带授权码(authorization code)以及client secret, API类似如下:
https://cloud.digitalocean.com/v1/oauth/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=CALLBACK_URL
  1. Authorization Server生成Access Token
    如果验证通过, API会返回access token给应用程序, 结果类似如下:
{"access_token":"ACCESS_TOKEN","token_type":"bearer","expires_in":2592000,"refresh_token":"REFRESH_TOKEN","scope":"read","uid":100101,"info":{"name":"Mark E. Mark","email":"mark@thefunkybunch.com"}}

接下来应用程序就已经被授权了, 应用程序访问被保护用户账号时必须携带access token, 所具有的的权限限定于scope指定的范围。
如果同时返回的还有refresh token, 则当access token过期时可以请求生成新的access token。

Implicit
适用于手机应用或web应用(运行于浏览器中的应用), 这个场景下client secret的安全性得不到保障。这个也是基于重定向的。 这个过程不会验证应用程序的身份, 而是依赖重定向URL验证应用程序的身份。
这个授权方式不支持refresh token。

授权过程:

  1. 应用程序发出授权请求, 这个授权请求链接类似授权码的授权链接, 除了这个请求的是token而不是code
https://cloud.digitalocean.com/v1/oauth/authorize?response_type=token&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read
  1. 用户授权应用程序
    用户点击同意授权应用程序, 用户必须首先登录被保护的用户账号。
  2. 用户代理通过重定向URI接收access token
    用户点击同意授权后, Authorization server会重定向用户代理到应用程序制定的重定向URI并且包含access token
https://dropletbook.com/callback#token=ACCESS_TOKEN
  1. 用户代理跟随重定向URI但是保留access token, 之后应用程序从URL重取出access token。

Resource Owner Password Credentials
用户直接提供被保护的用户账号的账号密码给应用程序, 应用程序使用这个账号信息去获取access token。这种授权方式应当仅在其他方式不能使用的时候使用。 并且应该只在可信的应用程序中使用, 比如Authorization server中的程序。
授权链接通常如下:

https://oauth.example.com/token?grant_type=password&username=USERNAME&password=PASSWORD&client_id=CLIENT_ID

Client Credentials
这种授权方式使得应用程序可以访问它自己的服务账号, 在应用程序需要更新注册信息时有用, 比如描述信息或重定向URI,或者其他信息。
应用程序向authorization server请求access token并携带client id和client secret。
连接通常如下:

https://oauth.example.com/token?grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET

Access token使用案例:

curl -X POST -H "Authorization: Bearer ACCESS_TOKEN""https://api.digitalocean.com/v2/$OBJECT" 

Refresh token使用案例:

https://cloud.digitalocean.com/v1/oauth/token?grant_type=refresh_token&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&refresh_token=REFRESH_TOKEN

https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2

OAuth Scopes
就是授权页面上app请求的权限,这是开发者写死的权限。

示例access_token:

{  "access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",  "token_type":"bearer", // token类型  "expires_in":3600,// 如果token有过期时间,则应该在过期时间内使用token  "refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk", // 获取新的access_token所用,但是implicit grant没有refresh token  "scope":"create"}

https://www.oauth.com/oauth2-servers/access-tokens/access-token-response/

OpenID Connect

OpenID Connect1.0是基于OAuth2.0协议的简单身份层,允许客户端确定已被Authorization Server验证过的终端用户的身份,以及可以以Restful方式获取终端用户的基本资料(basic profile information).

OpenID Connect允许所有类型的客户端,包括Web, mobile, JavaScript客户端。

OpenID Connect和OpenID2.0做了很多相似的工作,但是OpenID Connect是以一种API友好的方式。

AUth1.0a和OpenID2.0集成需要扩展,而OAuth2.0的功能是集成在OpenID Connect协议中的。

一个完整的Open ID Connect的过程如下:

  1. 查找OIDC元信息(通常地址为site/.well-known/openid-configuration)
  2. 执行OAuth流获取id token以及access token
  3. 访问JWKS终点获取JWT签名密钥并且可选择地注册客户端应用
  4. 验证JWT ID token(即上文的id token)
  5. 通过access token访问UserInfo终点获取用户信息
Identity Token

ID token类似于身份证, 是一个标准的JWT格式的由OpenID Provider(OP)提供的字符串。
ID token中包含的内容:

  • 用户的身份,subject(sub)
  • 签发的授权机构(iss)
  • 所属的客户端, audience或者client(aud)
  • 可选包含一个随机数(nonce)
  • 可选包含签发时间(auth_time),以及强度(acr)
  • 签发时间(iat)以及过期时间(exp)
  • 可选包含额外的用户信息, 如名称, 邮箱地址等

ID token由header, body, signature三部分组成, 以点(.)分隔,每部分都经base 64转码过。

OpenID Connect授权流:

  • Authorization code flow: 最普遍使用的情况, 通常使用在传统web应用, 手机app上。首先重定向用户到OP(Open Identity Proider)进行用户验证并授权, 然后后台发送请求获取id token。 这个方法提供了最好的安全性, 因为token不会传送到浏览器中。
  • Implicit flow: 为基于浏览器的, 无后台的app应用。 ID Token直接包含在OP 返回的重定向响应中。
  • Hybrid flow: 很少使用, 允许前台, 后台各自请求token, 是以上两种的组合。

OpenID Authorisation code flow详解
分为两步: 1, 验证用户, 请求用户同意, 获取授权码, 2, 可选地验证客户端, 使用授权码获取token
一、
重定向用户到OAuth2.0的授权端点(authorisation endpoint)验证用户。 OpenID验证请求实际上是OAuth2.0的获取用户信息的授权请求, 通过在scope中包含openid字段。

HTTP/1.1 302 FoundLocation: https://openid.c2id.com/login?          response_type=code          &scope=openid          &client_id=s6BhdRkqt3          &state=af0ifjsldkj          &redirect_uri=https://client.example.org/cb

在OP端检查用户是否已登录, 未登录则提示登录
然后OP会调用客户端应用的redirect_uri并返回authorisation code或者error code

Authorisation code是一个中间码, 客户端应用需要提交这个code到OP获取ID token, 这个可以直接通过后台请求完成, 以避免暴露私密信息和token。
用code交换id token发生在OP的token端点。
Client ID和client secret通过Authorization头部传递, OpenID Connect也支持通过JWT验证。
Token请求通常如下:

POST /token HTTP/1.1Host: openid.c2id.comContent-Type: application/x-www-form-urlencodedAuthorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JWgrant_type=authorization_code &code=SplxlOBeZQQYbYS6WxSbIA &redirect_uri=https://client.example.org/c

如果请求成功, 结果通常是包括ID token, access token和可选的refresh token的json对象。
对于一个基础的OpenID验证请求, 通常只有ID token是需要的, access token可以被忽略, 不过access token也可以用来获取用户的信息, 通过UserInfo端点。

ID token的用途:

  • 无状态的session, 可以放进浏览器的cookie中实现轻量级的无状态的session, 避免了在服务器端存储session的必要。
  • 传递给第三方: 当其他应用活动后台服务需要知道用户的身份信息时, 可以把ID Token传递给它们。
  • Token exchange: 可以使用ID token交换access token. Token exchange使用在分布式应用中。

OpenID well known endpoint
OIDC providers可以支持’well known’端点, 这是一个包含可以让客户端自行配置的json对象, 有些内容不会变化, 有些会定期变化。

https://xxxx.com/.well-known/openid-configuration

一般情况下, 可以使用OpenId Connect替代OAuth2.

https://connect2id.com/learn/openid-connect#example-auth-code-flow-step-1
https://www.onelogin.com/blog/openid-connect-explained-in-plain-english
https://connect2id.com/learn/openid-connect#example-auth-code-flow-step-1

扩展知识:

OpenID Connect Authorization Code Flow
  1. 客户端准备一个验证请求,包括一些用户指定的参数
  2. 客户端发送请求到Authorization Server
  3. Authorization Server验证用户账号,并获取用户的授权后返回Authorization Code
  4. 客户端利用Authorization code向token端点发请求
  5. 客户端收到包括ID Token和Access Token的响应
  6. 客户单验证ID Token,并且获取终端用户的身份标识(Subject Identifier)

验证ID Token和Access Token

ID Token验证

  1. 通过客户端注册时的key和algorithm解密ID Token
  2. 验证iss字段(issuer claim)
  3. 验证aud字段,aud字段必须包含client_id
  4. 如果有多个audience, 响应必须包含azp
  5. 如果有azp字段,值必须是client_id
  6. 其他包括验证alg, iat, nonce等字段

Access Token验证

在使用Authorization Code Flow时,如果ID Token包含at_hash字段,则客户端必须用它取校验Access Token,验证过程和Implicit Flow使用的一样,但是使用的是从Token Endpoint返回的ID Token和Access Token。

  1. 使用ID Token中指定的算法对access_token进行hash
  2. 取hash的左半部分并且base64url encode
  3. at_hash的值必须和第二步算出的值相等
Implicit Authorization Flow
  1. 客户端准备验证请求,包含指定的参数
  2. 客户端发送请求到Authorization Server
  3. Authorization验证用户账号,并且获取用户授权,然后重定向用户到一个指定地址,url里包含ID Token,如果请求参数里指定了需要Access Token,则url里还有Access Token。
  4. 客户端验证ID Token并获取用户身份标识(Subject Identifier)

验证ID Token和Access Token

验证过程和Authorization Code Flow相同

Hybrid Authentication Flow
  1. 客户端准备验证请求,并带有指定的参数
  2. 客户端发送请求到Authorization Server
  3. Authorization验证用户账号并取得用户授权,然后返回给客户端Authorization Code,根据指定的Response Type,也可以有一个或多个其他的参数
  4. 客户端利用Authorization Code向Token Endpoint发送请求,Token Endpoint返回ID Token和Access Token.
  5. 客户端验证ID Token,并取得用户标识

当使用Hybrid Flow验证流程时,Authorization Endpoint的使用和Authorization Code Flow相同,除了一个参数例外:

response_type: Oauth2.0 response_type决定了将使用的验证流程。当使用Hybrid Flow时,response_type值可能为code id_token, code token或者code id_token token.

Hybrid Flow Authorization Endpoint返回的值包括以下这些:

access_token: OAuth2.0 Access Token,当response_type是code token, code id_token token

id_token: ID Token,当response_type是code id_token或者code id_token token

code: Authorization Code, Hybrid Flow总是返回这个。

示例:

GET /authorize?response_type=code id_token&client_id=s6BhdRkqt3&redirect_uri=https://client.example.org/cb&scope=openid profile email&nonce=n-0S6_WzA2Mj&state=af0ifjsldkj HTTP/1.1Host: server.example.com
 HTTP/1.1 302 Found Location: https://client.example.org/cb# code=SplxlOBeZQQYbYS6WxSbIA &id_token=eyJ0 ... NiJ9.eyJ1c ... I6IjIifX0.DeWt4Qu ... ZXso &state=af0ifjsldkj

想必看到这里大家也明白了Hybrid混合的意思。即可以返回多个token和code, code还可以用来向token Endpoint请求access_token。

Id_token和access_token的验证方式和上文一样。

code校验流程:

  1. 使用ID Token头指定的算法hash code的值
  2. 取左边一半的hash值,然后base64url encode
  3. 比较c_hash字段的值必须和上一步算出的结果相同

https://openid.net/specs/openid-connect-core-1_0.htm

来源:https://www.icode9.com/content-4-786201.html

(0)

相关推荐

  • Oauth2详解

    Oauth2详解

  • 面试官问我:如何设计 QQ、微信等第三方账号登陆 ?还要我说出数据库表设计!

    作者:低调的码农链接:https://juejin.im/post/6844903871580471303 名称解释 这里的多账户区别于系统级别的,我们讲的多账户系统是指,在我们互联网应用当中,我们的 ...

  • 第 87 天:Python Web开发 OAuth2.0 简介

    随着互联网的发展,各种应用相互交叉,到处需要用户登录,信息安全成为了不可回避的问题,应用需要扩展,用户需要更好的体验,信息需要更安全的保障,为了满足这些需求,互联网技术不断推陈出新,从通信安全,到各种 ...

  • SAP Commerce Cloud OAuth 实现介绍

    Oauth2 oauth2 core extension 已经取代了 webservicescommons/oauthauthorizationserver 扩展. 它将 HTTP 端点公开为 Aut ...

  • Spring Cloud(6):保护微服务(Security)

    OAuth2是一个授权(Authorization)协议.我们要和Spring Security的认证(Authentication)区别开来,认证(Authentication)证明的你是不是这个人 ...

  • 前后端接口鉴权全解 Cookie/Session/Token 的区别

    今天 作者:ssshooter 不知不觉也写得比较长了,一次看不完建议收藏夹!本文主要解释与请求状态相关的术语(cookie.session.token)和几种常见登录的实现方式,希望大家看完本文后可 ...

  • SAP Commerce Cloud UI 的用户会话管理

    这是 Jerry 2021 年的第 51 篇文章,也是汪子熙公众号总共第 328 篇原创文章. 如无特殊说明,本公众号介绍的 SAP Commerce Cloud UI,均指新一代基于 Spartac ...

  • 一线大厂最新总结Spring Security Oauth2.0认证授权全彩笔记

    Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.由于它是Spring生态系统中的一员,因此它伴随着整个Spring生态系统不断修正. ...

  • 第 88 天:OAuth2.0 客户端实战

    上一次课程,我们了解了 OAuth 认证是怎么回事,以及了解了四种认证方式,今天我们将以 Github 为例,了解一下如何用 Flask 第三方应用 在之前的介绍 JWT 的时候,了解过 Authli ...

  • 镜像技术 OAuth2.0

    镜像技术        集群技术的一种.是将建立在同一个局域网之上的两台服务器通过软件或其他特殊的网络设备,将两台服务器的硬盘做镜像.        其中,一台服务器被指定为主服务器,另一台为从服务器 ...

  • OAuth2.0 基础知识

    Tips:本篇已加入,.Net core 3.1 使用IdentityServer4 实现 OAuth2.0 --阅读目录  . 前言 如果大家英语比较好 可以看下 OAuth2.0官网(https: ...

  • 为什么是0.65?解析产品质量抽样标

    质量工程师之家 昨天 IQC.OQC......,不论什么QC,作为一名质量检验人员,只要上班每天都要抽取样本进行检测,但由于产品的不均质性和传统的抽样方法的不科学性,抽取的样本往往不能真实反映产品全 ...

  • PHP应用:微信公众号OAuth2.0网页授权问题浅析

    <PHP应用:微信公众号OAuth2.0网页授权问题浅析>要点: 本文介绍了PHP应用:微信公众号OAuth2.0网页授权问题浅析,希望对您有用.如果有疑问,可以联系我们. 根据需求,我今 ...

  • 【超强干货!人体头部及五官画法大全】从0开始全方位解析脸部及眼睛、嘴巴、耳朵画法

    [编者言] 每个人物都有不同的头部特征.在绘画中,我们也常运用这些外在特征,比如脸部的轮廓.五官.表情.发型等,来表现一个人物的年龄.身份.性格等.因此,即使画中的人物不像现实中活生生的人一样会说话, ...

  • spark-3.0 application 调度算法解析

    spark 各个版本的application 调度算法还是有这明显的不同之处的.从spark1.3.0 到 spark 1.6.1.spark2.0 到 现在最新的spark 3.0 ,调度算法有了一 ...