ORY Hydra项目详解

Hydra项目介绍

Hydra介绍
ORY Hydra是经过强化,经过OpenID认证的OAuth 2.0服务器和OpenID Connect提供商,针对低延迟,高吞吐量和低资源消耗进行了优化。ORY Hydra 不是身份提供者(用户注册,用户登录,密码重置流程),而是通过登录和同意应用程序连接到您现有的身份提供者。以不同的语言实现登录和同意应用程序很容易,并且提供了示例性的同意应用程序(Go,Node)和 SDK。

1 代码下载

Hydra源码地址下载

2 初始数据库

2.1 编译项目成main.exe

进入到hydra项目根目录执行下面命令,会生成一个可执行文件main.exe

go build main.go

2.2 初始化数据库

进入到hydra项目根目录执行

2.2.1 用Navicat创建一个数据库hydra

在这里插入图片描述

2.2.2 进行hydra项目数据迁移

输入对应的数据库连接信息进行数据迁移

main.exe migrate sql mysql://root:admin@tcp(127.0.0.1:3306)/hydra

2.2.3 在Navicat查看是否迁移成功

在这里插入图片描述

3 config.yaml详解

# ORY Hydra 项目配置文件

# !!警告!! 此配置文件仅用于文档目的。不要在生产中使用它。作为所有配置项。

# ORY Hydra可以使用配置文件和使用`--config path/to/config.yaml`传递文件位置进行配置。
# 默认情况下,ORY Hydra将查找并加载文件 ~/.hydra.yaml。所有配置键也可以使用环境变量来设置。

##   设置环境变量介绍开始   ##
# 设置环境变量很容易:
## Linux / OSX
#
# $ export MY_ENV_VAR=foo
# $ hydra ...
#
# 或者:
# $ MY_ENV_VAR=foo hydra ...
#
## Windows
#
### 打开命令提示符
#
# > set MY_ENV_VAR=foo
# > hydra ...
#
### Powershell
#
# > $env:MY_ENV_VAR="foo"
# > hydra ...
#
## Docker
#
# $ docker run -e MY_ENV_VAR=foo oryd/hydra:...
#
##  设置环境变量介绍结束   ##

# 假设配置布局如下:
#
# serve:
#   public:
#     port: 4444
#     something_else: foobar
#
# 键“something_else”可以通过在其路径上加上标记设置为环境变量:
#   `serve.public.port.somethihng_else` -> `SERVE.PUBLIC.PORT.SOMETHING_ELSE`
# 和替换 `.` with `_`:
#   `serve.public.port.somethihng_else` -> `SERVE_PUBLIC_PORT_SOMETHING_ELSE`
#
# 环境变量总是重写配置文件中的值。以下是更多的例子:
#
# Configuration key | Environment variable |
# ------------------|----------------------|
# dsn               | DSN                  |
# serve.admin.host  | SERVE_ADMIN_HOST     |
# ------------------|----------------------|
#
#
# 清单项目,例如
#
# secrets:
#   system:
#     - this-is-the-primary-secret
#     - this-is-an-old-secret
#     - this-is-another-old-secret
#
# 在使用环境变量时,必须使用','分隔。相当于代码部分#的环境变量 以上是:
#
# Linux/macOS: $ export SECRETS_SYSTEM=this-is-the-primary-secret,this-is-an-old-secret,this-is-another-old-secret
# Windows: > set SECRETS_SYSTEM=this-is-the-primary-secret,this-is-an-old-secret,this-is-another-old-secret

# 日志配置日志记录器
log:
 # 设置日志级别,参数支持 "panic", "fatal", "error", "warn", "info" and "debug".默认"info"级别
  level: info
  # 设置日志格式。未定义基于文本的日志格式,或设置为JSON格式。
  format: json

