一、接入要求

  1. 客户系统 支持 OAuth 2.0 Authentication Code 方式授权
  2. 客户系统 可以根据 Access Token 提供 使用者 信息(帐号、在神策系统中对应项目的角色)

二、OAuth 是什么

OAuth(Open Authorization 开放授权) 是一个授权标准,可以让 神策系统 获取到 使用者 的信息,但 使用者 却不需要提供帐号密码给 神策系统。

举个例子:今天我想要用 微X 帐号登录 知X,点击 微X 图示的时候,会跳出一个新的视窗让我输入帐号密码,输入完帐号密码之后,知X 就能拿到我在 微X 上的昵称、头像等信息,但这过程中我并没有将帐号密码提供给 知X。

注意:新视窗的网址是 微X 的域名,而不是 知X 的域名,所以 微X 的帐号密码是提供给 微X,而非 知X


而换到 神策系统 也是同理,只是其中的身分发生了改变。

知X → 神策系统(想知道要登录的 使用者 是属于什么角色)

微X → 客户系统(系统保存了 使用者 的帐号密码)

角色用作授权使用,让神策系统知道该帐号可以做什么及不可以做什么

所以神策的 OAuth 就是:使用者 使用 客户系统 的帐号密码,登录到客户自己的系统,但 神策系统 可以获取到 使用者 对应的角色。

三、有哪些配置

如需配置 OAuth2.0 登录,需要提供如下配置信息:

配置项配置说明范例
oauth_authorize_url

使用者在神策的 OAuth 的登录页面,点下登录按钮后,会跳转到哪里。

通常 客户系统的登录页面。

https://openapi.example.com/oauth/2.0/authorize
oauth_client_id

客户系统分配给神策的帐号。

因为客户系统可能不只有让神策接入OAuth,这是给 客户系统去区分,这个请求是谁来呼叫的。

SensorsData
oauth_client_secret

与上方 oauth_client_id 配合的密码。

因为帐号、密码是给客户系统 来区分请求来源的,所以客户可以随意制定,客户系统能辨识即可。

后续神策系统请求客户系统的 oauth_access_token_request_uri 时候,就会带上帐号、密码。

a1234567
oauth_redirect_uri

在 客户系统 上认证成功后的回调地址。

通常为神策系统的地址。

https://www.sensorsdata.cn/
oauth_access_token_request_uri在 户系统上,获取访问令牌的地址。https://openapi.example.com/oauth/2.0/token
default_fetcher_request_uri在客户系统上,获取使用者对应角色的地址。https://openapi.example.com/userinfo
oauth_scope获取用户讯息的权限列表,可选配置profile


一个完整的配置示例如下:

spadmin config set product_global -p sbp -n oauth_authorize_url -v "https://openapi.example.com/oauth/2.0/authorize"
spadmin config set product_global -p sbp -n oauth_client_id -v "SensorsData"
spadmin config set product_global -p sbp -n oauth_client_secret -v "a1234567"
spadmin config set product_global -p sbp -n oauth_redirect_uri -v "https://www.sensorsdata.cn/"
spadmin config set product_global -p sbp -n oauth_access_token_request_uri -v "https://openapi.example.com/oauth/2.0/token"
spadmin config set product_global -p sbp -n default_fetcher_request_uri -v "https://openapi.example.com/userinfo"
spadmin config set product_global -p sbp -n oauth_scope -v "openid email profile"
BASH
spadmin config set server -p sbp -m web -n oauth_authorize_url -v "https://openapi.example.com/oauth/2.0/authorize" 
spadmin config set server -p sbp -m web -n oauth_client_id -v "SensorsData" 
spadmin config set server -p sbp -m web -n oauth_client_secret -v "a1234567" 
spadmin config set server -p sbp -m web -n oauth_redirect_uri -v "https://www.sensorsdata.cn/" 
spadmin config set server -p sbp -m web -n oauth_access_token_request_uri -v "https://openapi.example.com/oauth/2.0/token" 
spadmin config set server -p sbp -m web -n default_fetcher_request_uri -v "https://openapi.example.com/userinfo" 
spadmin config set server -p sbp -m web -n oauth_scope -v "openid email profile"
BASH
spadmin config set server -p sa -m web -n oauth_authorize_url -v "https://openapi.example.com/oauth/2.0/authorize"
spadmin config set server -p sa -m web -n oauth_client_id -v "SensorsData"
spadmin config set server -p sa -m web -n oauth_client_secret -v "a1234567"
spadmin config set server -p sa -m web -n oauth_redirect_uri -v "https://www.sensorsdata.cn/"
spadmin config set server -p sa -m web -n oauth_access_token_request_uri -v "https://openapi.example.com/oauth/2.0/token"
spadmin config set server -p sa -m web -n default_fetcher_request_uri -v "https://openapi.example.com/userinfo"
spadmin config set server -p sa -m web -n oauth_scope -v "openid email profile"
BASH

配置完成后需要重启 web 生效:

spadmin restart -m web -p sbp
BASH
spadmin restart -m web -p sa
BASH

四、登录流程


0. 整体流程图

1. 使用者 登录

使用者 进入到 神策系统 的 OAuth 登录页面,点下登录按钮后,将跳转到 oauth_authorize_url 配置的地址。

仅配置完成后才会有 OAuth 的按钮。

跳转之后,使用者 应该要看到 客户系统 的登录页面,在这边 使用者 要输入自己在 客户系统 的帐号密码。

具体的跳转地址会是 oauth_authorize_url,后面带上 redirect_uri 参数,该参数为 使用者 登录成功后,要 302 跳转的地址。

例如:

https://openapi.example.com/oauth/2.0/authorize?
redirect_uri=https://www.sensorsdata.cn/api/oauth/auth?project=default&oauth_type=oauth&status=&client_id=SensorsData
BASH

这里只会带上 oauth_client_id 而不会带上 oauth_client_secret,因为 使用者 会直接看到这个地址,这里带上 oauth_client_secret 会导致密码泄漏

2. 产生 code

当 使用者 在 客户系统 上,输入完帐号密码并点击登录后,如果 客户系统 校验使用者的帐号密码成功,则带上一个随机 code 参数,跳转到请求参数上的 redirect_uri ,code 则作为该 使用者 的标记。

例如:

HTTP/1.1 302 Found

https://www.sensorsdata.cn/api/oauth/auth?
project=default&
oauth_type=oauth&
status=&
client_id=SensorsData&
code=example-code
BASH

如果校验 使用者 的帐号、密码失败,请不要进行跳转。

code 需由 客户系统 随机产生,作为该 使用者 的标示,后续 神策系统 会发送该 code 来请求该 使用者 的 access_token

3. 产生 access_token

神策系统 用 POST 方式呼叫 客户系统 的 oauth_access_token_request_uri 地址,并带上 code、client_id、client_secret 作为标示,获取 访问令牌 access_token。

例如:

https://openapi.example.com/oauth/2.0/token?
code=example-code&
grant_type=authorization_code&
client_secret=a1234567&
oauth_type=oauth&
client_id=SensorsData
BASH


默认情况下,获取 access_token 的请求会将所有的请求参数放在 URI 中,如果需要将请求的参数放在 request body 中,需要执行以下命令:

spadmin config set product_global -p sbp -n oauth_token_request_impl -v param_in_request_body
BASH
spadmin config set server -p sa -m web -n oauth_token_request_impl -v param_in_request_body
BASH
monitor_tools set_config -t server -m web -n oauth_token_request_impl -v param_in_request_body
BASH


如果客户的接口协议在headercontent-type不是application/json,需要用这个配置改变content-type的参数:

spadmin config set product_global -p sbp -n oauth_access_token_request_content_type -v 客户指定的content-type
BASH


如果有指定content-type的参数,且同时也有验证的需求,需要额外再配置验证用的参数oauth_access_token_request_authorization,此时会在header加上Authorization参数

spadmin config set product_global -p sbp -n oauth_access_token_request_authorization -v 客户指定的授权码
BASH


