聊聊OAuth2.0和OIDC
[[toc]]
认证和授权
认证和授权通常一起使用用来确保系统和数据的安全性,但却经常被混淆。
- 认证:验证用户的身份,通过认证则表明你是该网站的用户。
- 授权:根据用户的身份和角色来决定用户可以做什么,确定用户是否具有执行特定操作或访问特定资源的权限。
OAuth2.0
问题背景
小胖最近空虚,随手打开了QQ相册,看着那些充满青春气息的照片,勾起了他的回忆。他想在***“留住美好”网站***中把这些相片打印出来。此时他有两种操作方式来打印这些照片:
- 方式1:他先在QQ相册中下载那些需要打印的照片,然后再把这些照片上传到“留住美好”网站中打印。
- 方式2:在留住美好网站中直接输入QQ相册的用户名和密码,由留住美好网站自动下载。
方式1 用户操作比较麻烦,体验不友好,方式2 把QQ相册的用户名和密码暴露给第三方,风险比较大,并且留住美好网站拿到凭证后,就可以拥有所有权限,只能通过修改密码撤回,否则无法撤回。
以上两种方式都不合适。那有没有其他的方案呢?
面对这类场景,OAuth2.0应运而生。OAuth2.0是一种授权协议,OAuth2.0授权框架使第三方应用(留住美好 网站)能够获取资源服务器(QQ相册)中特定资源(该用户的照片)的特定访问权限(只读权限)。
基于OAuth2.0授权框架(可参见RFC 6749 ),小胖只需要授权留住美好网站访问QQ相册的特定相片,那么留住美好网站在获取授权后,就可以自动下载相片,自动打印了。这样小胖也不用担心密码泄漏,也不用先下载后上传等繁琐操作。
角色
OAuth2.0授权协议中主要有4个角色:
角色 | 含义 | 备注 |
---|---|---|
Resource Owner | 资源所有者 | 小胖 |
Client | 客户端,包含前端页面和后端服务 | 留住美好网站 |
Authorization Server | 授权服务器,负责发送Acdess Token | QQ相册提供的授权服务 |
Resource Server | 资源服务器,存放受保护的资源 | QQ相册 |
客户端类型
OAuth 根据客户端与授权服务器进行安全身份验证的能力(即维护其客户端凭据机密性的能力),定义了两种客户端类型:
-
机密
能够维护其凭据机密性的客户端(例如,在安全服务器上实现且对客户端凭据的访问权限受到限制的客户端),或能够使用其他方式进行安全的客户端身份验证。
对于一个普通的web站点来说,虽然用户可以访问到前端页面, 但是客户端的机密数据都存储在后端服务器上, 前端无法获取这些机密信息。 -
公共
无法维护其凭据机密性的客户端(例如,在资源所有者使用的设备上执行的客户端,例如已安装的原生应用或基于 Web 浏览器的应用),并且无法通过任何其他方式进行安全的客户端身份验证。
比如桌面软件, 手机App, 单页面程序(SPA), 因为这些应用是发布出去的, 实际上也就没有安全可言, 恶意攻击者可以通过反编译等手段查看到客户端的密钥, 这种是公开的客户端。
授权模式
OAuth2.0主要有4中授权模式:授权码模式(Authorization Code)、隐式模式(Implicit)、密码模式(Resource Owner Password Credentials)和客户端凭证模式(Client Credentials)。其中授权码模式是最经典最安全的授权模式,不推荐使用隐式模式和密码模式。
授权码模式(Authorization Code)
- 适用场景:可以安全存储客户端密钥的应用
- 处理流程
- Client引导用户跳转到第三方授权页面进行授权
- 用户确认授权后,授权服务器返回重定向应答,用户浏览器重定向到client的特定地址,client从该重定向地址中获取授权码code。
- client从重定向地址中取出授权码code,请求授权服务获取Access Token,这里用户就不能接触到该AccessToken。
- 授权服务器收到请求后,进行相关的安全检查(如客户端用户密码校验、授权码code的有效期校验等),相关检查通过后,返回AccessToken和RefreshToken(可选)
- client携带AccessToken请求第三方服务受限资源
- 第三方服务收到资源请求后,进行权限校验,校验通过后返回相关资源信息
- 当AccessToken快过期时,client可以向授权服务器发起Token的刷新请求
- 授权服务器收到Token的刷新请求,进行相关的安全检查(如客户端用户密码校验、RefreshToken的有效性等),相关检查通过后,返回AccessToken和RefreshToken(可选)
- client使用新的AccessToken继续访问资源
- 接口描述:
-
获取授权码
参数 含义 备注 请求参数 response_type 必填,取值code client_id 必填,客户端id 在第三方网站中注册得到 redirect_uri 重定向回调地址,当只注册一个回调地址时 可选,否则必填 在第三方网站注册时填的回调地址,授权服务器会检查该地址是否跟注册时的地址匹配 scope 授权访问的范围 state 推荐,客户端随机生成的字符串 授权服务器回调时会携带该值以便client进行校验,防止CSRF攻击 应答参数 code 必填,授权码 有较短的有效期,推荐10分钟 state 请求中的state,如果请求中携带,则该值必填 客户端必须校验该值跟请求中的state一致 -
获取AccessToken
参数 含义 备注 请求参数 grant_type 必填,取值authorization_code code 必填,授权码 授权服务器必须校验该值处于有效期内,且只能使用一次 redirect_uri 重定向回调地址,如果在获取授权码请求中设置了,则必填 授权服务器会检查该地址是否跟获取授权码请求中的地址匹配 client_id 必填,客户端id 授权服务器会校验client_id和code的绑定关系 client_secret 必填,客户端密码 授权服务器必须检查客户端的用户名密码 应答参数 access_token 必填,访问令牌 token_type 必填,令牌类型,比如Bearer expires_in 推荐,访问令牌的有效时间 有相对短的有效期,比如2小时 refresh_token 可选,刷新token 有较长的有效期,比如60天,主要用来在访问令牌快过期时获取新的访问令牌 scope 访问令牌可访问的受限资源范围,如果跟请求的授权范围一致,则可选,否则必填
-