# 服务控制http(s)守护进程的配置
serve:
  # 公共控制为公共API端点服务的公共守护进程,比如 /oauth2/auth, /oauth2/token, /.well-known/jwks.json
  public:
    # 公共API端点服务监听的端口号,默认是4444
    port: 4444
    # 接口或 Unix socket ory Hydra应该侦听并处理公共API请求。
    # 使用前缀“unix:”指定unix socket的路径。 在所有接口上留下空的侦听器。
    host: localhost # 在默认的所有设备上,请将此删除或空以侦听
    # host: unix:/path/to/socket

    # Cors为公共端点配置跨域资源共享。
    cors:
      # 将启用的设置为true以启用CORS。默认为false。
      enabled: true
     # allowed_origins是一个可以执行跨域请求的起源列表(逗号分隔值)。
     # 如果清单中有特殊的*值,则将允许所有起源。原点可以包含一个通配符(*)来替换0个或更多个字符(即。http://*.domain.com)。
     # 每个起源只能使用一个通配符。如果为空或未定义,则默认为‘*’,允许来自每个域的CORS(如果启用CORS:true)。
      allowed_origins:
        - https://example.com
        - https://*.example.com
      #允许方法是允许用户代理与跨域一起使用的HTTP方法列表请求。默认为列出的方法。
      allowed_methods:
        - POST
        - GET
        - PUT
        - PATCH
        - DELETE

      # 允许客户端在跨域请求中使用的非简单标头列表。默认为列出的值。
      allowed_headers:
        - Authorization
        - Content-Type

      # 设置哪些标题(逗号分隔的值)安全地公开给CORSAPI规范的API。默认为列出的值。
      exposed_headers:
        - Content-Type

      #设置请求是否可以包括用户凭据,如cookie、HTTP身份验证或客户端SSL证书。默认为true
      allow_credentials: true
      # 设置可以缓存飞行前请求的结果的时间(以秒为单位)。
      # 如果设置为0,每个请求在之前有一个飞行前请求。默认为0。
      max_age: 10

      # 如果设置为true,则添加额外的日志输出以调试服务器端CORS问题。默认为false。
      debug: true

    # 公共服务器的访问日志配置。
    access_log:
      # 禁用健康端点的访问日志。
      disable_for_health: false

      # admin控制为adminAPI端点服务的admin守护进程,如 /jwk, /client, ...
  admin:
    # admin API端点服务监听的端口号,默认是4445
    port: 4445
    # 接口或unix套接字ory Hydra应该侦听并处理管理API请求。
    #使用前缀"unix"指定unix套接字的路径。在所有接口上留下空的侦听器。
    host: localhost # 省略或空听所有的设备,这是默认的。
    # host: unix:/path/to/socket

    # cors配置 Cross Origin资源共享的admin端点.
    cors:
      # 将启用的设置为true以启用CORS。默认为false。
      enabled: true
      # allowed_origins是可以从中执行跨域请求的源(逗号分隔值)列表。
      #如果列表中存在特殊*值,则允许所有原点。原点可以包含通配符(*)
      #替换0个或多个字符(即:http://*.domain.com)。每个原点只能使用一个通配符。
      # 如果为空或未定义,则默认为“*”,允许来自每个域的CORS(如果CORS.enabled:true)。
      allowed_origins:
        - https://example.com
        - https://*.example.com
      # allowed_methods是允许用户代理跨域使用的HTTP方法的列表请求。默认为 GET and POST.
      allowed_methods:
        - POST
        - GET
        - PUT
        - PATCH
        - DELETE

      #允许客户端用于跨域请求的非简单头列表。默认为列出的值。
      allowed_headers:
        - Authorization
        - Content-Type

      # 设置哪些头(逗号分隔值)可以安全地公开给CORS API规范的API。默认为列出的值。
      exposed_headers:
        - Content-Type

    #设置请求是否可以包括用户凭据,如cookies、HTTP身份验证或客户端SSL证书。
      allow_credentials: true
      #设置可以缓存飞行前请求的结果的时间(秒)。如果设置为0,则每个请求在飞行前请求。默认为0。
      max_age: 10

      # 如果设置为true,则会向调试服务器端CORS问题添加其他日志输出。默认为false。
      debug: true

    # 管理服务器的访问日志配置。
    access_log:
      # 禁用健康终结点的访问日志。
      disable_for_health: false

  # tls配置HTTPS(HTTP over tls)。如果已配置,服务器将自动支持HTTP/2。
  tls:
    # 密钥配置私钥(pem编码)
    key:
      # 密钥可以从文件加载:生成秘钥网站 https://www.selfsignedcertificate.com/
      path: ./docs/hydra_private.key
      # 或来自base64编码(不带填充)字符串:
      #base64: LS0tLS1CRUdJTiBFTkNSWVBURUQgUFJJVkFURSBLRVktLS0tLVxuTUlJRkRqQkFCZ2txaGtpRzl3MEJCUTB3...

    # cert configures the TLS certificate (PEM encoded)
    cert:
      # 证书可以从文件中加载:生成秘钥网站 https://www.selfsignedcertificate.com/
      path: ./docs/hydra_certificate.cert
      # 或来自base64编码(不带填充)字符串:
      #base64: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tXG5NSUlEWlRDQ0FrMmdBd0lCQWdJRVY1eE90REFOQmdr...

    #白名单一个或多个CIDR地址范围,并允许他们终止TLS连接。
    #请注意,必须设置X-Forwarded-Proto头,并且除了您的代理/网关/负载平衡器。支持ipv4和ipv6。
    #
    # 当设置此选项时,Hydra提供http而不是https。
    # 有关更多信息,请访问:https://www.ory.sh/docs/hydra/production#tls-termination
    allow_termination_from:
      - 127.0.0.1/32

# dsn设置数据源名称。这将配置ORY Hydra保存数据的后端。
#
## 内存数据库
#
# 如果dsn是“内存”,则数据将写入内存,并在重新启动此实例时丢失。可以使用DSN环境变量设置此值:
#
## SQL数据库
#
# ORY Hydra支持流行的SQL数据库。有关更详细的配置信息,请转到:https://www.ory.sh/docs/hydra/dependencies-environment#sql

