Hydra项目介绍
Hydra介绍
ORY Hydra是经过强化,经过OpenID认证的OAuth 2.0服务器和OpenID Connect提供商,针对低延迟,高吞吐量和低资源消耗进行了优化。ORY Hydra 不是身份提供者(用户注册,用户登录,密码重置流程),而是通过登录和同意应用程序连接到您现有的身份提供者。以不同的语言实现登录和同意应用程序很容易,并且提供了示例性的同意应用程序(Go,Node)和 SDK。
1 代码下载
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
5 查看项目接口文档
进入到hydra项目根目录执行以下命令 更多命令请参考swagger -h
swagger serve -F=swagger ./docs/api.swagger.json
6 前端项目
6.1 配置文件说明
绑定后端服务器地址,配置文件位置在hydra-login-consent-node-master/services/hydra.js,如下图
6.2 前端目录结构说明
7 部分接口说明
7.1 流程图说明
以下是部分接口文档说明,更多请求参数请参考swagger文档说明
7.2 创建Oauth2客户端
7.2.1 接口说明
- 请求方式:POST
- 请求URL:http://127.0.0.1:4445/clients
- 注:127.0.0.1:4445为后台
Admin API
端点服务
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 接口说明
- 请求方式:GET
- 请求URL:http://127.0.0.1:4445/clients
- 注:127.0.0.1:4445为后台
Admin API
端点服务
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 接口说明
- 请求方式:GET
- 请求URL:http://127.0.0.1:4445/clients/{id}
- 注:127.0.0.1:4445为后台
Admin API
端点服务
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 接口说明
- 请求方式:POST
- 请求URL:http://127.0.0.1:4444/oauth2/token
- 注:127.0.0.1:4444为后台
公共API端点服务
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源码授权代码问题。解决方案如下:
修改 /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 接口说明
- 请求方式:POST
- 请求URL:http://127.0.0.1:4445/oauth2/introspect
- 注:127.0.0.1:4445为后台
Admin API
端点服务
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 接口说明
- 请求方式:POST
- 请求URL:http://127.0.0.1:4445/clients
- 注:127.0.0.1:4445为后台
Admin API
端点服务
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 接口说明
- 请求方式:POST
- 请求URL:http://127.0.0.1:4444/oauth2/auth
- 注:127.0.0.1:4444为后台
公共API端点服务
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授权说明
CSDN
网站让用户跳转到QQ
QQ
要求用户登录(若没有QQ
账号,则需要注册),然后询问"CSDN
网站要求获得自己的QQ
用户权限,你是否同意?"- 用户同意,
QQ
就会重定向回CSDN
网站,同时发回一个授权码。 CSDN
网站使用授权码,向QQ
请求令牌。QQ
返回令牌。CSDN
网站使用令牌,向QQ
请求用户数据。CSDN
用QQ
用户在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客户端
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
请求参数说明
- 请求方式: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 参考资料
- https://oauth.net/2/
- https://www.oauth.com/
- RFC6749:OAuth 2.0授权框架
- RFC6749中文版
- Hydra官方文档说明
- IBM社区学习如何引导 Hydra
- Github项目问题反馈列表
in_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
<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)