本文并不会对OAuth、OpenID与SAML中的每一个进行详细地说明,而只是简要介绍它们之间的区别与联系。希望对从未接触过这几个概念,或者曾接触过但很迷惑的人有一些帮助。
首先,明白authentication与authorization之间的区别是继续阅读本文的前提。如果你还不明白,建议先阅读零君以前写的一篇文章《应用程序安全(Application Security)》。
OAuth 2.0
OAuth本质是用于委托授权管理的协议,也就是上面所说的authorization的范畴。OAuth最新版本是2.0。虽然上面零君说过本文不会对每一个协议进行详细的说明,但OAuth比较重要,所以还是要简要说明一下。
要理解OAuth,必须要先理解OAuth协议定义的4种角色:
resource owner (资源所有者)
resource server (资源服务器)
client (客户端)
authorization server (授权服务器)
resource owner就是资源的所有者,通常是一个人。resource owner所拥有的资源托管在resource server上。client就是一个应用程序,它需要访问托管在resource server上的资源,前提是获取resource owner的授权。authorization server就是验证resource owner的身份,并在获得其授权后给client颁发一个用于访问resource的access token。
虽然OAuth本质上是用于委托授权的协议,但由于在resource owner对client授权之前,authorization server要先验证resource owner的身份,而这又是authentication的范畴。所以OAuth通常也可以用于解决SSO(Single-Sign On)。
rfc6749定义了OAuth在各种授权类型下的详细工作流程。这里零君不打算细说,具体可参考零君以前写的一篇文章《单点登录(Single Sign On)实现原理详解》,就是一个典型的OAuth协议流程。其中webapp就是这里的角色client,IdP就是这里的角色authorization server与resource server的合二为一。终端用户就是这里的角色resource owner。
OAuth 2.0 与 OpenID Connect 1.0
OpenID只能用于身份验证,也就是authentication。OpenID Connect 1.0是基于OAuth 2.0的。这时可能有人会问,前面说OpenID,怎么这里又冒出OpenID Connect?OpenID 2.0规范已经被废弃,而OpenID Connect 1.0则是最新的规范。参考下面的链接:
https://openid.net/developers/specs/
OpenID Connect 1.0包含很多方面的内容,这里我们只关注Open Connect 1.0与OAuth 2.0相关的点。OpenID Connect core 1.0规范的第一句话就阐明了它们之间的关系:
OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol.
OpenID Connect对OAuth的主要扩展就是引入了ID Token。OAuth协议流程的第一步就是client将resource owner的user-agent(就是浏览器)重定向到authorization server (authorization endpoint),以便authorization server验证resource owner的身份并获取resource owner的授权。这里要注意,OAuth2.0与OpenID Connect 1.0对这一步叫法略有不同,OAuth2.0称为Authorization request(参考rfc6749 4.1.1),而OpenID Connect 1.0则称为Authencation Request(参考OpenID Connect core 1.0规范3.1.2.1)。不管称为什么,实际请求是一样的,包含的参数也是相同的。这里与OpenID Connect相关的参数有两个,分别是resposne_type和scope。OAuth2.0的四种授权模式中,只有Authorization Code和Implicit两种适用于OpenID Connect。具体采用哪种模式,就是参数response_type确定的,例如response_code为code时,则是采用的Authorization Code流程模式。scope参数必须包含openid。因为Authorization Code模式最常用,所以这里就以Code模式举例:
GET authorize?
response_type=code
&scope=openid%20profile%20email
&client_id=s6BhdRkqt3
&state=af0ifjsldkj
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
Host: server.example.com
当Authorization server成功验证了resource owner的身份,并获得了resource owner的授权之后,就会返回一个授权码(authorization code)给client。随后,client就用这个code向Authorization server (Token endpoint)请求ID Token和Access Token。下面request和response是OpenID Connect 1.0中的例子:
Request:
POST token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
Resposne
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "SlAV32hkKG",
"token_type": "Bearer",
"refresh_token": "8xLOxBtZp8",
"expires_in": 3600,
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc
yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5
NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ
fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz
AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q
Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ
NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd
QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS
K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4
XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg"
}
OAuth2.0 与SAML 2.0
SAML是Security Assertion Markup Language的缩写。它是基于XML的一种协议,主要用于IdP(Identity Provider)与SP(Service Provider)之间交换authentication与authorization信息。SAML与OAuth一样,既可以用于authencation,也可以用于authorization。
SAML的一个重要的应用场景就是单点登录(SSO)。虽然OAuth也可用于SSO,但记住OAuth协议的初衷是解决委托授权(delegated authorization)的问题。它们解决单点登录(SSO)的工作流程很类似。区别在于SAML采用XML格式,而OAuth采用JSON传输信息。SAML更适合与企业用户,而对于移动设备则OAuth更合适。
OAuth2.0是一个开放的协议,可以很灵活的扩展,而SAML就可以用来扩展OAuth。SAML2.0对OAuth2.0的扩展体现在两个方面。
SAML2.0对OAuth2.0的第一个扩展就是对授权类型(Authorization Grant)的扩展。前面也已经说过,OAuth2.0支持四种授权类型。作为一种扩展,SAML assertion也可以作为授权类型。这时,在client向authorization server (token endpoint)请求access token时,可以将参数grant_type设置成:
urn:ietf:params:oauth:grant-type:saml2-bearer
下面就是rfc7522中给出的一个例子:
POST token.oauth2 HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Asaml2-bearer&
assertion=PHNhbWxwOl...[omitted for brevity]...ZT4
SAML2.0对OAuth2.0的第二个扩展就是client身份验证方式的扩展。client向authorization server (token endpoint)请求access token时,可以提供client_id和client_secret证明自己的身份。作为一种扩展,SAML assertion也可以用来验证client的身份,这样client就无需提供secret了。这时,client向authorization server的请求需要带上下面两个参数:
client_assertion_type
client_assertion
client_assertion_type的值必须为:
urn:ietf:params:oauth:client-assertion-type:saml2-bearer
rfc7522给出的一个例子如下:
POST token.oauth2 HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth
%3Aclient-assertion-type%3Asaml2-bearer&
client_assertion=PHNhbW...[omitted for brevity]...ZT
注意,SAML2.0对OAuth2.0的这两个扩展可以联合起来使用,也可以分开使用,rfc7521中原文如下:
Note: The use of assertions for client authentication is orthogonal
to and separable from using assertions as an authorization grant.
They can be used either in combination or separately. Client
assertion authentication is nothing more than an alternative way for
a client to authenticate to the token endpoint and must be used in
conjunction with some grant type to form a complete and meaningful
protocol request. Assertion authorization grants may be used with or
without client authentication or identification.
参考文献:
https://tools.ietf.org/html/rfc6749
https://tools.ietf.org/html/rfc6750
https://tools.ietf.org/html/rfc7521
https://tools.ietf.org/html/rfc7522
https://tools.ietf.org/html/rfc7523
https://openid.net/connect/
https://openid.net/developers/specs/
https://en.wikipedia.org/wiki/SAML_2.0
--END--




