OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 OAuth的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 OAuth是安全的。OAuth 是 Open Authorization 的简写。
OAuth 本身不存在一个标准的实现,后端开发者自己根据实际的需求和标准的规定实现。其步骤一般如下:
任何身份认证,本质上都是基于对请求方的不信任所产生的。同时,请求方是信任被请求方的,例如用户请求服务时,会信任服务方。
所以,身份认证就是为了解决身份的可信任问题。
在OAuth中,简单来说有三方:用户(这里是指属于服务方的用户)、服务方、第三方应用。
服务方不信任用户,所以需要用户提供密码或其他可信凭据;
服务方不信任第三方,所以需要第三方提供自已交给它的凭据(通常的一些安全签名之类的就是);
用户部分信任第三方,所以用户愿意把自已在服务方里的某些服务交给第三方使用,但不愿意把自已在服务方的密码交给第三方;
在oauth2.0的流程中,用户登录了第三方的系统后,会先跳去服务方获取一次性用户授权凭据,再跳回来把它交给第三方,第三方的服务器会把授权凭据以及服务方给它的的身份凭据一起交给服务方,这样,服务方一可以确定第三方得到了用户对此次服务的授权(根据用户授权凭据),二可以确定第三方的身份是可以信任的(根据身份凭据),所以,最终的结果就是,第三方顺利地从服务方获取到了此次所请求的服务。
从上面的流程中可以看出,oauth2.0完整地解决掉了用户、服务方、第三方 在某次服务时这三者之间的信任问题。
Oauth2.0基本流程:
原理很简单,用户访问App,App访问Authorization Server请求权限,
Authorization Server得到用户同意后,返回token,
App通过这个token向Authorization Server索要数据,
App只能从Authorization Server这个中介获取服务器数据,而无法直接访问Resource Server。
客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式。
授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。
它的步骤如下:
下面是上面这些步骤所需要的参数。
步骤1: 客户端申请认证的URI,包含以下参数:
例子:
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 HTTP/1.1 Host: server.example.com
对比微信网页扫描授权请求CODE
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
步骤3:服务器回应客户端的URI,包含以下参数:
例子:
HTTP/1.1 302 Found Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA &state=xyz
步骤4:客户端向认证服务器申请令牌的HTTP请求,包含以下参数:
例子:
POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
步骤5:认证服务器发送的HTTP回复,包含以下参数:
例子:
HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache { "access_token":"2YotnFZFEjr1zCsicMWpAA", "token_type":"example", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter":"example_value" }
从上面代码可以看到,相关参数使用JSON格式发送(Content-Type: application/json)。此外,HTTP头信息中明确指定不得缓存。
如果用户访问的时候,客户端的"访问令牌"已经过期,则需要使用"更新令牌"申请一个新的访问令牌。客户端发出更新令牌的HTTP请求,包含以下参数:
例子:
POST /token HTTP/1.1
Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA