Basic Concepts

Cookies

  • 一种用于服务器与浏览器交换数据的方式
  • 服务器响应时通过 Set-Cookie 的 HTTP header 写入浏览器
  • 浏览器每次请求自动在 header 中带上 cookies
  • set cookie 时可以设置过期时间、域名、路径、HttpOnly 等条件,满足条件的请求才会带上该 cookie

Session

  • 由于 HTTP 请求是无状态的,需要在多次请求中保持用户状态的话需要额外的数据,这个数据可以是一个随机的字符串(Session ID),这样带有同样 Session ID 的请求就可以被关联为同一个会话
  • Session ID 一般由服务端生成,并保存在服务端,来对每一次的请求进行关联。与客户端的交互可以用 set cookie 的方式实现

Token

客户端发送请求时携带的凭证,用于表明自己的身份(Authentication)

  • 常见 tokens:
    • 随机字符串:通过服务端生成随机字符串(Session ID),然后通过 Set-Cookie 写入客户端的浏览器作为 token 的形式,每次请求会在 header 中的 cookie 带上该 token/session id

    • JWT:一种按照 JWT 通用协议签名过的信息,base64 解码后为 JSON 格式。由于信息经过了签名,有防篡改的功能。

      • Online Debugger

      • 示例:

        {
          "iss": "example.com", # 表示令牌是由 example.com 这个实体发行的
          "sub": "1234567890", # 令牌的主题是用户 ID  "1234567890" 的用户
          "aud": "https://api.example.com", # 令牌的目标接收方
          "exp": 1516239022, # 令牌的过期时间
          "nbf": 1516238422, # 令牌的生效时间
          "iat": 1516237822, # 令牌的发行时间
        
          # 自定义字段,用于传递用户的权限角色、姓名和电子邮件地址等信息
          "role": "admin",
          "name": "John Doe", # 
          "email": "johndoe@example.com",
          "custom_data": {
            "department": "Engineering",
            "team": "Security"
          }
        }
        

OTP (One Time Password)

动态口令,一次有效的验证码机制。最常用的 OTP 为 TOTP(Time-based One-Time Password),通常 30s 一变,服务端和客户端(APP)需提前对齐种子、提前校对时间。在同一时间窗口内,客户端(APP)计算的动态口令(OTP)应与服务端一致,从而通过认证。

MFA (Multi-Factors Authentication)

Multi-Factor Authentication 多因素认证、Two-Factor Authentication 双因素/二次认证,指在登录时需要提供多种身份认证因子,交叉确认访问者身份。由于密码天然的安全弱点,通常用于加强账号+密码登录方式。IDaaS 中支持对账密认证开启短信、邮件或动态令牌(OTP)二次认证。

SSO (Single Sign-On)

单点登录,实现用户在多个应用程序或系统中使用一组 Token 来进行登录

具体流程:

  1. 用户认证:用户首次登录到一个认证中心(Authentication Server),输入用户名和密码。
  2. 令牌生成:认证中心验证用户的凭据,一旦验证成功,将生成一个包含用户身份信息的令牌(Token),如 JSON Web Token(JWT)。
  3. 令牌存储:令牌被存储在用户的本地存储中,如浏览器的 Cookie 或 SessionStorage。
  4. 跨域验证:当用户尝试访问其他与认证中心关联的应用程序时,浏览器会将令牌发送到服务器。
  5. 令牌验证:目标应用程序的服务器将接收到的令牌发送回认证中心进行验证。
  6. 访问授权:如果令牌有效,认证中心将返回一个确认信息,应用程序服务器根据此信息允许用户访问资源。

OAuth 2.0

Open Authorization (开放授权),是一个授权标准协议,可以使第三方应用获得对资源服务的有限访问 应用:用户在访问 A 应用时需要使用 B 应用的数据,通过获取 B 应用的授权 token,授权给 A 应用使用该 token 获取 B 应用的数据

角色

OAuth 2.0 定义了四个角色

  1. 资源所有者(Resource Owner):能够授予对受保护资源访问权限的实体。例如应用的用户是资源的所有者,可以授权其他人访问他的资源。当资源所有者是一个人时,它被称为最终用户。
  2. 资源服务器(Resource Server):存储受保护资源的服务器,能够接受并使用访问令牌来响应受保护的资源请求。就是资源服务器接受 Access Token,然后验证它拥有的权限,最后返回对应的资源。这个资源服务器一般是应用本身。
  3. 授权服务器(Authorisation Server):服务器向客户端(即应用)颁发访问令牌来验证资源所有者并获得授权。即负责颁发 Access Token 的服务器,例如 IDaaS 就是一个授权服务器。
  4. 客户端(Client):需要获取访问令牌以访问资源服务器的应用。经过授权后,授权服务器为客户端颁发 Access Token。后续客户端可以携带这个 Access Token 到资源服务器那访问用户的资源。

