web服务器应用中使用Oauth
摘自《OAuth2.0 Identity and Access Management Patterns》
授权码模式(Authorization code grant)
我们了解到授权码模式有以下特性:
- 授权码模式一般用于信任的客户端(confidential clients)
- 它需要重定向,因此它是基于重定向的流程(redirection-based)在客户端和授权服务中
- 在授权的时候需要用户同意(approval)
授权码模式流程图:
具体流程:
- 流程开始,首先客户端程序(client application)将用户代理(user-agent,如浏览器)重定向到授权登陆点(authorization endpoint)
- 然后资源服务器(authorization server)认证资源所有者(resource owner)。一般就是一个登陆认证的过程,这个步骤大多发生在浏览器窗口并且它是流程中唯一一个对终端用户可见的步骤
- 如果用户对请求授权,服务器就会重定向到之前提供的重定向登陆点,客户端应用从那里得到返回给用户的code
- 使用这个授权码,客户端可以发送请求获取access_token
- 授权服务器认证了客户端,校验了授权码,并且确保在步骤2和步骤4提供的重定向登陆(redirection endpoint)点是否匹配,如果有效,授权服务器将返回
access token
(可选的refresh token
)。一旦客户端获取到了access token
,就可以代表用户发送请求API
请求授权码
授权请求其实就是让用户授权给客户端,并且授权服务器返回一个授权码
发送请求
客户端程序从the endpoint and the parameters
构造请求地址,如:
https://api.example-service.com/oauth/authorize?
response_type=code&
client_id=CLIENT_ID_EXAMPLE&
redirect_uri=REDIRECT_ENDPOINT_EXAMPLE
在请求中的一些参数是请求URL中的一部分,其中一些是强制的,而一些是可选的。参数解释:
- response_type: 强制参数,并且它的值必须是
code
- client_id: 强制参数,一般用于客户端到授权服务器的身份认证,值是来自客户端在授权服务器注册的数据
- redirect_uri: 可选参数,代表授权服务器提供授权码的端点,如果授权得到最终用户的批准
- scope: 可选参数,指明代表用户可以访问保护资源的哪一部分
- state: 可选参数,客户端使用这个大多是为了安全校验。当授权服务器重定向到带有授权码的
redirect_uri
的时候,它会额外的提供返回一个和之前请求一样值的state
参数。对于客户端开发安全预防是强烈推荐的
如果redirect_uri
没有提供,就会默认使用客户端程序在注册时候指定的重定向登陆点(redirect endpoint)
授权成功
如果用户同意授权,服务器将会重定向到client指定的登陆点:
https://client.example.com/oauth/cb?code=AUTHORIZATION_CODE&state=APP_STATE
授权错误
如果用户拒绝授权或者发生了一些错误,如参数缺失,无效的client_id,客户端也会重定向到登陆点,如:
https://client.example.com/oauth/cb?error=access_denied&state=APP_STATE
error
参数的值可能有:
- invalid_request: 在请求的url中缺失参数或值
- unauthorized_client: 客户端应用没有被授权
- access_denied: 终端用户拒绝这授权
- unsupported_response_type: 授权服务器不支持的请求响应类型
- invalid_scope: 指定的
scope
不存在或者无效 - server_error: 服务器内部发生错误
- temporarily_unavailable: 在给定的时间内服务器没有处理请求
除了error
参数,响应中还有其他类型:
- error_description: 可选参数,描述了错误的信息
- error_uri: 可选参数,uri指向一个web文档,包涵了错误信息的描述
- state: 强制参数,和请求中指定的
state
一样的值
请求Access Token
一旦客户端获取到code
,就可以请求获取access token
了
发送请求
根据登陆点和参数构造请求地址,如:
https://api.example-service.com/oauth/access_token?
grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=REDIRECT_EXAMPLE&
client_id=ID_EXAMPLE
请求中的以下参数是强制的:
- grant_type: 这个值必须设置成
authorization_code
- code: 从授权服务器获取到的授权码
- redirect_uri 授权服务器重定向到客户端和提供
access token
。另外,如果在请求获取授权码步骤中,客户端使用了这个参数,那么在获取授权码步骤使用的redirect_uri
必须和这个是一致的 - client_id: 客户端在授权服务器注册的时候提供的,和之前的一样
响应成功
如果在服务器端校验成功,POST
请求将会返回一个access_token
和一个可选的refresh_token
,返回的可能是一个json或者是xml,例如:
{
"access_token":"exampleAccessTokenValue123",
"expires_in":3600,
"refresh_token":"exampleRefreshTokenValue123",
"token_type":"Bearer"
}