#PostgreSQL(推荐)
# 如果dsn以 postgres:// PostgreSQL作为后端存储数据库:连接dsn示例如下
# dsn: dsn=postgres://user:password@host:123/database
#
### MySQL数据库
# 如果dsn以 mysql:// MySQL作为后端存储数据库:连接dsn示例如下
# dsn: mysql://user:password@tcp(host:123)/database


### CockroachDB
# 如果dsn以cockroach:// CockroachDB 作为后端存储数据库:连接dsn示例如下
# dsn: cockroach://user:password@host:123/database
#
dsn: mysql://root:admin@tcp(127.0.0.1:3306)/hydra

# webfinger配置./well-known/settings
webfinger:
  # jwks配置/.well-known/jwks.json端点。
  jwks:
    # 广播密钥是应该在该端点公开的JSON Web密钥列表。这通常是
    #用于验证OpenID Connect ID令牌的公钥。但是,您可能还需要在此处添加其他键。
    broadcast_keys:
      - hydra.openid.id-token # 默认情况下,此密钥始终公开
      # - hydra.jwt.access-token # 当OAuth2访问令牌策略设置为JWT时,将公开此密钥。

  #oidc_discovery配置OpenID Connect discovery(/.well-known/OpenID配置)
  oidc_discovery:
    client_registration_url: https://my-service.com/clients
    # 要广播的受支持声明的列表。始终包括声明“sub”:
    supported_claims:
      - email
      - username
    # 作用域OAuth 2.0客户端可以请求。始终包括作用域“offline”、“offline\u access”和“openid”。
    supported_scope:
      - email
      - whatever
      - read.photos

    # 要在OpenID Connect上公布的userinfo端点的URL发现终结点/.well-known/openid配置。
    # 默认为ORY Hydra的userinfo端点,位于/userinfo。如果要自己处理此终结点,请设置此值。
    userinfo_url: https://example.org/my-custom-userinfo-endpoint

# oidc配置OpenID Connect特性。
oidc:
  # subject_identifiers配置subject Identifier算法。
  # 有关更多信息,请参阅文档:https://www.ory.sh/docs/hydra/advanced#subject-identifier-algorithms
  subject_identifiers:
    # 要启用哪些算法。默认为"public"
    enabled:
      - pairwise
      - public
    # 配置成对算法
    pairwise:
      # 如果启用“成对”,则必须定义 salt属性
      salt: some-random-salt

  #动态客户机注册配置OpenID Connect动态客户机注册(公开为管理端点/clients/…)
  dynamic_client_registration:

    # OpenID Connect动态客户端注册规范没有白名单OAuth 2.0范围的概念。
    # 如果你要公开动态客户端注册,应为新注册的客户端设置启用的默认作用域。
    # 请记住,用户可以通过在注册负载中设置“scope”键来覆盖此默认值,有效地禁用白名单作用域的概念。
    default_scope:
      - openid
      - offline
      - offline_access

urls:
  self:
    # 此值将用作访问和ID令牌中的"issuer"。一定是指定并使用HTTPS协议,除非设置了--dangerous-force-http 。
    # 这通常应该是相等的为了公众的价值。
    issuer: https://localhost:4444/

    # 这是ORY Hydra安装的公共终结点的基本位置。这通常应该是相等的对发行人的价值。
    # 如果未指定,则返回到颁发者值。
    public: https://localhost:4444/

  # 设置login属性为 用户登录和同意流的终结点。默认为内部回退URL。
  login: https://my-login.app/login
  # 设置consent节点属性, 用户登录和同意流的终结点。默认为内部回退URL。
  consent: https://my-consent.app/consent
  # 设置注销终结点。默认为内部回退URL。
  logout: https://my-logout.app/logout
  # 设置错误端点。当发生OAuth2错误而无法发回时,将显示错误页面给客户。默认为内部回退URL。
  error: https://my-error.app/error
  # 当用户代理请求注销时,它将在默认情况下重定向到此url。
  post_logout_redirect: https://my-example.app/logout-successful

strategies:
  scope: DEPRECATED_HIERARCHICAL_SCOPE_STRATEGY
  # 您可以使用JSON Web令牌作为访问令牌。
  # 但说真的。别那么做。这不是一个好主意,有很多警告和微妙的安全影响。阅读更多: https://www.ory.sh/docs/hydra/advanced#json-web-tokens
  #
  #  access_token: jwt

# 配置生存时间
ttl:
  # 配置用户登录和同意流可能需要多长时间。默认为1小时。
  login_consent_request: 1h
  # 配置访问令牌有效的时间。默认为1小时。
  access_token: 1h
  # 配置刷新令牌有效的时间。默认值为720h。设置为-1可使刷新令牌永不过期。
  refresh_token: 720h
  # 配置标识令牌有效的时间。默认为1小时。
  id_token: 1h
  # 配置验证代码有效的时间。默认值为10秒。
  auth_code: 10m

