十分钟实现单点登陆

单点登陆(Single Sign On),简称为SSO,是目前比较流行的企业业务整合的解决方案之一。 SSO的定义是在多个应用系统中,用户只须要登陆一次就能够访问全部相互信任的应用系统。

更好的阅读体验请访问:docs.authing.cn/authing/qui…javascript

开始以前

若是你不了解用户池、单点登陆和认证受权,建议先阅读基础概念html

预备知识

  1. 基本的 HTML 和 CSS 知识java

  2. 中级 JavaScript 技能git

所需工具

  1. 你喜欢的文本编辑器github

  2. 能够在本地运行的 Web 服务器(好比:npm install http-server -gweb

注册一个 Authing 帐号

若是你尚未帐号,请点击这里注册 Authing 帐号,注册完成后请进入控制台并建立一个用户池。算法


建立一个 OIDC 应用

第三方登陆 -> OIDC 应用选项卡,点击蓝色的「建立 OIDC 应用」按钮。npm

填上你的应用名,指定此 OIDC 应用的二级域名(认证地址),回调地址,其余参数保留默认便可。点击「肯定」。
配置 OIDC 应用

参数解释json

认证地址,一个 authing.cn 的二级域名,用户将在此网址进行登陆。浏览器

回调 URL,OIDC 登陆成功后,回调到开发者本身业务的地址。本教程为演示,填写的地址是 http://localhost:8080,实际场景下要填写本身的业务地址。

在应用列表中点击刚建立好的应用,记录下 AppID,二级域名,供之后使用。

使用 AuthingSSO SDK 集成单点登陆

建立一个空白的 HTML 文档用来编写 Authing 程序

本教程只是为了演示,所以咱们没选择高级框架,这可让咱们专一于 Authing 自己。

<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <meta http-equiv="X-UA-Compatible" content="ie=edge" />    <title>Authing SSO Example</title>  </head>  <body></body></html>复制代码

添加三个按钮

增长三个按钮控件到 body 中,目的是为了演示如何使用 SDK 管理单点登陆状态。

<button id="btn-login">login</button><button id="btn-track-session">trackSession</button><button id="btn-logout">logout</button>复制代码



引入 AuthingSSO 并初始化

从 CDN 加载 AuthingSSO 的 SDK。填入你的 OIDC 应用 ID 和 域名,进行初始化。

<script src="https://cdn.jsdelivr.net/npm/@authing/sso/dist/AuthingSSO.umd.min.js"></script><script> let auth = new AuthingSSO({ appId: "YOUR_OIDC_APP_ID", appType: "oidc", appDomain: "OIDC_APP_DOMAIN.authing.cn" });</script>复制代码

为按钮注册点击事件

达到的效果是:

  • 点击 login 按钮,浏览器会跳转到 OIDC 登陆页面,与用户完成身份确认。

  • 点击 trackSession 按钮,会显示当前登陆状态。

  • 点击 logout 按钮,进行单点登出。

let login = document.getElementById("btn-login");let trackSession = document.getElementById("btn-track-session");let logout = document.getElementById("btn-logout");login.onclick = function() {  auth.login();};trackSession.onclick = async function() {  let res = await auth.trackSession();  alert(JSON.stringify(res));};logout.onclick = async function() {  let res = await auth.logout();  alert(JSON.stringify(res));};复制代码

完整代码

<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <meta http-equiv="X-UA-Compatible" content="ie=edge" />    <title>Authing SSO Example</title>  </head>  <body>    <button id="btn-login">login</button>    <button id="btn-track-session">trackSession</button>    <button id="btn-logout">logout</button>    <script src="https://cdn.jsdelivr.net/npm/@authing/sso/dist/AuthingSSO.umd.min.js"></script>    <script>      let auth = new AuthingSSO({        appId: "YOUR_OIDC_APP_ID",        appType: "oidc",        appDomain: "OIDC_APP_DOMAIN.authing.cn"      });      let login = document.getElementById("btn-login");      let trackSession = document.getElementById("btn-track-session");      let logout = document.getElementById("btn-logout");      login.onclick = function() {        auth.login();      };      trackSession.onclick = async function() {        let res = await auth.trackSession();        alert(JSON.stringify(res));      };      logout.onclick = async function() {        let res = await auth.logout();        alert(JSON.stringify(res));      };    </script>  </body></html>复制代码

示例代码可从 Github 上找到,建议将 Github 上的代码下载运行。

运行方法

在终端中运行如下命令

$ git clone https://github.com/Authing/authing-sso-demo
$ cd authing-sso-demo
$ npm install -g http-server
$ http-server复制代码

以后在浏览器访问 http://localhost:8080

若是本地 8080 端口已被占用,应用可能会运行在 808一、8082 等后续端口。

运行效果

最初,咱们没有登陆,所以,点击 trackSession 按钮获取到的登陆状态为空。

如今咱们点击 login 按钮,会跳转到 OIDC 应用的用户认证页面,输入用户名密码进行登陆。

浏览器被重定向到咱们以前设置的回调连接,记下 code 参数,用于后面换取用户信息。

点击 trackSession 按钮,此时可以获取到该用户的登陆状态,包括用户 ID,应用 ID,应用类型。

点击 logout 按钮,输出单点登出成功。

此时咱们再点击 trackSession 按钮,可见登陆状态为空,说明用户已经单点登出了。

获取用户信息

使用 OIDC 流程中返回的 code 换取 access_token

向如下地址发送 POST 请求:

POST https://OIDC_APP_DOMAIN.authing.cn/oauth/oidc/token复制代码

body 参数

参数名

意义

client_id

OIDC 应用的 app_id

redirect_uri

在控制台配置的 OIDC 回调 url 其中的一个值

scope

须要请求的权限,若是须要获取 email 和手机号须要有 phone email,若是须要 refresh_token 须要包含 offline_access 参考 scope 表格

response_type

OIDC 模式,能够为 code, id_token, id_token token, code id_token, code token, code id_token token 参考 OIDC 规范

prompt

能够为 none,login,consent 或 select_account,指定 AP 与 End-User 的交互方式,如需 refresh_token,必须为 consent 参考 OIDC 规范

state

一个随机字符串,用于防范 CSRF 攻击,若是 response 中的 state 值和发送请求以前设置的 state 值不一样,说明受到攻击

nonce

一个随机字符串,用于防范 Replay 攻击

返回示例

{  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InIxTGtiQm8zOTI1UmIyWkZGckt5VTNNVmV4OVQyODE3S3gwdmJpNmlfS2MifQ.eyJqdGkiOiJ4R01uczd5cmNFckxiakNRVW9US1MiLCJzdWIiOiI1YzlmNzVjN2NjZjg3YjA1YTkyMWU5YjAiLCJpc3MiOiJodHRwczovL2F1dGhpbmcuY24iLCJpYXQiOjE1NTQ1Mzc4NjksImV4cCI6MTU1NDU0MTQ2OSwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBvZmZsaW5lX2FjY2VzcyBwaG9uZSBlbWFpbCIsImF1ZCI6IjVjYTc2NWUzOTMxOTRkNTg5MWRiMTkyNyJ9.wX05OAgYuXeYM7zCxhrkvTO_taqxrCTG_L2ImDmQjMml6E3GXjYA9EFK0NfWquUI2mdSMAqohX-ndffN0fa5cChdcMJEm3XS9tt6-_zzhoOojK-q9MHF7huZg4O1587xhSofxs-KS7BeYxEHKn_10tAkjEIo9QtYUE7zD7JXwGUsvfMMjOqEVW6KuY3ZOmIq_ncKlB4jvbdrduxy1pbky_kvzHWlE9El_N5qveQXyuvNZVMSIEpw8_y5iSxPxKfrVwGY7hBaF40Oph-d2PO7AzKvxEVMamzLvMGBMaRAP_WttBPAUSqTU5uMXwMafryhGdIcQVsDPcGNgMX6E1jzLA",  "expires_in": 3600,  "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InIxTGtiQm8zOTI1UmIyWkZGckt5VTNNVmV4OVQyODE3S3gwdmJpNmlfS2MifQ.eyJzdWIiOiI1YzlmNzVjN2NjZjg3YjA1YTkyMWU5YjAiLCJub25jZSI6IjIyMTIxIiwiYXRfaGFzaCI6Ik5kbW9iZVBZOEFFaWQ2T216MzIyOXciLCJzaWQiOiI1ODM2NzllNC1lYWM5LTRjNDEtOGQxMS1jZWFkMmE5OWQzZWIiLCJhdWQiOiI1Y2E3NjVlMzkzMTk0ZDU4OTFkYjE5MjciLCJleHAiOjE1NTQ1NDE0NjksImlhdCI6MTU1NDUzNzg2OSwiaXNzIjoiaHR0cHM6Ly9hdXRoaW5nLmNuIn0.IQi5FRHO756e_eAmdAs3OnFMU7QuP-XtrbwCZC1gJntevYJTltEg1CLkG7eVhdi_g5MJV1c0pNZ_xHmwS0R-E4lAXcc1QveYKptnMroKpBWs5mXwoOiqbrjKEmLMaPgRzCOdLiSdoZuQNw_z-gVhFiMNxI055TyFJdXTNtExt1O3KmwqanPNUi6XyW43bUl29v_kAvKgiOB28f3I0fB4EsiZjxp1uxHQBaDeBMSPaRVWQJcIjAJ9JLgkaDt1j7HZ2a1daWZ4HPzifDuDfi6_Ob1ZL40tWEC7xdxHlCEWJ4pUIsDjvScdQsez9aV_xMwumw3X4tgUIxFOCNVEvr73Fg",  "refresh_token": "WPsGJbvpBjqXz6IJIr1UHKyrdVF",  "scope": "openid profile offline_access phone email",  "token_type": "Bearer"}复制代码

验证 access_token 和 id_token 的合法性

OIDC 默认使用 OIDC 应用的 secret 对 token 进行验证(也就是在建立应用时默认选择 HS256 算法)。 若是你使用 javascript 那么可使用 jsonwebtoken 进行验证:

const jwt = require('jsonwebtoken');复制代码
let decoded = jwt.verify(token, <appSecret>);复制代码

若是是其余语言,那么你在服务端须要用 app_secret 做为 HS256 签名参数来计算签名和 JWT 中的签名进行对比,伪代码以下:

HMACSHA256(  base64UrlEncode(header) + "." +  base64UrlEncode(payload),  "1133fd20c14e4cc29b6ecb71fb8eb952"// app_secret)复制代码

若是是 RS256 等非对称加密算法,须要使用公钥验证签名。Authing 将使用私钥进行签名,请使用 Authing 的公钥来验证签名:

-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxRijj2seoesv5K0Z+ymRK7DSDPxdsM2sGQD2ZVhLjLsxZWJtXUXh7ERdUU6OT3BqYZZf7CLIhN6yyNtTOgfgpLG9HVJd7ZSKzuy2dS7mo8jD8YRtptAJmNFqw6z8tQp5MNG1ZHqp9isKqJmx/CFYkRdXBmjjj8PMVSP757pkC3jCq7fsi0drSSg4lIxrSsGzL0++Ra9Du71Qe/ODQKU0brxaI1OKILtfcVPTHTaheV+0dw4eYkSDtyaLBG3jqsQbdncNg8PCEWchNzdO6aajUq4wbOzy/Ctp399mz0SGKfuC5S8gqAFABFT3DH3UD21ZztQZwFEV2AlvF+bcGEstcwIDAQAB-----END PUBLIC KEY-----复制代码

使用 access_token 换取用户信息

开发者在本身的服务中可使用 access_token 换取用户信息。根据 scope 的不一样,这里的返回信息也会有所不一样,字段符合 OIDC 规范,字段解释请参考用户信息字段含义。 请求连接:

GET https://users.authing.cn/oauth/oidc/user/userinfo?access_token=<access_token>复制代码

返回示例:

{  "sub": "<用户在 Authing 的惟一标识>",  "nickname": "Authing",  "name": "张三",  "locale": "en-US"}复制代码

更多字段解释请参考用户信息字段含义

相关文章
相关标签/搜索