# 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
1

# 2.2 初始化数据库

进入到hydra项目根目录执行

# 2.2.1 用Navicat创建一个数据库hydra

创建数据库hydra

# 2.2.2 进行hydra项目数据迁移

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

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

# 2.2.3 在Navicat查看是否迁移成功

在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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383

# 4 启动项目

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

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

启动项目成功

# 5 查看项目接口文档

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

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

项目接口文档

# 6 前端项目

hydra-login-consent-node下载

# 6.1 配置文件说明

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

前端页面配置说明

# 6.2 前端目录结构说明

前端目录结构说明

# 7 部分接口说明

# 7.1 流程图说明

Hydra流程图

以下是部分接口文档说明,更多请求参数请参考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"
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 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"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 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
    }
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

# 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
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 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
}
1
2
3
4
5

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

修改$GOPATH$/pkg/mod/github.com/ory/fosite@v0.30.2/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()))
}
1
2
3
4
5
6
7
8
9

# 7.5.4 凭据授予成功示例

{
    "access_token": "n5236wH87fpCoZ4AQc8QPhpysu9pDbtBH6ilZr0DwdU.lCYGIa1g48xuXzb7xj2leVSn7ACOgwWhpVxDBG9g9OI",
    "expires_in": 3599,
    "scope": "",
    "token_type": "bearer"
}
1
2
3
4
5
6

# 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"
}
1
2
3
4
5
6
7
8
9

# 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"
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 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字段
字段名称 字段类型 参数说明
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第三方登录示例图

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服务器上写博客、评论等

Oauth2第三方登录示例图

# 10 测试Oauth2授权服务

# 10.1 客户端凭据授权方式

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

Client-Credentials

# 10.2 创建OAuth 2.0客户端

创建OAuth2.0客户端示例

# 10.3 执行客户端凭据

执行客户端凭据示例

# 10.4 执行令牌自省

执行令牌自省示例

# 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
1

请求参数说明

  • 请求方式: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端点服务

返回前端的登录页面

# 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
1
2
3
4
5
6

登录成功页面

# 项目详细流程说明

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

# 11 参考资料