OpenID Connect Core 1.0(四)使用授权码流验证(上)
3.1 使用授权码流验证(Authentication using the Authorization Code Flow)
本节描述如何使用授权码流执行验证。当使用授权码流时,会从令牌终结点返回的所有令牌。
授权码流返回授权码给客户端,这个授权码可以直接交换一个ID Token和一个Access Token。这给User Agent提供了不暴露任何令牌的好处,因为可能还有其他恶意的应用程序访问User Agent。授权服务器也可以在验证客户端之前通过Access Token交换的授权码。授权码流适合那些可以安全地在客户与密钥授权服务器之间进行客户密码维护的场景。
3.1.1 授权码流步骤(Authorization Code Flow Steps)
授权码流经过以下步骤。
1、客户准备一个包含所需的验证请求的请求参数。
2、客户端发送请求到授权服务器。
3、授权服务器验证用户。
4、授权服务器获得用户同意/授权。
5、授权服务器给终端用户发送回一个授权码给客户端。
6、客户端使用授权码向令牌终结点请求一个响应。
7、客户端接收到包含一个ID Token和Access Token响应body。
8、客户端验证ID Token和检索终端用户的 Subject标识符。
3.1.2 授权终结点(Authorization Endpoint)
授权终结点对终端用户的验证。是通过发送User Agent到授权服务器的验证和授权的终结点,其请求参数在OAuth 2.0中定义,额外的参数和参数值定义在OpenID Connect中定义。
授权终结点的通信必须使用TLS。参看16.17节中关于TLS的更多信息。
3.1.2.1验证请求(Authentication Request)
一个验证请求是OAuth 2.0由授权服务器的终端用户验证的授权请求。
授权服务器必须支持使用授权终结点在RFC 2616中定义的HTTP GET和POST方法。客户可以使用HTTP GET或POST方法来发送授权请求到授权服务器。如果使用HTTP GET方法,请求参数的序列化是使用每URI查询字符串序列化(13.1节)。如果使用HTTP POST 方法,请求参数序列化使用表单序列化形式(13.2节)。
OpenID Connect使用下面的OAuth 2.0授权码流的请求参数:
scope
必需的。OpenID Connect请求必须包含 openid scope值。如果 openid scope值不存在,其行为是完全不确定的。可能存在其他scope值。对不能理解 scope实现值应该被忽略。参看(5.4 和 11 这个规范定义的额外的scope值部份)。
response_type
必需的。决定授权处理的流程,并从终结点返回什么样的参数是由OAuth 2.0响应类型值所决定。当使用授权码流,其值是 code。
client_id
必需的。OAuth 2.0 对授权服务器有效的客户端标识符。
redirect_uri
必需的。将由响应发送的重定向URL。此URI必须是精确匹配客户端预先注册的OpenID提供者的重定向URI值,匹配执行的描述在 6.2.1节 (RFC3986) (简单的字符串比较)。当使用此流程,重定向URI应该使用 https 方案; 但它也可以使用 http方案,在这种OP允许使用 http 重定向URL提供方式情况下,如何提供客户端类型保密,在OAuth 2.0 2.1节中定义。重定向的URI可能使用一个替代方案,比如,例如,当目的是识别本机应用程序一个回调时。
state
推荐。不透明值,在维护请求和回调之间状态时使用。一般来说,是通过浏览器一个cookie加密值,以降低跨站请求伪造(CSRF XSRF)。
OpenID Connect也使用OAuth 2.0请求参数,此定义在 OAuth 2.0有多个响应类型编码实践。
response_mode
可选的。通知授权服务器从授权终结点返回参数使用的机制。不推荐使用这个响应模式参数,而将其请求设定为响应类型指定的默认模式。
此规范还定义了以下请求参数:
nonce
可选的。字符串值,用于关联客户端会话的ID Token,以减轻重播攻击。该值在验证ID Token请求中不会修改。Nonce必须有足够的复杂度去防止攻击者猜测值。实现说明,请参阅 15.5.2节 。
display
可选的。验证和授权服务器的ASCII字符串值,指示如何显示在经由终端用户同意的用户界面页面上,定义的值是:
page
授权服务器应该显示的验证和同意UI与一个完整的User Agent页面一致的视图。如果没有指定显示参数,就采用默认显示模式。
popup
授权服务器应该显示验证和一致的用户同意界面的一个弹出User Agent窗口。弹出User Agent窗口应该适当的大小,在整个窗口中不应掩盖login-focused对话框呈现。
touch
授权服务器应该在利用可触摸设备中显示的验证和一致的用户同意界面。
wap
授权服务器应该在“功能手机”中显示的验证和一致的用户同意界面。
授权服务器也可能试图检测User Agent功能,并呈现一个适当的显示。
prompt
可选的。空格分隔的,区分大小写的ASCII字符串值列表,指定是否授权服务器提示终端用户重认证和同意。定义的值是:
none
授权服务器不能显示任何验证或同意的用户页面。如果一个终端用户还没有经过验证或客户端没有预配置请求同意声明或不满足其他条件处理请求时返回一个错误。通常的错误代码是login_required ,interaction_required ,或定义在 3.1.2.6节的另外的代码 。可以用于检查现有的授权 和/或 同意的方法。
login
授权服务器应该提示终端用户重认证。如果终端用户不能重认证,必须返回一个错误,通常 login_required 。
consent
授权服务器应该提示终端用户准许,然后返回信息到客户端。如果不能获得准许,它必须返回一个错误,通常 consent_required 。
select_account
授权服务器应该提示用户选择一个帐户。这在一个终端用户有多个账户的授权服务器上在当前会话中进行多个帐户选择。如果不能获得一个由终端用户选择的帐户,必须返回一个错误,通常 account_selection_required 。
提示参数能被客户端使用,以确保终端用户在当前会话中存在或者请求意图。如果这个参数不包含任何其他值,则返回错误。
max_age
可选的。验证最大过期时间。指定允许存续时间,以秒为单位,是自上次通过OP终端用户激活验证的存续时间,如果存续时间大于这个值,OP必须积极尝试对终端用户进行重新确认。(max_age 请求参数对应 OpenID 2.0 PAPE (OpenID.PAPE)的 max_auth_age 请求参数)。当使用max_age,返回的ID Token中必须包括一个 auth_time 声明值。
ui_locales
可选的。终端用户界面的首选语言和脚本,表示为一个BCP47 RFC5646语言标记值的空格分隔的列表,按偏好排序。如,值“fr-CA fr en”代表了一种偏好:加拿大的法语、法语(没有指定一个区域),其次是英语(没有指定一个区域)。如果OpenID提供者不支持部分和所有请求的区域设置不应该产生错误。
id_token_hint
可选的。之前由授权服务器签发的ID Token,作为暗示,传递给终端用户与客户验证的当前或过去会话。如果终端用户已经被登录的ID Token登确认或已登录的请求,那么授权服务器返回一个肯定的响应; 否则,它应该返回一个错误,如 login_required 。在可能的情况下,当 prompt=none 时应该使用id_token_hint,如不是则应返回一个 invalid_request 错误;当然,服务器应该在允许的情况下响应成功,即使它不存在。授权服务器不应当在ID Token使用id_token_hint值时坐视不理。
如果RP接收到被OP加密的ID Token,并使用它作为id_token_hint ,客户端必须解密签名ID Token中包含加密ID Token。客户可能使用认证服务器能解密的键值重加密签名ID Token,和用重新加密ID Token方式加密id_token_hint值。
login_hint
可选的。关于终端用户可能使用登录标识符登录(如果有必要)提示给授权服务器。这种暗示可以被RP使用,如果它首先寻问终端用户的电子邮件地址(或其他标识符),然后想通过这个值作为一个发现授权服务提示。建议提示值匹配用于发现的值。这个值可能是一个电话号码的格式指定 phone_number 声明。由OP决定是否使用这个参数。
acr_values
可选的。请求的验证上下文类引用值。指定了被请求处理验证请求授权服务器使用的 acr空格分隔的字符串值,值的出现按优先顺序排列。作为 acr 声明值返回满足执行验证的验证上下文类,第二节指定,acr 声明请求是主动声明的参数。
其他参数可能会被发送。部分参看 3.2.2 ,3.3.2 ,5.2 ,5.5 ,6 ,7.2.1 ,由该规范定义的额外的授权请求参数和参数值。
下面是一个非规范的例子,由客户机的 HTTP 302重定向响应,User Agent验证请求授权终结点触发器:
HTTP/1.1 302 Found
Location: https://server.example.com/authorize?
response_type=code
&scope=openid%20profile%20email
&client_id=s6BhdRkqt3
&state=af0ifjsldkj
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
下面是请求非规范化的例子,这将是由User Agent发送到授权服务器,响应的HTTP 302重定向响应客户端上面:
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
3.1.2.2验证请求验证(Authentication Request Validation)
授权服务器必须验证收到的请求如下:
1、授权服务器必须根据OAuth 2.0规范验证所有的 OAuth 2.0参数。
2、验证scope参数存在,并且包含 openid scope值。(如果没有 openid scope值,请求可能仍然是一个有效的OAuth 2.0的要求,但不是一个OpenID Connect请求。)
3、授权服务器必须验证所有必需的参数存在,以及他们的使用符合本规范。
4、如果sub(主题)声明请求一个特定的值的ID Token,授权服务器只会发送一个肯定的响应,如果终端用户确认sub值是具有一个与授权服务器活跃的会话或已经通过验证的请求的结果。授权服务器不必为不同的用户回复ID 令牌或Access Token,即使他们有活动的会话与授权服务器。如果有这样的要求,可使用 id_token_hint 参数或通过请求一个特定的在5.5.1节描述的声明值。如果声明参数支持实现。
OAuth 2.0 (RFC6749)指明授权服务器应该忽略未识别的请求参数。
如果授权服务器遇到任何错误,它必须返回一个错误的响应,参看 3.1.2.6节 。
3.1.2.3授权服务器验证用户(Authorization Server Authenticates End-User)
如果请求是有效的,根据使用的请求参数值,授权服务器尝试对终端用户进行验证或确定终端用户验证。授权服务器所使用的对终端用户进行验证的方法(如用户名和密码,会话cookie,等等)。超出了本规范的范围。授权服务器根据请求参数值使用和所使用的验证方法显示验证用户界面。
在下列情况下授权服务器必须尝试验证终端用户:
- 终端用户没有进行验证。
- 验证请求包含登录提示参数值。在这种情况下,授权服务器必须重验证终端用户,即使终端用户已经通过验证。
授权服务器在下列情况下不应与用户交互:
- 验证请求没有任何包含登录提示参数值。在这种情况下,如果一个终端用户不是已经通过认证或不能隐式的通过验证,授权服务器必须返回一个错误。
与终端用户交互时,授权服务器必须采取适当的措施防范跨站点请求伪造和“点击劫持”如OAuth 2.0 [RFC6749] 10.12和10.13章节描述的那样。
3.1.2.4授权服务器获得用户同意/授权(Authorization Server Obtains End-User Consent/Authorization)
一旦对终端用户进行验证,在对依赖方科放信息之前授权服务器必须获得一个授权决定。当使用的请求参数被许可,就可以与终端用户通过交互式对话,使它清楚已同意或通过建立通过条件处理请求下同意,其他方式(例如:通过以前的管理许可)。在 2 和 5.3信息发布机制部分描述。
3.1.2.5成功的验证响应(Successful Authentication Response)
一个验证响应,是从RP发出的授权请求,并由OP的授权终结点响应的OAuth 2.0授权响应消息。
当使用授权码流,授权响应返回由OAuth 2.0 (RFC6749) 4.1.2节中定义的参数,通过添加查询参数 redirect_uri 中指定的授权请求,使用application/x-www-form-urlencoded格式,除非指定不同的响应模式。
下面是一个成功的响应使用此流程非规范化的例子:
HTTP/1.1 302 Found
Location: https://client.example.org/cb?
code=SplxlOBeZQQYbYS6WxSbIA
&state=af0ifjsldkj
实现例子中关于授权码内容,参看15.5.1节 。
也可发邮件至:azthinker@sina.com
GitHub的https://github.com/azthinker
开源中国 https://gitee.com/azthinker