oauth2:
  #如果要与OAuth 2.0客户端共享错误调试信息,请将此设置为true。
  #请记住,在处理错误时,调试信息非常有价值,但也可能会暴露数据库错误、代码和类似错误。默认为false。
  expose_internal_errors: true
  # 配置哈希算法。目前只支持BCrypt
  hashers:
    # 配置用于哈希客户端机密的BCrypt哈希算法。
    bcrypt:
      # 设置BCrypt成本。最小值为4,默认值为10。值越高,CPU时间就越多,用于生成哈希.
      cost: 10
  pkce:
    # 如果希望对所有客户端强制执行PKCE,请将此设置为true。
    enforced: false

# secrets部分配置用于对多个系统进行加密和签名的机密。所有的秘密都可以旋转,
#有关此主题的详细信息,请导航到: https://www.ory.sh/docs/hydra/advanced#rotation-of-hmac-token-signing-and-database-and-cookie-encryption-keys
secrets:
  #系统机密的长度必须至少为16个字符。如果没有提供,将生成一个。
  # 它们是钥匙用于使用AES-GCM(256位)加密敏感数据并验证HMAC签名。
  #列表中的第一项用于签名和加密。整个列表用于验证签名还有解密。
  system:
    - this-is-the-primary-secret
    - this-is-an-old-secret
    - this-is-another-old-secret
  #用于加密cookie会话的机密。默认为secrets.system。建议使用一个单独的生产秘密。
  #列表中的第一项用于签名和加密。整个列表用于验证签名还有解密。
  cookie:
    - this-is-the-primary-secret
    - this-is-an-old-secret
    - this-is-another-old-secret

# 如果已设置,则启用分析。使用“cpu”启用cpu分析,使用“mem”启用内存分析。更多细节在分析时,转到: https://blog.golang.org/profiling-go-programs
profiling: cpu
# profiling: mem

#ORY Hydra支持分布式跟踪。
tracing:
  # 将此设置为要使用的跟踪后端。目前支持jaeger。如果省略或为空,则跟踪将被禁用。
  provider: jaeger
  # 指定要在跟踪程序上使用的服务名称。
  service_name: ORY Hydra
  providers:
    # 配置jaeger跟踪后端。
    jaeger:
      # jaeger代理应将spans发送到的地址
      local_agent_address: 127.0.0.1:6831
      # 跟踪头格式
      propagation: jaeger
      sampling:
        # 要使用的采样器的类型。支持:
        # - const
        # - probabilistic
        # - ratelimiting
        type: const
        # 传递给已配置的采样器类型的值。支持的值:这取决于使用的采样策略:
        # - const: 0 or 1 (全有或全无)
        #  rateLimiting(速率限制):恒定速率(例如,将此设置为3将以每秒3个跟踪的速率采样请求)
        # - rateLimiting: 3
        # 介于0~1之间的值,比如0.5
        # - probabilistic: 0.5
        value: 1.0
        # jaeger代理的HTTP采样服务器的地址
        server_url: http://localhost:5778/sampling

4 启动项目

进入到hydra项目根目录执行以下命令 更多命令请参考main.exe -h

main.exe serve all --config ./docs/config.yaml

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iGC4ckmH-1591889699732)(/img/goImage/hydra3.png)]

5 查看项目接口文档

进入到hydra项目根目录执行以下命令 更多命令请参考swagger -h

swagger serve -F=swagger ./docs/api.swagger.json

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vpuVasOe-1591889699736)(/img/goImage/hydra4.png)]

6 前端项目

hydra-login-consent-node下载

6.1 配置文件说明

绑定后端服务器地址,配置文件位置在hydra-login-consent-node-master/services/hydra.js,如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lNTKKeAG-1591889699740)(/img/goImage/hydra7.png)]

6.2 前端目录结构说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BK5hnfpg-1591889699748)(/img/goImage/hydra8.png)]

7 部分接口说明

7.1 流程图说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FCbz3jQV-1591889699751)(/img/goImage/hydra_flow.png)]

以下是部分接口文档说明,更多请求参数请参考swagger文档说明

7.2 创建Oauth2客户端

7.2.1 接口说明

7.2.2 请求参数说明

请求参数 参数类型 参数说明
client_id 字符串 客户端id
client_name 字符串 客户端名称
client_secret 字符串 客户端秘钥
client_secret_expires_at 字符串 客户端秘钥过期时间
created_at 字符串 客户端创建时间
frontchannel_logout_session_required 字符串 是否注销会话 0否,1是
scope 字符串 客户端作用范围
token_endpoint_auth_method 字符串 令牌终结点身份验证方法
grant_types 字符串 授予类型
response_types 数组 响应类型
…… …… ……