模式

  1. 授权码模式(Authorization Code Grant)

    • 流程:
      1. 客户端将用户重定向到服务提供商的授权服务器,并请求授权码。这通常通过发送一个带有客户端标识符、重定向 URI 和响应类型(code)的请求来完成。例如:

        Apache
        https://github.com/login/oauth/authorize?              # 授权服务器地址,例如 github
        client_id=01b478c0264a1fbd7183&                        # 客户端 ID
        redirect_uri=https://stackauth.com/auth/oauth2/github& # 授权成功或失败后的回调地址  
        response_type=code    					               # 使用授权码模式
        scope=user:email&                                      # 表示应用正在请求哪些权限
        state=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx               # 一个随机字符串用来防止 CSRF
        
      2. 用户在服务提供商的授权服务器上登录并授权客户端的请求

      3. 服务提供商验证用户同意后,将授权码发送回客户端指定的重定向 URI。例如

        Apache
        https://stackauth.com/auth/oauth2/github?              # 回调地址
        code=1efc47a278d10a04f88e&                             # 授权码
        state=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx               # 第一步生成的 state ,防止 CSRF
        
      4. 客户端使用授权码和客户端密钥向服务提供商的令牌端点请求访问令牌(Access Token)和刷新令牌

        // Request
        POST 
            code=1efc47a278d10a04f88e&
            client_id=01b478c0264a1fbd7183&
            client_secret=xxxxxx
        
      5. 服务提供商验证授权码和客户端密钥后,发放访问令牌和刷新令牌给客户端

        // Response
        Accept: application/json
        {
          "access_token":"gho_16C7e42F292c6912E7710c838347Ae178B4a",
          "scope":"user:email",
          "token_type":"bearer"
        }
        
      6. 使用服务提供商颁发的访问令牌跟获取到所需的资源,继续自己的业务流程,例如重定向回首页

    • 适用于拥有前端和后端的应用程序
  2. 简化模式(Implicit Grant)

    • 流程
      1. 客户端直接将用户重定向到服务提供商的授权服务器,并请求访问令牌。请求中包含客户端标识符、重定向 URI 和响应类型(token)
      2. 用户在服务提供商的授权服务器上登录并授权客户端的请求。
      3. 服务提供商验证用户同意后,直接将访问令牌发送回客户端指定的重定向 URI,而不是先发送授权码。
    • 适用于纯前端应用程序
  3. 密码模式(Resource Owner Password Credentials Grant)

    • 流程
      1. 客户端直接向服务提供商的令牌端点发送请求,包含客户端标识符、用户用户名和密码。
      2. 服务提供商验证用户凭据后,直接发放访问令牌给客户端。
    • 适用于用户对第三方应用程序高度信任的情况
  4. 客户端凭据模式(Client Credentials Grant)

    • 流程
      1. 客户端直接向服务提供商的令牌端点发送请求,包含客户端标识符和密钥。
      2. 服务提供商验证客户端凭据后,发放访问令牌给客户端。
    • 适用于服务端应用程序之间的授权

OIDC (OpenID Connect)

是一个基于 OAuth 2.0 的认证 + 授权(OAuth 2.0 提供的能力)协议。

在 OAuth 2.0 颁发 Access Token 的基础上,多颁发了一个 ID Token(用户的身份凭证),和 Access Token 是一个随机字符串不同的是,ID Token 是一个 JWT Token 。ID Token 自身包含了一些用户的基本信息,而且由于 JWT 的防篡改性,让客户端不需要再向授权服务器进行身份验证,就能直接用 ID Token 来进行身份验证。

开源项目

如果不想使用 IDaas 服务商的 OIDC 服务,可以自己基于开源项目搭建

IAM (Identity and Access Management)

一般指用于实现 AuthenticationAuthorization 的管理系统

IDaaS

身份即服务,可以看作是 SaaS(软件即服务)和 IAM(身份和访问管理)的结合

服务商

Auth0

Demo

  1. 下载 Demo 项目
  2. 修改配置 auth_config.json 中的 domainclientId,在 Default App -> Settings -> Basic Information 中
  3. 修改 App 配置中的 Application URIs -> Allowed Callback URLs/Allowed Logout URLs/Allowed Web Origins 为 http://localhost:3000
  4. 修改 Application Properties -> Application Type 为 Single Page Application
  5. 修改 Credentials -> Application Authentication -> Authentication Method 为 None
  6. 运行项目,npm install && npm run serve

问题:

References