全部产品
云市场

Javascript 前端web应用的OAuth2.0接入流程

更新时间:2019-09-06 11:12:26

本文档主要描述Javascript前端应用如何通过OAuth2.0接入CCP服务。 适用于: 纯前端的Javascript web应用, 比如chrome插件扩展,js Widget等。

由于是前端应用,您的应用中无法存放机密信息,比如 App 的 secret。所以认证流程和 Web服务应用流程又有所不同。

1. 介绍

(1) 原理: OAuth2.0 简化模式(implicit grant type)

简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了”授权码”这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。

(2) 纯前端单页面应用(SPA)用例:

a1

(3) widget 用例:

a2

2. 接入前提

(1) 创建Domain

首先,您需要在CCP官网控制台 https://ccp.console.aliyun.com 创建一个域(Domain)。创建完成后,会提供一个3级API域名 https://{domainId}.api.alicloudccp.com

(2) 启用登录页面

使用此种方式,还需要启用CCP提供的Auth登录页面。开通后,CCP会提供一个3级域名https://{domainId}.auth.alicloudccp.com

(3) 创建App(Client)

创建App,选择类型为”javascript 客户端应用”。确定App的访问Scope: 支持Scope列表, 这个Scope要在用户授权页面展示。配置redirect_uri。创建完成,可以得到 AppId(ClientId)。

3. 通过 JS SDK 接入获取token

(1) 引入api.js

  1. <script src="http://g.alicdn.com/ccp/1.0.0/api.js"></script>

(2) 调用signIn() 授权

  1. var client = new CCPAuthClient({
  2. client_id: APP_ID,
  3. scope: "FILE.READ",
  4. redirect_uri: 'http://a.com/callback'
  5. })
  6. //打开登录授权页面
  7. client.signIn().then(function(data){
  8. //授权成功, 拿到access_token
  9. var access_token = data.access_token;
  10. //保存到客户端...
  11. }).catch(function(err){
  12. //授权失败
  13. });

3. JS SDK 授权原理和调用的API

(1) /authorize 接口

调用 signIn() 方法,其实是打开新的窗口授权

  1. //打开新的窗口授权
  2. var authWin = window.open('/authorize?client_id='+APP_ID+'&response_type=token&state=abc&redirect_uri=http://mysite.com/callback', '_blank', 'location=0,status=0,titlebar=0,menubar=0,resizeable=0,height=500,width=600', true)
  3. authWin.onmessage=function(e){
  4. var hash = e.data;
  5. //解析hash, 得到access_token
  6. }

API 请求语法:

  1. GET /auth/authorize?client_id=<APPID>&response_type=token&state=[state]&redirect_uri=<redirect_uri> HTTP/1.1
  2. Host: {domainId}.api.alicloudccp.com
参数 是否必选 描述
client_id AppId, 如果没有请到官网控制台去创建。
redirect_uri 回调地址: 告诉认证服务在授权认证流程完成后重定向到哪里。一般是您的web服务提供的一个地址:比如:http://a.com/callback, 认证服务在授权完成后,会redirect到这个地址并且带上access_token等信息: http://a.com/callback#access_token=xxx&refresh_token=xxx&expires_time=xxx&token_type=Bearer 注意:这个redirect_uri 必须和您创建App时填写的redirect_uri 一致。
scope 访问范围列表,描述您的Web服务应用需要的访问权限范围,将在用户同意授权页面展示。请看支持Scope列表
response_type 此处固定为”token”
state 否,但推荐使用 如果请求中包含这个参数,认证服务器在重定向的时候会原封不动返回, 用于防止重放攻击。
prompt 在用户第一次登录完成后,是否需要展示 consent 页面。可选值: none, consent。如果为none则不展示,直接跳过。

(2) 重定向回 /callback

  • 成功举例: http://a.com/callback#access_token=xxx&refresh_token=xxx&expires_time=xxx&token_type=Bearer
  • 失败举例: http://a.com/callback#error=xxxxxx

/callback 页面举例:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>callback</title>
  5. </head>
  6. <body>
  7. <script>
  8. var hash = location.hash;
  9. if(hash){
  10. window.postMessage(hash) //向宿主页面发送hash, js sdk 可以得到hash
  11. window.location.replace('/callback') //清除历史记录
  12. }else{
  13. window.close() //replace 后没有hash,关闭窗口
  14. }
  15. </script>
  16. </body>
  17. </html>

(3) 解析hash 得到access_token

JS SDK 解析callback页面发送过来的hash, 得到 access_token。

4. 调用CCP 服务API

前端应用可以直接使用 AccessToken 调用 CCP API。只需在请求头的Authorization中带上AccessToken。

调用方式举例:

API 请求语法:

  1. GET /v2/files/list HTTP /1.1
  2. Host: {domainId}.auth.alicloudapp.com
  3. Authorization: Bearer {AccessToken}

5. 刷新Token

(1) 请求方式举例:

API 请求语法:

  1. POST /v2/oauth/token/v2/auth/refresh_token HTTP/1.1
  2. Host: {domainId}.api.alicloudapp.com
  3. Content-Type: application/x-www-form-urlencoded
  4. refresh_token=xxx\
  5. &client_id=xxx\
  6. &client_secret=xxx\
  7. &grant_type=refresh_token

请求参数

参数名称 是否必选 描述
refresh_token 用授权码换取访问令牌时获得的刷新令牌。
client_id 应用的身份 ID。
grant_type 根据 OAuth 2.0 协议, 取值为:refresh_token。
client_secret 应用的密钥,用作换取访问令牌时鉴定应用身份的密码。

(2) 返回

  1. HTTP/1.1 200 OK
  2. Content-Type: application/json
  3. {
  4. "access_token":"xxxxxxxxx",
  5. "expires_in":3920,
  6. "expires_time":"2019-11-11T10:10:10.009Z",
  7. "token_type":"Bearer"
  8. }

返回参数

参数名称 描述
access_token 新的访问令牌。应用可以使用新的访问令牌来访问阿里云 API。
expires_in 访问令牌的剩余有效时间,单位为秒。
expires_time 访问令牌的失效时间,ISO时间格式。
token_type 访问令牌的类型。取值为:Bearer。

说明: 本次请求的返回值与用授权码换取访问令牌的返回值一致,但不包含 refresh_token。