7.2.3 请求参数举例

{
    "client_id":"what-client",
    "client_name":"whatOAuth2.0",
    "client_secret":"what-secret",
    "client_secret_expires_at":0,
    "client_uri":"http://127.0.0.1:5555/callback",
    "created_at":"2020-01-06T15:09:15.946Z",
    "frontchannel_logout_session_required":false,
    "scope":"openid offline offline_access",
    "token_endpoint_auth_method":"client_secret_basic",
    "updated_at":"2020-01-07T15:09:15.946Z",
    "userinfo_signed_response_alg":"none",
    "grant_types": [
    "client_credentials"
  ],
   "response_types": [
    "code"
  ]
}

7.2.4 客户端创建响应示例

{
    "client_id": "what-client",
    "client_name": "whatOAuth2.0",
    "client_secret": "what-secret",
    "redirect_uris": null,
    "grant_types": [
        "client_credentials"
    ],
    "response_types": [
        "code"
    ],
    "scope": "openid offline offline_access",
    "audience": null,
    "owner": "",
    "policy_uri": "",
    "allowed_cors_origins": null,
    "tos_uri": "",
    "client_uri": "http://127.0.0.1:5555/callback",
    "logo_uri": "",
    "contacts": null,
    "client_secret_expires_at": 0,
    "subject_type": "public",
    "token_endpoint_auth_method": "client_secret_basic",
    "userinfo_signed_response_alg": "none",
    "created_at": "2020-01-07T07:30:11Z",
    "updated_at": "2020-01-07T07:30:11Z"
}

7.3 获取Oauth2客户端列表

7.3.1 接口说明

7.3.2 响应示例

[
    {
        "client_id": "auth-code-client",
        "client_name": "",
        "redirect_uris": [
            "http://127.0.0.1:5555/callback"
        ],
        "grant_types": [
            "authorization_code",
            "refresh_token"
        ],
        "response_types": [
            "code",
            "id_token"
        ],
        "scope": "openid offline",
        "audience": [],
        "owner": "",
        "policy_uri": "",
        "allowed_cors_origins": [],
        "tos_uri": "",
        "client_uri": "",
        "logo_uri": "",
        "contacts": [],
        "client_secret_expires_at": 0,
        "subject_type": "public",
        "token_endpoint_auth_method": "client_secret_basic",
        "userinfo_signed_response_alg": "none",
        "created_at": "2020-01-06T03:01:30Z",
        "updated_at": "2020-01-06T03:01:30Z",
        "metadata": null
    },
    {
        "client_id": "bbb-client",
        "client_name": "",
        "redirect_uris": [
            "http://127.0.0.1:3000/login"
        ],
        "grant_types": [
            "authorization_code",
            "refresh_token"
        ],
        "response_types": [
            "code",
            "id_token"
        ],
        "scope": "openid offline",
        "audience": [],
        "owner": "",
        "policy_uri": "",
        "allowed_cors_origins": [],
        "tos_uri": "",
        "client_uri": "",
        "logo_uri": "",
        "contacts": [],
        "client_secret_expires_at": 0,
        "subject_type": "public",
        "token_endpoint_auth_method": "client_secret_basic",
        "userinfo_signed_response_alg": "none",
        "created_at": "2020-01-06T08:22:33Z",
        "updated_at": "2020-01-06T08:22:33Z",
        "metadata": null
    },
    {
        "client_id": "ccc-client",
        "client_name": "",
        "redirect_uris": [],
        "grant_types": [
            "client_credentials"
        ],
        "response_types": [
            "code"
        ],
        "scope": "openid offline offline_access",
        "audience": [],
        "owner": "",
        "policy_uri": "",
        "allowed_cors_origins": [],
        "tos_uri": "",
        "client_uri": "",
        "logo_uri": "",
        "contacts": [],
        "client_secret_expires_at": 0,
        "subject_type": "public",
        "token_endpoint_auth_method": "client_secret_basic",
        "userinfo_signed_response_alg": "none",
        "created_at": "2020-01-06T09:29:16Z",
        "updated_at": "2020-01-06T09:29:16Z",
        "metadata": null
    }
]

7.4 获取单个Oauth2客户端

7.4.1 接口说明

7.4.2 请求参数

请求参数 参数类型 参数说明
id 字符串 客户端id,必填项

7.4.3 请求举例

http://127.0.0.1:4445/clients/xxx-client

7.4.4 响应示例

{
    "client_id": "xxx-client",
    "client_name": "xxxOAuth2.0",
    "redirect_uris": [],
    "grant_types": [],
    "response_types": [],
    "scope": "openid offline offline_access",
    "audience": [],
    "owner": "",
    "policy_uri": "",
    "allowed_cors_origins": [],
    "tos_uri": "",
    "client_uri": "http://127.0.0.1:5555/callback",
    "logo_uri": "",
    "contacts": [],
    "client_secret_expires_at": 0,
    "subject_type": "public",
    "token_endpoint_auth_method": "client_secret_basic",
    "userinfo_signed_response_alg": "none",
    "created_at": "2020-01-07T06:25:53Z",
    "updated_at": "2020-01-07T06:25:53Z",
    "frontchannel_logout_session_required": true,
    "metadata": null
}

