文章目录
通过Keycloak API理解OAuth2与OpenID Connect
前言
Keycloak是一个被广泛使用的SSO(单点登录)工具,支持OAuth2和OpenID Connect。
本文通过测试调用Keycloak API来帮助理解OAuth2与OpenID Connect。
OAuth2 介绍
OAuth2核心概念
OAuth2核心概念:
- Resource Owner - 资源所有者,一般指用户。
- Resource Server - 资源服务器。
- Client - 代表Resource Owner去访问受保护的资源。
- Authorization Server - 对Resource Owner进行身份认证,并颁发访问受保护资源的access token。
- User Agent - 用户代理,一般指浏览器,负责用户登录和注销后的页面跳转。
- Resource - 受保护的资源,比如API,页面。
示例1:
- 用户William打开浏览器访问业务系统A时,被重定向到Keycloak登录页面。
- 用户William在Kyecloak登录页面输入用户名和密码,登录成功后,页面跳转到业务系统A的首页。
- 用户William点击业务系统A的某个菜单查询业务数据,业务系统成功返回数据。
在示例1中:
- Resource Owner - 用户Willliam
- Resource Server - 业务系统A
- Client - 业务系统A的Web页面
- Authorization Server - Keycloak
- User Agent - 浏览器
- Resource - 业务数据
OAuth2 核心数据
OAuth2 核心数据
- User Credential - 用户登录的凭据,比如用户名和密码。
- Client ID - 唯一标识一个Client。
- Client Secret - 用于Authroziation Server验证Client身份,不能泄漏。
- Authorization Code - 授权码,通过 User Credential + Client ID换取Authorization Code。授权码不能泄漏,且一次性有效。
- Access Token - 访问令牌,拥有令牌者可以访问受保护的资源。通过 Authorization Code + Client ID + Client Secret 换取。Access Token在有效期内有效。
- Refresh Token - 刷新令牌,用来刷新(重新获取)Access Token和Refresh Token。Refresh Token在有效期内有效。
- ID Token - The OpenID Connects ID Token is a signed JSON Web Token (JWT) which contains a set of information about the authentication session, which basically includes identifiers for the end user, identity provider who issued the token, client for which this token was created.
JWT
Access Token为JWT格式。
示例:
eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJqRkdrVnhBbEVXcGN4ekJPZ25RUWxZb2VQYkZfOXM1aG5SeVlRdExHeTNVIn0.eyJleHAiOjE2MTA3MjA5NDAsImlhdCI6MTYxMDcyMDY0MCwianRpIjoiM2Q3M2IyNjItZDU3NC00OWEyLThlMGEtYWQ0ZmM0ZDAxMTA1IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL29yZy1kZW1vIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjQ4ZGJiMGJkLTBiODYtNDFjNC1hNWUwLTlmNmY2YTAwMGQyMiIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFwcC0xIiwic2Vzc2lvbl9zdGF0ZSI6ImRlNzZmNmYwLTRjMjktNDkwMy04YTQxLTUxYmVlMjllMmNiZiIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiVXNlciIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6IndpbGxpYW0ifQ.JAZhvi8QHY0MHyiwuhXZ9amxXXvutLhYN3jUclmPUrJizikYNpS61Qub8iVruSGOxI6pfvc5BcwTJUwZ0UsmBl_BalKEox1MkOujHKhtMQ78631H3eZyANCUbbe-u0y4Vp3fmWTk6ErgcIQSY2DkmsE97tzVVCrVC_uGdcpewUpUu1VDzA1TPd5KSvU-2d8T_KOeTUsLoG4964ryheJiYQOkXVxJCe1CN5eQlIIZlSIujq7O71tPDaNif9RunrpU0c2rAtqKoU0bS1iKXIOqRtxfFum7Ju1l7I2Sa4uiZH-T76yLRO5Mxk124FNu49y6H-Zu10u0memWAPvtJSi-ZQ
这是一串Base64URL的编码。
对其解码后,内容包括header, payload 和 signature:
- Header:
{
"typ": "JWT",
"alg": "RS256",
"kid": "jFGkVxAlEWpcxzBOgnQQlYoePbF_9s5hnRyYQtLGy3U"
}
- Payload:
{
"exp": 1610720940, # 令牌过期时间戳
"iat": 1610720640, # 令牌颁发时间戳
"jti": "3d73b262-d574-49a2-8e0a-ad4fc4d01105", # 令牌唯一标识符
"iss": "http://localhost:8080/auth/realms/org-demo", # 令牌颁发者
"aud": "account", # 令牌的受众,接收者
"sub": "48dbb0bd-0b86-41c4-a5e0-9f6f6a000d22", # 令牌的主体
"typ": "Bearer", # 令牌的类型
"azp": "app-1",
"session_state": "de76f6f0-4c29-4903-8a41-51bee29e2cbf",
"acr": "1",
"realm_access": {
"roles": [
"User",
"offline_access",
"uma_authorization"
]
},
"resource_access": {
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "profile email",
"email_verified": false,
"preferred_username": "william"
}
- Signture
secret
JWT 解码网站(只做debug用,不要泄漏token!):
可以看到JWT本身已经包含验证Token所需的全部元数据,因此Resource Server无需调用Authorization Server的接口就可以验证Access Token的有效性。
当然,Resource Server也可以再调用Authorization Server的Introspect Token (令牌内省)接口来验证Access Token的有效性,作为防止令牌被伪造的增强性安全措施。
OAuth2 flow
OAuth2 框架定义以下几种flow (授权流程):
- Authorization Code Flow - 授权码授权流程;最常见的授权流程。
- Implicit Flow - 隐式授权流程
- Resource Owner Credential Flow - 资源所有者凭据授权流程;不安全,强烈不建议使用。
- Client Credential Flow - 客户端凭据授权流程
Authorization Code Flow
Authorization Code Flow (授权码授权流程)如下图所示:
说明:
- 因为Access Token采用JWT格式,已经包含了验证Access Token的元数据,因此Resource Server无需调用Authorization Server的接口就可以验证Access Token的有效性。
- 当然,Resource Server也可以再调用Authorization Server的Token Introspection (令牌内省)接口来验证Access Token的有效性,作为防止令牌被伪造的增强性安全措施。
安全性要求:
- 保证数据链路安全:Client - Authorizaiton Server 、Client - Resource Server 和 Authorization Server - Resource Server 之间强烈建议为HTTPS协议,防止数据被窃听后泄密。
- 加密数据:对敏感数据进行加密,万一泄漏,也无法被解密。
- 防止重放攻击:对Authorization Server和Resource Server提供的API需要通过nonce的方法防止重放攻击(replay attack)。
- 防止数据被篡改:对对Authorization Server和Resource Server提供的API需要通过签名和验签的方法防止数据被篡改。
- 双向验证:服务端要验证客户端的合法性,客户端也要验证服务端的合法性。
- 代码安全:不能将Client Secret存储在前端代码中,防止Client Secret泄漏。
参见: