Browse Source

feat(vben5): Use secure storage for oidc data

pull/1261/head
colin 7 months ago
parent
commit
83a5b5d341
  1. 53
      apps/vben5/apps/app-antd/src/auth/authService.ts
  2. 15
      apps/vben5/apps/app-antd/src/store/auth.ts
  3. 2
      apps/vben5/packages/@abp/account/package.json
  4. 1
      apps/vben5/packages/@abp/account/src/hooks/index.ts
  5. 43
      apps/vben5/packages/@abp/account/src/hooks/useOidcClient.ts
  6. 53
      apps/vben5/packages/@abp/account/src/utils/auth.ts
  7. 1
      apps/vben5/packages/@abp/account/src/utils/index.ts

53
apps/vben5/apps/app-antd/src/auth/authService.ts

@ -1,53 +0,0 @@
import { useAppConfig } from '@vben/hooks';
import { UserManager, WebStorageStateStore } from 'oidc-client-ts';
const { authority, audience, clientId, clientSecret, disablePKCE } =
useAppConfig(import.meta.env, import.meta.env.PROD);
const userManager = new UserManager({
authority,
client_id: clientId,
client_secret: clientSecret,
redirect_uri: `${window.location.origin}/signin-callback`,
response_type: 'code',
scope: audience,
post_logout_redirect_uri: `${window.location.origin}/`,
silent_redirect_uri: `${window.location.origin}/silent-renew.html`,
automaticSilentRenew: true,
loadUserInfo: true,
userStore: new WebStorageStateStore({ store: window.localStorage }),
disablePKCE,
});
export default {
async login() {
return userManager.signinRedirect();
},
async logout() {
return userManager.signoutRedirect();
},
async refreshToken() {
return userManager.signinSilent();
},
async getAccessToken() {
const user = await userManager.getUser();
return user?.access_token;
},
async isAuthenticated() {
const user = await userManager.getUser();
return !!user && !user.expired;
},
async handleCallback() {
return userManager.signinRedirectCallback();
},
async getUser() {
return userManager.getUser();
},
};

15
apps/vben5/apps/app-antd/src/store/auth.ts

@ -10,6 +10,7 @@ import { preferences } from '@vben/preferences';
import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
import {
useOidcClient,
usePhoneLoginApi,
useProfileApi,
useQrCodeLoginApi,
@ -21,7 +22,6 @@ import { notification } from 'ant-design-vue';
import { defineStore } from 'pinia';
import { useAbpConfigApi } from '#/api/core/useAbpConfigApi';
import authService from '#/auth/authService';
import { $t } from '#/locales';
export const useAuthStore = defineStore('auth', () => {
@ -36,12 +36,13 @@ export const useAuthStore = defineStore('auth', () => {
const userStore = useUserStore();
const abpStore = useAbpStore();
const router = useRouter();
const oidcClient = useOidcClient();
const loginLoading = ref(false);
async function refreshSession() {
if (await authService.getAccessToken()) {
const user = await authService.refreshToken();
if (await oidcClient.getAccessToken()) {
const user = await oidcClient.refreshToken();
const newToken = `${user?.token_type} ${user?.access_token}`;
accessStore.setAccessToken(newToken);
if (user?.refresh_token) {
@ -61,12 +62,12 @@ export const useAuthStore = defineStore('auth', () => {
}
async function oidcLogin() {
await authService.login();
await oidcClient.login();
}
async function oidcCallback() {
try {
const user = await authService.handleCallback();
const user = await oidcClient.handleCallback();
return await _loginSuccess({
accessToken: user.access_token,
tokenType: user.token_type,
@ -127,9 +128,9 @@ export const useAuthStore = defineStore('auth', () => {
async function logout(redirect: boolean = true) {
try {
if (await authService.getAccessToken()) {
if (await oidcClient.getAccessToken()) {
accessStore.setAccessToken(null);
await authService.logout();
await oidcClient.logout();
}
} catch {
// 不做任何处理

2
apps/vben5/packages/@abp/account/package.json

@ -37,6 +37,8 @@
"@vueuse/core": "catalog:",
"@vueuse/integrations": "catalog:",
"ant-design-vue": "catalog:",
"oidc-client-ts": "catalog:",
"secure-ls": "catalog:",
"vue": "catalog:*",
"vue-router": "catalog:"
}

1
apps/vben5/packages/@abp/account/src/hooks/index.ts

@ -1 +1,2 @@
export * from './useOAuthError';
export * from './useOidcClient';

43
apps/vben5/packages/@abp/account/src/hooks/useOidcClient.ts

@ -0,0 +1,43 @@
import { userManager } from '../utils/auth';
export function useOidcClient() {
async function login() {
return userManager.signinRedirect();
}
async function logout() {
return userManager.signoutRedirect();
}
async function refreshToken() {
return userManager.signinSilent();
}
async function getAccessToken() {
const user = await userManager.getUser();
return user?.access_token;
}
async function isAuthenticated() {
const user = await userManager.getUser();
return !!user && !user.expired;
}
async function handleCallback() {
return userManager.signinRedirectCallback();
}
async function getUser() {
return userManager.getUser();
}
return {
login,
logout,
refreshToken,
getAccessToken,
isAuthenticated,
handleCallback,
getUser,
};
}

53
apps/vben5/packages/@abp/account/src/utils/auth.ts

@ -0,0 +1,53 @@
import { useAppConfig } from '@vben/hooks';
import { UserManager, WebStorageStateStore } from 'oidc-client-ts';
import SecureLS from 'secure-ls';
const { authority, audience, clientId, clientSecret, disablePKCE } =
useAppConfig(import.meta.env, import.meta.env.PROD);
const env = import.meta.env.PROD ? 'prod' : 'dev';
const appVersion = import.meta.env.VITE_APP_VERSION;
const namespace = `${import.meta.env.VITE_APP_NAMESPACE}-${appVersion}-${env}`;
const ls = new SecureLS({
encodingType: 'aes',
encryptionSecret: import.meta.env.VITE_APP_STORE_SECURE_KEY,
isCompression: true,
// @ts-ignore secure-ls does not have a type definition for this
metaKey: `${namespace}-secure-oidc`,
});
export const userManager = new UserManager({
authority,
client_id: clientId,
client_secret: clientSecret,
redirect_uri: `${window.location.origin}/signin-callback`,
response_type: 'code',
scope: audience,
post_logout_redirect_uri: `${window.location.origin}/`,
silent_redirect_uri: `${window.location.origin}/silent-renew.html`,
automaticSilentRenew: true,
loadUserInfo: true,
userStore: new WebStorageStateStore({
store: import.meta.env.DEV
? localStorage
: {
length: ls.storage.length,
clear: ls.clear,
setItem(key, value) {
ls.set(key, value);
},
getItem(key) {
return ls.get(key);
},
key(index) {
const keys = ls.getAllKeys();
return keys[index] ?? null;
},
removeItem(key) {
ls.remove(key);
},
},
}),
disablePKCE,
});

1
apps/vben5/packages/@abp/account/src/utils/index.ts

@ -0,0 +1 @@
export * from './auth';
Loading…
Cancel
Save