7.5 客户端凭据授予

7.5.1 接口说明

7.5.2 请求参数

客户端通过 使用添加Header参数 Content-Type="application/x-www-form-urlencoded”
请求实体主体发送以下参数来向令牌端点发出请求。注:以下参数请求使用form-data

请求参数 参数类型 参数说明
grant_type 字符串 授予类型,必填项
refresh_token 字符串 刷新令牌
client_id 字符串 客户端id,必填项
client-secret 字符串 客户端秘钥,必填项
redirect_uri 字符串 重定向uri

7.5.3 凭据授予后台BUG

客户端凭据授予时会出现以下bug

{
    "error":"invalid_client",
    "error_description":"Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)",
    "status_code":401
}

原因是Hydra源码授权代码问题。解决方案如下:

修改 G O P A T H GOPATH /pkg/mod/github.com/ory/[email protected]/client_authentication.go文件190行左右代码,
else if ok && form.Get(“client_id”) != “” && form.Get(“client_secret”) != ""判断有误,修改为下面代码

if oidcClient, ok := client.(OpenIDConnectClient); !ok {
    // If this isn't an OpenID Connect client then we actually don't care about any of this, just continue!
} else if ok && form.Get("client_id") == "" && form.Get("client_secret") == "" && oidcClient.GetTokenEndpointAuthMethod() != "client_secret_post" {
    return nil, errors.WithStack(ErrInvalidClient.WithHintf("The OAuth 2.0 Client supports client authentication method \"%s\", but method \"client_secret_post\" was requested. You must configure the OAuth 2.0 client's \"token_endpoint_auth_method\" value to accept \"client_secret_post\".", oidcClient.GetTokenEndpointAuthMethod()))
} else if _, _, basicOk := r.BasicAuth(); basicOk && ok && oidcClient.GetTokenEndpointAuthMethod() != "client_secret_basic" {
    return nil, errors.WithStack(ErrInvalidClient.WithHintf("The OAuth 2.0 Client supports client authentication method \"%s\", but method \"client_secret_basic\" was requested. You must configure the OAuth 2.0 client's \"token_endpoint_auth_method\" value to accept \"client_secret_basic\".", oidcClient.GetTokenEndpointAuthMethod()))
} else if ok && oidcClient.GetTokenEndpointAuthMethod() != "none" && client.IsPublic() {
    return nil, errors.WithStack(ErrInvalidClient.WithHintf("The OAuth 2.0 Client supports client authentication method \"%s\", but method \"none\" was requested. You must configure the OAuth 2.0 client's \"token_endpoint_auth_method\" value to accept \"none\".", oidcClient.GetTokenEndpointAuthMethod()))
}

7.5.4 凭据授予成功示例

{
    "access_token": "n5236wH87fpCoZ4AQc8QPhpysu9pDbtBH6ilZr0DwdU.lCYGIa1g48xuXzb7xj2leVSn7ACOgwWhpVxDBG9g9OI",
    "expires_in": 3599,
    "scope": "",
    "token_type": "bearer"
}

7.6 对access_token自省

7.6.1 接口说明

7.6.2 请求参数

注:以下参数请求使用form-data

请求参数 参数类型 参数说明
token 字符串 access_token,必填项
scope 字符串 客户端作用范围

7.6.3 响应示例

{
    "active": true,
    "client_id": "what-client",
    "sub": "what-client",
    "exp": 1578412753,
    "iat": 1578409154,
    "iss": "https://localhost:4444/",
    "token_type": "access_token"
}

7.7 OAuth2.0授权代码授予

我们将执行OAuth 2.0授权代码授予。为此,我们必须首先创建一个能够执行该授权的客户端

7.7.1 接口说明

7.7.2 请求参数

客户端通过 使用添加Header参数 Content-Type="application/x-www-form-urlencoded”
。OAuth2.0授权代码授予。特别注意:以下参数请求使用form-data ,此处的client_id是根据上面的客户端秘钥client-secret
自己从新创建的一个OAuth2.0端的id

请求参数 参数类型 参数说明
client_id 字符串 客户端id
client_name 字符串 客户端名称
client_secret 字符串 客户端秘钥
client_secret_expires_at 字符串 客户端秘钥过期时间
created_at 字符串 客户端创建时间
frontchannel_logout_session_required 字符串 是否注销会话 0否,1是
scope 字符串 客户端作用范围
token_endpoint_auth_method 字符串 令牌终结点身份验证方法
grant_types 字符串 授予类型
response_types 数组 响应类型
…… …… ……

7.7.3 请求参数示例

