十分鐘實現單點登陸

單點登陸(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"}複製代碼

更多字段解釋請參考用戶信息字段含義

相關文章
相關標籤/搜索