客户系统 需返回 access_token

{
    "access_token": "example-access-token"
}
BASH

照正式的 OAuth 规范,应该也要返回 refresh_token、expires_in 字段,但 神策 的 OAuth 系统,仅需要  access_token 字段即可,另外两个字段是否返回都不影响结果。


4. 返回 UserInfo

神策系统 默认 用 POST 方式呼叫 客户系统 的 default_fetcher_request_uri,并带上 access_token 作为标示,获取 使用者 对应的角色

https://openapi.example.com/userinfo?
access_token=example-access-token&
project=default
BASH

如果客户获取userInfo的请求只支持 GET  方式,需要sbp >= 1.1.0,并执行以下配置命令:

spadmin config set product_global -p sbp -n open_id_user_info_request_method -v GET
BASH

当以 POST 方式请求时,获取userInfo的请求会将所有的请求参数放在URI中,如果需要将请求的参数放在 request body 中,需要sbp >= 1.1.0,并执行以下配置命令:

spadmin config set product_global -p sbp -n user_info_fetcher_request_impl -v param_in_request_body
BASH

客户系统 需返回 UserInfo

{
 	"username":"xiaoming", 	// 使用者帐号(必选,不能存在中文字符及其他特殊字符,可以为邮箱格式或纯数字)
 	"user_cname":"小明",		// 使用者中文名称(可选,不返回时与 username 一致)
 	"role":"analyst"		// 使用者角色(可选,admin(管理员),analyst(分析师) 和 guest(普通用户), 若取其他值则按普通用户处理)
}
BASH

如果没有返回 role 字段,若该帐号在神策系统中已存在,那么使用其之前的角色;若该帐号不存在,则角色为普通用户。

如果没有返回 username 字段,则认为该帐号不存在。如果该帐号在神策系统没有权限,可以直接返回空 JSON 即可。

如果客户系统响应的 UserInfo 数据中没有username,但是有相关的字段用于用户的唯一标识,可通过以下配置映射。

SBP >= 1.1.0

spadmin config set product_global -p sbp -n default_user_info_user_name_field -v 客户UserInfo接口响应的账号唯一标识字段
BASH

用户角色描述请见 权限管理

5. 登录成功

使用者 登录 神策系统 成功,并以 UserInfo 接口返回的帐号和角色使用 神策系统。

五、特殊需求


1. 使用 OpenID 标准 UserInfo 接口格式

API 格式参考:OpenID UserInfo 接口

与神策定义的 UserInfo 接口的区别是请求是请求时不区分神策的项目信息,而且返回的 response 里面没有角色信息,例如:

{
 	"sub": "248289761001",
 	"name": "Jane Doe",
 	"given_name": "Jane",
 	"family_name": "Doe",
 	"preferred_username": "j.doe",
 	"email": "janedoe@example.com",
 	"picture": "http://example.com/janedoe/me.jpg"
}
BASH


神策分析会使用 preferred_username 字段作为 username(也作为显示名),同时使用默认的角色(即普通用户)进行登录。

如需使用该格式的 UserInfo 接口,需要开启如下配置:

spadmin config set product_global -p sbp -n use_open_id_user_info_fetcher -v true
BASH
spadmin config set server -p sa -m web -n use_open_id_user_info_fetcher -v true
BASH
monitor_tools set_config -t server -m web -n use_open_id_user_info_fetcher -v true
BASH


2. OAuth的 UserInfo 接口响应数据信息同步到神策系统(SBP >= 1.1.0)

sbp >= 1.1.0时:将OAuth的UserInfo接口的响应数据同步信息到神策系统,目前支持的信息有:用户姓名,手机号,邮箱
配置示例:

spadmin config set product_global -p sbp -n oauth_user_mapping_map -v "{\"userCname\":\"user_cname_field\",\"phone\":\"phone_field\",\"email\":\"email_field\"}"
BASH

说明:以k-v的形式配置,其中userCname、phone、email分别对应用户姓名,手机号和邮箱,不可修改。user_cname_field,phone_field,email_field为UserInfo接口响应的用户信息字段