{
    "client_id":"auth-what-client",
    "client_name":"auth-whatOAuth2.0",
    "client_secret":"what-secret",
    "client_secret_expires_at":0,
     "redirect_uris": [
    "http://127.0.0.1:5555/callback"
  ],
    
    "created_at":"2020-01-06T15:09:15.946Z",
    "frontchannel_logout_session_required":false,
    "scope":"openid offline offline_access",
    "token_endpoint_auth_method":"client_secret_basic",
    "updated_at":"2020-01-07T15:09:15.946Z",
    "userinfo_signed_response_alg":"none",
    "grant_types": [
    "authorization_code","refresh_token"
  ],
   "response_types": [
    "code","id_token"
  ]
}

7.8 执行OAuth2.0授权代码流

以下命令将启动前端Web应用程序的服务器。该应用程序将使用ORY Hydra执行OAuth 2.0授权代码流。

7.8.1 接口说明

7.8.2 请求参数

客户端通过 使用添加Header参数 Content-Type="application/x-www-form-urlencoded”
。OAuth2.0授权代码授予。特别注意:以下参数请求使用form-data ,此处的client_id是根据上面的客户端秘钥client-secret
自己从新创建的一个OAuth2.0端的id

请求参数 参数类型 参数说明
client_id 字符串 OAuth2.0端id,不同于客户端id,必填项
client_secret 字符串 客户端秘钥,必填项
scope 字符串 客户端作用域 必填项openid,offline

8 数据库设计文档

8.1 客户端数据表hydra_client

字段名称 字段类型 参数说明
id varchar(255) 客户端id
client_name text 客户端名称
client_secret text 客户端秘钥
redirect_uris text 重定向uri
grant_types text 授予类型
response_types text 响应类型
scope text 客户端作用范围
owner text 客户端拥有者
policy_uri text 策略uri
tos_uri text tos_uri
client_uri text 客户端uri
logo_uri text logo_uri
contacts text 客户端联络
client_secret_expires_at int(11) 客户端秘钥过期时间
sector_identifier_uri text 扇区标识符
jwks text json web密钥集
jwks_uri text json web密钥集uri
request_uris text 请求URIS
token_endpoint_auth_method varchar(25) 令牌终结点身份验证方法
request_object_signing_alg varchar(10) 请求对象签名
userinfo_signed_response_alg varchar(10) 用户信息签名响应
subject_type varchar(15) 主题类型
allowed_cors_origins text 允许跨域起源
pk int(10) 主键id
audience text 访客
created_at timestamp 创建时间
updated_at timestamp 更新时间
frontchannel_logout_uri text 前置频道注销uri
frontchannel_logout_session_required tinyint(1) 需要前置频道注销会话
post_logout_redirect_uris text 退出后重定向uri
backchannel_logout_uri text 退出后频道uri
backchannel_logout_session_required tinyint(1) 需要退出会话
metadata text 元数据

8.2 客户端迁移表hydra_client_migration

字段名称 字段类型 参数说明
id varchar(255) 主键id
applied_at datetime 迁移应用时间

8.3 jsonWeb密钥数据表hydra_jwk

字段名称 字段类型 参数说明
sid varchar(255) token类型标识id
kid varchar(255) 秘钥id
version int(11) 版本号
keydata text 秘钥数据
created_at timestamp 创建时间
pk int(10) 主键

8.4 jsonWeb密钥迁移表hydra_jwk_migration

字段名称 字段类型 参数说明
id varchar(255) 主键id
applied_at datetime 迁移应用时间

8.5 客户端授权码表hydra_oauth2_access

字段名称 字段类型 参数说明
signature varchar(255) 签名
request_id varchar(40) 请求id
requested_at timestamp 请求时间
client_id varchar(255) 客户端id (表hydra_client的id)
scope text 作用范围
granted_scope text 授予范围
form_data text 表单数据
session_data text session数据
subject varchar(255) 主题
active tinyint(1) 是否有效
requested_audience text 请求的访客
granted_audience text 授予访客
challenge_id varchar(40) 挑战id 表hydra_oauth2_consent_request_handled的challenge字段

8.6 同意认证迁移表hydra_oauth2_authentication_consent_migration

字段名称 字段类型 参数说明
id varchar(255) 主键id
applied_at datetime 迁移应用时间

8.7 身份验证请求表 hydra_oauth2_authentication_request

字段名称 字段类型 参数说明
challenge varchar(40) 主键id
requested_scope text 请求范围
verifier varchar(40) 验证者id
csrf varchar(40) Cross—SiteRequestForger
subject varchar(255) 主题
request_url text 请求url
skip tinyint(1) 是否跳过
client_id varchar(255) 客户端id ,表hydra_client的id
requested_at timestamp 请求时间
authenticated_at timestamp 验证时间
oidc_context text OIDC上下文
login_session_id varchar(40) 登录session的id,表hydra_oauth2_authentication_session的id
requested_at_audience text 请求的访客

