準(zhǔn)備工作
本節(jié)介紹如何將OneAuth 與您的SPA應(yīng)用集成雕沿,使用OneAuth作為SPA應(yīng)用的用戶存儲(chǔ)庫(kù)并實(shí)現(xiàn)用戶登錄嫩海。
如果您正在構(gòu)建一個(gè)由服務(wù)器端渲染的Web應(yīng)用积锅,參考Web應(yīng)用集成用戶登錄
前提條件:
已經(jīng)具備了OneAuth的組織賬戶枣氧。如果沒(méi)有萨咳?免費(fèi)創(chuàng)建
具備基礎(chǔ)的JavaScript開(kāi)發(fā)經(jīng)驗(yàn)
有SPA應(yīng)用或正在構(gòu)建的工程需要接入認(rèn)證流程
如果你沒(méi)有相關(guān)的應(yīng)用,只是期望學(xué)習(xí)如何使用巨税,建議參考如下的資料 :
Vue.js quickstart
教您構(gòu)建Vue.js應(yīng)用程序的基礎(chǔ)知識(shí)蟋定,Vue Quickstart
或者,如果您想快速開(kāi)始草添,只需下載一個(gè)應(yīng)用示例溢吻,請(qǐng)下載我們的Vue示例。
在OneAuth控制臺(tái)創(chuàng)建SPA應(yīng)用
在您使用OneAuth可以登錄用戶之前果元,您需要在管理后臺(tái)創(chuàng)建一個(gè)單頁(yè)應(yīng)用用于的OneAuth的 應(yīng)用集成促王。
使用您的管理員帳戶登錄您的OneAuth組織。
在管理后臺(tái)而晒,選擇 應(yīng)用 > 應(yīng)用
點(diǎn)擊 創(chuàng)建應(yīng)用
選擇OIDC-Openid Connect認(rèn)證方式
選擇SPA 單頁(yè)面應(yīng)用 應(yīng)用類型蝇狼,點(diǎn)擊下一步
填寫(xiě)應(yīng)用名稱,應(yīng)用描述(可選)
用戶授權(quán)方式選擇Authorization Code倡怎,這將為您的SPA啟用帶有 PKCE 的授權(quán)碼流迅耘,并能夠在訪問(wèn)令牌過(guò)期時(shí)刷新訪問(wèn)令牌,而不會(huì)提示用戶重新進(jìn)行身份驗(yàn)證监署。
輸入登錄重定向的地址 颤专,例如,添加本地開(kāi)發(fā)環(huán)境的地址:
http://localhost:3000/callback
,或者生產(chǎn)環(huán)境的地址:https://app.example.com/callback
钠乏。點(diǎn)擊保存
添加CORS安全域名栖秕,選擇API>安全域,點(diǎn)擊添加域晓避,填寫(xiě)名稱和安全域的URI,例如本地調(diào)試環(huán)境
http://localhost:8080
, 或者生產(chǎn)環(huán)境的URIhttps://app.example.com
在新建的SPA應(yīng)用的授權(quán)用戶 Tab頁(yè)面簇捍,選擇授權(quán)給Everyone或需要限制在某個(gè)Group進(jìn)行訪問(wèn)。
安裝SDK
npm i --save @oneauth/sdk-core @oneauth/sdk-vue
@oneauth/sdk-core 會(huì)提供登錄登出和鑒權(quán)所需的方法俏拱,@oneauth/sdk-vue 中會(huì)提供對(duì)路由的鑒權(quán)功能和準(zhǔn)備好的登錄重定向頁(yè)面
@oneauth/sdk-core 可單獨(dú)使用暑塑。也可搭配@oneauth/sdk-vue 使用。本文使用@oneauth/sdk-core 和 @oneauth/sdk-vue 共同來(lái)完成vue2.0的集成锅必。
配置 sdk
初始化時(shí)需要傳入 issuer
事格, clientId
, redirectUri
搞隐, scopes
驹愚, 這些值可以從 oneauth 控制臺(tái)得到,
實(shí)例化@oneauth/sdk-core 和@oneauth/sdk-vue
import App from "./App.vue";
import router from "./router";
import OneAuth from "@oneauth/sdk-core";
import OneAuthVue from "@oneauth/sdk-vue";
const oneAuth = new OneAuth({
issuer: `kang.oneauth.cn/oauth/v1`,
clientId: `2YXXZ78611K0c8906MX6RJ8c0s84VcQB`,
redirectUri: `http://localhost:8080/callback`,
scopes: ["openid", "profile", "email"],
});
初始化@oneauth/sdk-core
- 登錄
調(diào)用oneauth.login
尔许,傳入originalUri
參數(shù)么鹤,則會(huì)在登錄完成之后跳轉(zhuǎn)回這個(gè)網(wǎng)址
oneauth.login({
originalUri: 'http://localhost:3000/originalUri',
});
- 登出
調(diào)用oneauth.logout
oneauth.logout();
- 獲取 accessToken
const accessToken = oneauth.accessToken;
- 獲取 idToken
const idToken = oneauth.idToken;
- 獲取用戶信息
可傳入泛型,以獲得類型約束
type User = unknown;
const userInfo = await oneauth.getUserInfo<User>();
- 獲取當(dāng)前用戶的登錄狀態(tài)
/**
* 是否登錄了
**/
const isAuthed = await oneauth.isAuthenticated();
- 校驗(yàn)從登錄重定向頁(yè)面獲取的 code 和 state
登錄之后味廊,oneauth 會(huì)重定向到實(shí)例化時(shí)傳入的redirectUri
對(duì)應(yīng)的頁(yè)面蒸甜。
并在 query 中帶上參數(shù)code
和state
棠耕。
將參數(shù)傳入本方法佑淀,返回布爾值还绘,標(biāo)識(shí) code 是否有效
const isValid = await oneauth.verify(code, state);
注入$oneauth
把 @oneauth/sdk-core 實(shí)例注入到 Vue 的原型上
Vue.use(OneAuthVue, {
oneAuth,
});
添加登錄按鈕
在頁(yè)面中添加一個(gè)按鈕,并對(duì)其調(diào)用
this.$oneauth.login();
<template>
<button @click="login">login</button>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
@Component({
components: {},
})
export default class App extends Vue {
private login() {
this.$oneAuth.login();
}
}
</script>
添加回調(diào)路由
從@oneauth/sdk-vue 得到登錄重定向頁(yè)面殊者,并配置到路由中恨憎。 路由的路徑需要與@oneauth/sdk-core 的實(shí)例化參數(shù)redirectUri一致蕊退。
import { LoginCallback } from "@oneauth/sdk-vue";
const routes: Array<RouteConfig> = [
{
path: "/callback",
component: LoginCallback,
},
];
對(duì)特定路由進(jìn)行認(rèn)證鑒權(quán)
從@oneauth/sdk-vue 中獲取導(dǎo)航守衛(wèi)navigationGuard,并配置到路由中憔恳。
在需要鑒權(quán)的路由的 meta 中配置 auth 屬性這樣瓤荔,在打開(kāi)該路由時(shí)都會(huì)檢查是否登錄了。
如果沒(méi)有登錄則會(huì)跳轉(zhuǎn)到登錄頁(yè),登錄完成后會(huì)跳轉(zhuǎn)回來(lái)钥组。
import { LoginCallback, navigationGuard } from "@oneauth/sdk-vue";
const routes: Array<RouteConfig> = [
{
path: "/callback",
component: LoginCallback,
},
{
path: "/about",
name: "About",
meta: {
auth: true,
},
component: () => import("../views/About.vue"),
},
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
});
router.beforeEach(navigationGuard);
export default router;
SPA與刷新令牌(Refresh token)
作為公共客戶端實(shí)現(xiàn)的單頁(yè)應(yīng)用(SPA)程序输硝,無(wú)法安全地在瀏覽器中存儲(chǔ)和處理刷新令牌,因此必須使用不依賴刷新令牌的方法程梦,除非其授權(quán)服務(wù)器對(duì)刷新令牌的泄漏風(fēng)險(xiǎn)采取了安全措施(如使用刷新令牌輪換或具有使用約束條件的刷新令牌)点把。在許多情況下,尤其是對(duì)于公共客戶機(jī)的SPA應(yīng)用屿附,發(fā)行到期時(shí)間較短的訪問(wèn)令牌并在需要時(shí)更新令牌被認(rèn)為是一種最佳做法郎逃,因此在用戶會(huì)話存在的整個(gè)過(guò)程中都可能需要更新新令牌。
但是挺份,將用戶重定向到OpenID提供方并返回會(huì)帶來(lái)用戶體驗(yàn)的挑戰(zhàn)褒翰,有可能會(huì)中斷用戶的體驗(yàn),因此通常不希望在正常導(dǎo)航期間將用戶重定向到登錄頁(yè)面压恒。為了避免這種破壞性重定向影暴,一個(gè)改進(jìn)的措施是在應(yīng)用程序中使用隱藏的iframe進(jìn)行重定向错邦,/authorize
端點(diǎn)允許使用名為 prompt
的請(qǐng)求參數(shù)探赫,并將prompt
參數(shù)設(shè)置為none
,以避免中斷用戶體驗(yàn)撬呢。如果 prompt 參數(shù)的值為 none伦吠,這將保證不會(huì)提示用戶登錄,無(wú)論他們是否有活動(dòng)會(huì)話魂拦。
如果用戶具有有效會(huì)話毛仪,則應(yīng)用程序?qū)⒔邮招铝钆啤H绻麤](méi)有芯勘,應(yīng)用程序?qū)⑹盏藉e(cuò)誤響應(yīng)箱靴,并且可以再次重定向用戶,而無(wú)需使用prompt=none
選項(xiàng)觸發(fā)身份驗(yàn)證荷愕。OneAuth在提供SDK中包含相關(guān)的設(shè)計(jì)衡怀,使應(yīng)用程序更容易執(zhí)行此操作棍矛。到目前為止,prompt
參數(shù)是 SPA 維持用戶會(huì)話而不提示用戶多次登錄的唯一最佳實(shí)踐抛杨。
智能跟蹤防護(hù) (ITP) 和增強(qiáng)型跟蹤防護(hù) (ETP) 等瀏覽器隱私控制的引入會(huì)影響瀏覽器處理第三方 cookie 的方式够委。這些瀏覽器隱私控制防止使用 OneAuth 會(huì)話 cookie 以靜默方式更新用戶會(huì)話,這會(huì)迫使用戶重新進(jìn)行身份驗(yàn)證怖现,對(duì)無(wú)縫的用戶體驗(yàn)產(chǎn)生影響茁帽。
刷新令牌輪換為 SPA 提供了一種在 ITP 瀏覽器中維護(hù)用戶會(huì)話的解決方案。由于刷新令牌獨(dú)立于任何 cookie屈嗤,因此您不必依賴 OneAuth會(huì)話 cookie 來(lái)更新訪問(wèn)和 ID 令牌潘拨。
如果應(yīng)用程序和 OneAuth 在同一個(gè)域中,并不會(huì)受到影響饶号,您仍然可以使用 OneAuth 會(huì)話 cookie 并靜默更新令牌战秋。
支持服務(wù)
如果您需要幫助或有問(wèn)題,請(qǐng)?jiān)?OneAuth開(kāi)發(fā)者論壇上發(fā)布問(wèn)題 OneAuth 開(kāi)發(fā)者論壇讨韭。