Skip to content

Commit 2e3f6d0

Browse files
author
hubert
committed
feat: add token type in local mode
1 parent ec8ff53 commit 2e3f6d0

File tree

20 files changed

+206
-142
lines changed

20 files changed

+206
-142
lines changed
Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
import { storage } from '@/store/utils';
22

3-
const TOKEN_KEY = 'token';
3+
const ACCESS_TOKEN_KEY = 'access-token',
4+
TOKEY_TYPE_KEY = 'token-type';
45

56
export function getToken() {
6-
return storage.get(TOKEN_KEY);
7+
return {
8+
accessToken: storage.get(ACCESS_TOKEN_KEY),
9+
tokenType: storage.get(TOKEY_TYPE_KEY),
10+
};
711
}
812

9-
export function setToken(token: string) {
10-
return storage.set(TOKEN_KEY, token);
13+
export function setToken(token: string, type = 'Baerer') {
14+
storage.set(ACCESS_TOKEN_KEY, token);
15+
storage.set(TOKEY_TYPE_KEY, type);
1116
}
1217

1318
export function removeToken() {
14-
return storage.remove(TOKEN_KEY);
19+
storage.remove(ACCESS_TOKEN_KEY);
20+
storage.remove(TOKEY_TYPE_KEY);
1521
}

clients/vue-web/src/auth/local/index.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import { i18n } from '@/i18n';
55
import { UserManager, type IUser, type ISigninArgs, type ISignoutArgs } from '../user-manager';
66
import { getToken, setToken, removeToken } from './helper';
77

8+
export interface UserManagerOptions {
9+
filterProtocolClaims?: boolean | string[];
10+
}
11+
812
/**
913
* Protocol claims that could be removed by default from profile.
1014
* Derived from the following sets of claims:
@@ -38,14 +42,23 @@ class Timer {
3842
class User implements IUser {
3943
payload: JwtPayload;
4044

41-
constructor(private readonly token: string, private readonly options: { filterProtocolClaims?: boolean | string[] }) {
45+
constructor(
46+
private readonly token: string,
47+
private readonly options: UserManagerOptions & {
48+
tokenType?: string;
49+
},
50+
) {
4251
this.payload = jwtDecode(token);
4352
}
4453

4554
get access_token() {
4655
return this.token;
4756
}
4857

58+
get token_type() {
59+
return this.options.tokenType ?? 'Bearer';
60+
}
61+
4962
get profile() {
5063
const result = { ...this.payload } as IUser['profile'];
5164

@@ -85,14 +98,15 @@ class User implements IUser {
8598
}
8699

87100
export class LocalUserManagerCreator extends UserManager {
88-
constructor(private readonly options: { filterProtocolClaims?: boolean | string[] } = {}) {
101+
constructor(private readonly options: UserManagerOptions = {}) {
89102
super();
90103
}
91104

92105
getUser(): Promise<IUser | null> {
93-
const token = getToken();
94-
if (token) {
95-
return Promise.resolve(new User(token, this.options));
106+
const { accessToken, tokenType } = getToken();
107+
if (accessToken) {
108+
const user = new User(accessToken, { tokenType, ...this.options });
109+
return Promise.resolve(user);
96110
}
97111
return Promise.resolve(null);
98112
}

clients/vue-web/src/auth/user-manager.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export interface IUser {
22
access_token: string;
3+
token_type: string;
34
/** The claims represented by a combination of the id_token and the user info endpoint */
45
get profile(): {
56
sub: string;

clients/vue-web/src/fetch/graphql/basic.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,18 @@ export const basicLink = split(
5454
const instance = Authoriztion.getInstance(),
5555
authType = instance.type,
5656
userManager = instance.userManager,
57-
token = await userManager
57+
authorization = await userManager
5858
.getUser()
59-
.then((user) => user?.access_token)
59+
.then((user) => {
60+
if (!user || user.expired) return '';
61+
return [user.token_type, user.access_token].filter(Boolean).join(' ');
62+
})
6063
.catch(() => '');
6164
const headers = {
6265
apikey: `pomelo-${authType}`,
6366
};
6467

65-
token && (headers['Authorization'] = `Bearer ${token}`);
68+
authorization && (headers['Authorization'] = authorization);
6669
i18n.locale && (headers['x-custom-locale'] = i18n.locale);
6770

6871
return headers;

clients/vue-web/src/fetch/graphql/identity.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,18 @@ export const identityLink = from([
2828
const instance = Authoriztion.getInstance(),
2929
authType = instance.type,
3030
userManager = instance.userManager,
31-
token = await userManager
31+
authorization = await userManager
3232
.getUser()
33-
.then((user) => user?.access_token)
33+
.then((user) => {
34+
if (!user || user.expired) return '';
35+
return [user.token_type, user.access_token].filter(Boolean).join(' ');
36+
})
3437
.catch(() => '');
3538
const headers = {
3639
apikey: `pomelo-${authType}`,
3740
};
3841

39-
token && (headers['Authorization'] = `Bearer ${token}`);
42+
authorization && (headers['Authorization'] = authorization);
4043
i18n.locale && (headers['x-custom-locale'] = i18n.locale);
4144

4245
return headers;

clients/vue-web/src/login/fetch/index.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,25 @@ import { defineRegistGraphql, gql } from '@ace-fetch/graphql-vue';
33
// Types
44
import type { TypedMutationDocumentNode } from '@ace-fetch/graphql';
55

6-
export interface UserVerifyInput {
6+
export interface SignInVerifyInput {
77
// 用户名
88
username: string;
99
// 密码
1010
password: string;
1111
}
1212

13-
export interface UserVerifySuccessResult {
13+
export interface SignInVerifySuccessResult {
1414
// 是否登录成功
1515
success: true;
16-
token: string;
16+
// access token
17+
accessToken: string;
18+
// token type
19+
tokenType: string;
20+
// 过期时间
21+
expiresAt: number;
1722
}
1823

19-
export interface UserVerifyFaildResult {
24+
export interface SignInVerifyFaildResult {
2025
// 是否登录成功
2126
success: false;
2227
message: string;
@@ -34,16 +39,18 @@ export interface ModifyPasswordInput {
3439
export const useLoginApi = defineRegistGraphql('login', {
3540
definition: {
3641
signIn: gql`
37-
mutation signIn($model: VerifyUserInput!) {
42+
mutation signIn($model: SignInInput!) {
3843
result: signIn(model: $model) {
3944
success
40-
token
45+
accessToken
46+
tokenType
47+
expiresAt
4148
message
4249
}
4350
}
4451
` as TypedMutationDocumentNode<
45-
{ result: UserVerifySuccessResult | UserVerifyFaildResult },
46-
{ model: UserVerifyInput }
52+
{ result: SignInVerifySuccessResult | SignInVerifyFaildResult },
53+
{ model: SignInVerifyInput }
4754
>,
4855
modifyPassword: gql`
4956
mutation updateUserPassword($model: UpdateUserPasswordInput!) {

clients/vue-web/src/login/views/login/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export default Form.create({})(
6060
})
6161
.then(({ result }) => {
6262
if (result.success) {
63-
setToken(result.token);
63+
setToken(result.accessToken, result.tokenType);
6464
message.success({
6565
content: i18n.tv('page_login.form.submit_success', '登录成功!') as string,
6666
onClose: redirect,

clients/vue-web/src/views/post/desktop.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ import moment from 'moment';
22
import hljs from 'highlight.js/lib/core';
33
import Lazyload from 'lazyload';
44
import { defineComponent, computed, onMounted } from '@vue/composition-api';
5-
import { TemplatePageType } from '@ace-pomelo/shared/client';
65
import { useI18n } from '@/composables';
76
import { useLocationMixin } from '@/mixins';
8-
import { PostMetaPresetKeys } from '@/fetch/apis';
7+
import { PostMetaPresetKeys, TemplatePageType } from '@/fetch/apis';
98
import { safeJSONParse } from '@/utils';
109
import classes from './desktop.module.less';
1110

clients/vue-web/src/views/post/mobile.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ import moment from 'moment';
22
import hljs from 'highlight.js/lib/core';
33
import Lazyload from 'lazyload';
44
import { defineComponent, computed, onMounted } from '@vue/composition-api';
5-
import { TemplatePageType } from '@ace-pomelo/shared/client';
65
import { useI18n } from '@/composables';
76
import { useLocationMixin } from '@/mixins';
8-
import { PostMetaPresetKeys } from '@/fetch/apis';
7+
import { PostMetaPresetKeys, TemplatePageType } from '@/fetch/apis';
98
import { safeJSONParse } from '@/utils';
109
import classes from './mobile.module.less';
1110

servers/infrastructure-bff/src/app.module.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,10 @@ const logger = new Logger('AppModule', { timestamp: true });
161161
AuthorizationModule.forRootAsync({
162162
isGlobal: true,
163163
useFactory: async (config: ConfigService) => {
164-
const { keys } = await getJWKS([config.get('PRIVATE_KEY')].filter(Boolean) as string[]);
164+
const privateKey = config.get('PRIVATE_KEY');
165+
const { keys } = await getJWKS([privateKey].filter(Boolean) as string[]);
165166
return {
167+
signingKey: await getSigningKey(privateKey),
166168
verifyingKey: createLocalJWKSet({
167169
keys: keys.map((jwk) => ({
168170
kty: jwk.kty,
@@ -302,7 +304,6 @@ const logger = new Logger('AppModule', { timestamp: true });
302304
UserModule.forRootAsync({
303305
useFactory: async (config: ConfigService) => ({
304306
isGlobal: true,
305-
signingKey: await getSigningKey(config.get('PRIVATE_KEY')),
306307
tokenExpiresIn: config.get('JWT_EXPIRES_IN'),
307308
}),
308309
inject: [ConfigService],

0 commit comments

Comments
 (0)