8.8 已处理身份验证请求hydra_oauth2_authentication_request_handled

字段名称 字段类型 参数说明
challenge varchar(40) 主键id
subject varchar(255) 主题
remember tinyint(1) 是否记住
remember_for int(11) 记住时间
error text 错误数据
acr text acr
requested_at timestamp 已完成请求时间
authenticated_at timestamp 已验证时间
was_used tinyint(1) 是否使用
forced_subject_identifier varchar(255) 强制的主题标识符
context text 已请求的内容

8.9 身份验证会话hydra_oauth2_authentication_session

字段名称 字段类型 参数说明
id varchar(40) 主键id
authenticated_at timestamp 已验证会话时间
subject varchar(255) 主题
remember tinyint(1) 是否记忆

9 Oauth2第三方登录示例图

::: tip qq账号登录CSDN服务器Oauth2授权说明

  1. CSDN网站让用户跳转到QQ
  2. QQ要求用户登录(若没有QQ账号,则需要注册),然后询问"CSDN网站要求获得自己的QQ用户权限,你是否同意?"
  3. 用户同意,QQ就会重定向回CSDN网站,同时发回一个授权码。
  4. CSDN网站使用授权码,向QQ请求令牌。
  5. QQ返回令牌。
  6. CSDN网站使用令牌,向QQ请求用户数据。
  7. CSDNQQ用户在CSDN服务器上写博客、评论等
    :::

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o9NF4vLa-1591889699754)(/img/goImage/oauth2_client.png)]

10 测试Oauth2授权服务

10.1 客户端凭据授权方式

Client Credentials Grant这种类型是最简化的,Client直接定义自己的client_id而不是Resource owner的名义去要求访问Resource server的一些受保护资源。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w9GFXO3y-1591889699755)(/img/goImage/Client-Credentials.png)]

10.2 创建OAuth 2.0客户端

参考7-2-创建oauth2客户端

10.3 执行客户端凭据

参考7-5-客户端凭据授予

10.4 执行令牌自省

参考7-6-对access-token自省

10.5 跳转到登录页面

浏览器输入以下地址到后台服务请求,后台服务返回前端的登录页面http://localhost:3000/login?login_challenge=ec2bf8e55a11474392f8867e92624e04

http://127.0.0.1:4444/oauth2/auth?client_id=what-client&scope=offline_access&response_type=code&state=abcdefghigklmn

请求参数说明

  • 请求方式:GET
  • 请求接口:http://127.0.0.1:4444/oauth2/auth
  • 参数client_id为10.2创建的客户端id
  • 参数response_type为响应类型,一般固定response_type=code
  • 参数scope为Client的作用范围[openid offline ,offline_access]
  • 参数state为Client提供的一个字符串,服务器会原样返回给Client。长度必须大于8位
  • 注:127.0.0.1:4444为后台Public API端点服务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RSE3WQYI-1591889699758)(/img/goImage/hydra_login.png)]

10.6 登录页面

输入input框提示的账号密码,点击登录,跳转到成功登录页面,登录接口如下

#登录接口
http://127.0.0.1:4444/oauth2/auth/requests/login/accept?login_challenge=536e6810083947aab2bb7dda5ee6815a
#验证接口
http://127.0.0.1:4444/oauth2/auth?client_id=what-client&login_verifier=c7faac0f7b62457d955a00c5d95f65e2&response_type=code&6scope=offline_access&6state=abcdefghiddgklmn
#验证成功返回接口
http://127.0.0.1:4444/oauth2/auth/requests/consent?consent_challenge=70f9f2402e8b4ea4b07376a9dee22c52

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mkewiwLy-1591889699760)(/img/goImage/login_success.png)]

项目详细流程说明

登录、同意和注销官方流程说明

11 参考资料

 <a data-fancybox title="登录成功页面" href="/img/goImage/login_success.png">[外链图片转存中...(img-mkewiwLy-1591889699760)]</a>

### 项目详细流程说明
[登录、同意和注销官方流程说明](https://www.ory.sh/docs/hydra/login-consent-flow)

## 11 参考资料
- [https://oauth.net/2/](https://oauth.net/2/)
- [https://www.oauth.com/](https://www.oauth.com/)
- [RFC6749:OAuth 2.0授权框架](https://tools.ietf.org/html/rfc6749)
- [RFC6749中文版](https://github.com/jeansfish/RFC6749.zh-cn)
- [Hydra官方文档说明](https://www.ory.sh/docs/hydra/)
- [IBM社区学习如何引导 Hydra](https://www.ibm.com/developerworks/cn/security/se-bootstrap-hydra-oauth2/index.html)
- [Github项目问题反馈列表](https://github.com/ory/hydra/issues)
- [Oauth2认证和授权参考文档](https://www.cnblogs.com/linianhui/category/929878.html)

猜你喜欢

转载自blog.csdn.net/qq_37493556/article/details/106699444