@meistrari/auth-nuxt 0.1.0 → 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +272 -124
- package/dist/core.d.mts +1 -0
- package/dist/core.mjs +1 -0
- package/dist/module.d.mts +1 -3
- package/dist/module.json +3 -3
- package/dist/module.mjs +20 -26
- package/dist/runtime/composables/api-key.d.ts +13 -0
- package/dist/runtime/composables/api-key.js +29 -0
- package/dist/runtime/composables/organization.d.ts +28 -0
- package/dist/runtime/composables/organization.js +164 -0
- package/dist/runtime/composables/session.d.ts +18 -0
- package/dist/runtime/composables/session.js +88 -0
- package/dist/runtime/composables/state.d.ts +22 -0
- package/dist/runtime/composables/state.js +17 -0
- package/dist/runtime/plugin.d.ts +1 -14
- package/dist/runtime/plugin.js +69 -84
- package/dist/runtime/server/middleware/auth.js +11 -16
- package/dist/runtime/server/tsconfig.json +4 -1
- package/dist/runtime/server/types/h3.d.ts +5 -5
- package/dist/runtime/shared.d.ts +1 -0
- package/dist/runtime/shared.js +19 -0
- package/package.json +51 -48
- package/dist/runtime/composable.d.ts +0 -5
- package/dist/runtime/composable.js +0 -29
- package/dist/runtime/server/api/sign-out.d.ts +0 -2
- package/dist/runtime/server/api/sign-out.js +0 -16
- package/dist/runtime/server/middleware/set-cookies.d.ts +0 -2
- package/dist/runtime/server/middleware/set-cookies.js +0 -42
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { CreateTeamPayload, InviteUserToOrganizationOptions, ListMembersOptions, RemoveUserFromOrganizationOptions, UpdateMemberRoleOptions, UpdateOrganizationPayload, UpdateTeamPayload } from '@meistrari/auth-core';
|
|
2
|
+
/**
|
|
3
|
+
* Composable for managing organizations and their members, invitations, and teams.
|
|
4
|
+
*
|
|
5
|
+
* @returns An object containing organization management functions and the active organization and member states.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useTelaOrganization(): {
|
|
8
|
+
activeOrganization: import("vue").Ref<any, any>;
|
|
9
|
+
activeMember: import("vue").Ref<any, any>;
|
|
10
|
+
getActiveOrganization: () => Promise<any>;
|
|
11
|
+
listOrganizations: () => Promise<any>;
|
|
12
|
+
setActiveOrganization: (id: string) => Promise<void>;
|
|
13
|
+
updateOrganization: (payload: UpdateOrganizationPayload) => Promise<any>;
|
|
14
|
+
listMembers: (options?: ListMembersOptions) => Promise<any>;
|
|
15
|
+
getActiveMember: () => Promise<any>;
|
|
16
|
+
inviteUserToOrganization: (options: InviteUserToOrganizationOptions) => Promise<any>;
|
|
17
|
+
acceptInvitation: (id: string) => Promise<void>;
|
|
18
|
+
cancelInvitation: (id: string) => Promise<void>;
|
|
19
|
+
removeUserFromOrganization: (options: RemoveUserFromOrganizationOptions) => Promise<void>;
|
|
20
|
+
updateMemberRole: (options: UpdateMemberRoleOptions) => Promise<void>;
|
|
21
|
+
createTeam: (payload: CreateTeamPayload) => Promise<any>;
|
|
22
|
+
updateTeam: (id: string, payload: UpdateTeamPayload) => Promise<any>;
|
|
23
|
+
deleteTeam: (id: string) => Promise<void>;
|
|
24
|
+
listTeams: () => Promise<any>;
|
|
25
|
+
listTeamMembers: (id: string) => Promise<any>;
|
|
26
|
+
addTeamMember: (teamId: string, userId: string) => Promise<any>;
|
|
27
|
+
removeTeamMember: (teamId: string, userId: string) => Promise<void>;
|
|
28
|
+
};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { useCookie, useRuntimeConfig } from "#app";
|
|
2
|
+
import { createNuxtAuthClient } from "../shared.js";
|
|
3
|
+
import { useOrganizationState, useSessionState } from "./state.js";
|
|
4
|
+
export function useTelaOrganization() {
|
|
5
|
+
const { activeOrganization, activeMember } = useOrganizationState();
|
|
6
|
+
const { session } = useSessionState();
|
|
7
|
+
const { jwtCookieName, apiUrl } = useRuntimeConfig().public.telaAuth;
|
|
8
|
+
const tokenCookie = useCookie(jwtCookieName);
|
|
9
|
+
const authClient = createNuxtAuthClient(apiUrl, () => tokenCookie.value ?? null);
|
|
10
|
+
async function getActiveOrganization() {
|
|
11
|
+
if (!session.value?.activeOrganizationId) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const organization = await authClient.organization.getOrganization(
|
|
15
|
+
session.value?.activeOrganizationId,
|
|
16
|
+
{
|
|
17
|
+
includeMembers: true,
|
|
18
|
+
includeInvitations: true,
|
|
19
|
+
includeTeams: true
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
activeOrganization.value = organization;
|
|
23
|
+
return organization;
|
|
24
|
+
}
|
|
25
|
+
async function listOrganizations() {
|
|
26
|
+
return authClient.organization.listOrganizations();
|
|
27
|
+
}
|
|
28
|
+
async function setActiveOrganization(id) {
|
|
29
|
+
await authClient.organization.setActiveOrganization(id);
|
|
30
|
+
const organization = await authClient.organization.getOrganization(id, {
|
|
31
|
+
includeMembers: true,
|
|
32
|
+
includeInvitations: true,
|
|
33
|
+
includeTeams: true
|
|
34
|
+
});
|
|
35
|
+
activeOrganization.value = organization;
|
|
36
|
+
}
|
|
37
|
+
async function updateOrganization(payload) {
|
|
38
|
+
if (!activeOrganization.value) {
|
|
39
|
+
throw new Error("No active organization found");
|
|
40
|
+
}
|
|
41
|
+
const organization = await authClient.organization.updateOrganization(payload);
|
|
42
|
+
activeOrganization.value = { ...activeOrganization.value, ...organization };
|
|
43
|
+
return organization;
|
|
44
|
+
}
|
|
45
|
+
async function listMembers(options) {
|
|
46
|
+
return authClient.organization.listMembers(options);
|
|
47
|
+
}
|
|
48
|
+
async function getActiveMember() {
|
|
49
|
+
const member = await authClient.organization.getActiveMember();
|
|
50
|
+
activeMember.value = member;
|
|
51
|
+
return member;
|
|
52
|
+
}
|
|
53
|
+
async function inviteUserToOrganization(options) {
|
|
54
|
+
const invitation = await authClient.organization.inviteUserToOrganization(options);
|
|
55
|
+
if (activeOrganization.value) {
|
|
56
|
+
activeOrganization.value = {
|
|
57
|
+
...activeOrganization.value,
|
|
58
|
+
invitations: [...activeOrganization.value?.invitations ?? [], invitation]
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return invitation;
|
|
62
|
+
}
|
|
63
|
+
async function acceptInvitation(id) {
|
|
64
|
+
await authClient.organization.acceptInvitation(id);
|
|
65
|
+
const members = await authClient.organization.listMembers();
|
|
66
|
+
if (activeOrganization.value) {
|
|
67
|
+
activeOrganization.value = {
|
|
68
|
+
...activeOrganization.value,
|
|
69
|
+
members
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function cancelInvitation(id) {
|
|
74
|
+
await authClient.organization.cancelInvitation(id);
|
|
75
|
+
if (activeOrganization.value) {
|
|
76
|
+
activeOrganization.value = {
|
|
77
|
+
...activeOrganization.value,
|
|
78
|
+
invitations: activeOrganization.value?.invitations?.filter((invitation) => invitation.id !== id) ?? []
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function removeUserFromOrganization(options) {
|
|
83
|
+
await authClient.organization.removeUserFromOrganization(options);
|
|
84
|
+
if (activeOrganization.value) {
|
|
85
|
+
activeOrganization.value = {
|
|
86
|
+
...activeOrganization.value,
|
|
87
|
+
members: activeOrganization.value?.members?.filter((member) => member.id !== options.memberId) ?? []
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async function updateMemberRole(options) {
|
|
92
|
+
await authClient.organization.updateMemberRole(options);
|
|
93
|
+
const members = await authClient.organization.listMembers();
|
|
94
|
+
if (activeOrganization.value) {
|
|
95
|
+
activeOrganization.value = {
|
|
96
|
+
...activeOrganization.value,
|
|
97
|
+
members
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async function createTeam(payload) {
|
|
102
|
+
const team = await authClient.organization.createTeam(payload);
|
|
103
|
+
if (activeOrganization.value) {
|
|
104
|
+
activeOrganization.value = {
|
|
105
|
+
...activeOrganization.value,
|
|
106
|
+
teams: [...activeOrganization.value?.teams ?? [], team]
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return team;
|
|
110
|
+
}
|
|
111
|
+
async function updateTeam(id, payload) {
|
|
112
|
+
const updatedTeam = await authClient.organization.updateTeam(id, payload);
|
|
113
|
+
if (activeOrganization.value) {
|
|
114
|
+
activeOrganization.value = {
|
|
115
|
+
...activeOrganization.value,
|
|
116
|
+
teams: activeOrganization.value?.teams?.map((team) => team.id === id ? updatedTeam : team) ?? []
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return updatedTeam;
|
|
120
|
+
}
|
|
121
|
+
async function deleteTeam(id) {
|
|
122
|
+
await authClient.organization.deleteTeam(id);
|
|
123
|
+
if (activeOrganization.value) {
|
|
124
|
+
activeOrganization.value = {
|
|
125
|
+
...activeOrganization.value,
|
|
126
|
+
teams: activeOrganization.value?.teams?.filter((team) => team.id !== id) ?? []
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async function listTeams() {
|
|
131
|
+
return authClient.organization.listTeams();
|
|
132
|
+
}
|
|
133
|
+
async function listTeamMembers(id) {
|
|
134
|
+
return authClient.organization.listTeamMembers(id);
|
|
135
|
+
}
|
|
136
|
+
async function addTeamMember(teamId, userId) {
|
|
137
|
+
return authClient.organization.addTeamMember(teamId, userId);
|
|
138
|
+
}
|
|
139
|
+
async function removeTeamMember(teamId, userId) {
|
|
140
|
+
await authClient.organization.removeTeamMember(teamId, userId);
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
activeOrganization,
|
|
144
|
+
activeMember,
|
|
145
|
+
getActiveOrganization,
|
|
146
|
+
listOrganizations,
|
|
147
|
+
setActiveOrganization,
|
|
148
|
+
updateOrganization,
|
|
149
|
+
listMembers,
|
|
150
|
+
getActiveMember,
|
|
151
|
+
inviteUserToOrganization,
|
|
152
|
+
acceptInvitation,
|
|
153
|
+
cancelInvitation,
|
|
154
|
+
removeUserFromOrganization,
|
|
155
|
+
updateMemberRole,
|
|
156
|
+
createTeam,
|
|
157
|
+
updateTeam,
|
|
158
|
+
deleteTeam,
|
|
159
|
+
listTeams,
|
|
160
|
+
listTeamMembers,
|
|
161
|
+
addTeamMember,
|
|
162
|
+
removeTeamMember
|
|
163
|
+
};
|
|
164
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type SignInWithEmailAndPasswordOptions, type SignInWithSamlOptions, type SocialSignInOptions } from '@meistrari/auth-core';
|
|
2
|
+
/**
|
|
3
|
+
* Composable for managing user sessions and authentication.
|
|
4
|
+
*
|
|
5
|
+
* @returns An object containing session management functions and the user and session states.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useTelaSession(): {
|
|
8
|
+
user: import("vue").Ref<any, any>;
|
|
9
|
+
session: import("vue").Ref<any, any>;
|
|
10
|
+
getSession: () => Promise<any>;
|
|
11
|
+
getToken: () => Promise<any>;
|
|
12
|
+
signInWithEmailAndPassword: ({ email, password, callbackURL, errorCallbackURL, }: SignInWithEmailAndPasswordOptions) => Promise<void>;
|
|
13
|
+
signInWithSocialProvider: ({ provider, callbackURL, errorCallbackURL, }: SocialSignInOptions) => Promise<void>;
|
|
14
|
+
signInWithSaml: ({ email, callbackURL, errorCallbackURL, }: SignInWithSamlOptions) => Promise<void>;
|
|
15
|
+
signOut: (callback?: (() => void) | (() => Promise<void>)) => Promise<void>;
|
|
16
|
+
requestPasswordReset: (email: string, callbackURL: string) => Promise<void>;
|
|
17
|
+
resetPassword: (token: string, password: string) => Promise<void>;
|
|
18
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { useCookie, useRuntimeConfig } from "#app";
|
|
2
|
+
import { APIError } from "@meistrari/auth-core";
|
|
3
|
+
import { createNuxtAuthClient } from "../shared.js";
|
|
4
|
+
import { useSessionState, useOrganizationState } from "./state.js";
|
|
5
|
+
export function useTelaSession() {
|
|
6
|
+
const { user, session } = useSessionState();
|
|
7
|
+
const { jwtCookieName, apiUrl } = useRuntimeConfig().public.telaAuth;
|
|
8
|
+
const tokenCookie = useCookie(jwtCookieName);
|
|
9
|
+
const authClient = createNuxtAuthClient(apiUrl, () => tokenCookie.value ?? null);
|
|
10
|
+
async function getSession() {
|
|
11
|
+
return await authClient.session.getSession();
|
|
12
|
+
}
|
|
13
|
+
async function getToken() {
|
|
14
|
+
try {
|
|
15
|
+
const { token } = await authClient.session.getToken();
|
|
16
|
+
return token;
|
|
17
|
+
} catch (error) {
|
|
18
|
+
if (error instanceof APIError && error.status === 401) {
|
|
19
|
+
await signOut();
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function signInWithSocialProvider({
|
|
25
|
+
provider,
|
|
26
|
+
callbackURL,
|
|
27
|
+
errorCallbackURL
|
|
28
|
+
}) {
|
|
29
|
+
await authClient.session.signInWithSocialProvider({
|
|
30
|
+
provider,
|
|
31
|
+
callbackURL,
|
|
32
|
+
errorCallbackURL
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
async function signInWithSaml({
|
|
36
|
+
email,
|
|
37
|
+
callbackURL,
|
|
38
|
+
errorCallbackURL
|
|
39
|
+
}) {
|
|
40
|
+
await authClient.session.signInWithSaml({
|
|
41
|
+
email,
|
|
42
|
+
callbackURL,
|
|
43
|
+
errorCallbackURL
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
async function signInWithEmailAndPassword({
|
|
47
|
+
email,
|
|
48
|
+
password,
|
|
49
|
+
callbackURL,
|
|
50
|
+
errorCallbackURL
|
|
51
|
+
}) {
|
|
52
|
+
await authClient.session.signInWithEmailAndPassword({
|
|
53
|
+
email,
|
|
54
|
+
password,
|
|
55
|
+
callbackURL,
|
|
56
|
+
errorCallbackURL
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async function requestPasswordReset(email, callbackURL) {
|
|
60
|
+
await authClient.session.requestPasswordReset(email, callbackURL);
|
|
61
|
+
}
|
|
62
|
+
async function resetPassword(token, password) {
|
|
63
|
+
await authClient.session.resetPassword(token, password);
|
|
64
|
+
}
|
|
65
|
+
async function signOut(callback) {
|
|
66
|
+
const { activeOrganization, activeMember } = useOrganizationState();
|
|
67
|
+
await authClient.session.signOut(async () => {
|
|
68
|
+
tokenCookie.value = null;
|
|
69
|
+
user.value = null;
|
|
70
|
+
session.value = null;
|
|
71
|
+
activeOrganization.value = null;
|
|
72
|
+
activeMember.value = null;
|
|
73
|
+
await callback?.();
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
user,
|
|
78
|
+
session,
|
|
79
|
+
getSession,
|
|
80
|
+
getToken,
|
|
81
|
+
signInWithEmailAndPassword,
|
|
82
|
+
signInWithSocialProvider,
|
|
83
|
+
signInWithSaml,
|
|
84
|
+
signOut,
|
|
85
|
+
requestPasswordReset,
|
|
86
|
+
resetPassword
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { FullOrganization, Invitation, Member, Team } from '@meistrari/auth-core';
|
|
2
|
+
export type FullOrganizationWithRelations = FullOrganization & {
|
|
3
|
+
members: Member[];
|
|
4
|
+
invitations: Invitation[];
|
|
5
|
+
teams: Team[];
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Shared state for session management.
|
|
9
|
+
* This module provides access to session-related state without creating circular dependencies.
|
|
10
|
+
*/
|
|
11
|
+
export declare function useSessionState(): {
|
|
12
|
+
user: import("vue").Ref<any, any>;
|
|
13
|
+
session: import("vue").Ref<any, any>;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Shared state for organization management.
|
|
17
|
+
* This module provides access to organization-related state without creating circular dependencies.
|
|
18
|
+
*/
|
|
19
|
+
export declare function useOrganizationState(): {
|
|
20
|
+
activeOrganization: import("vue").Ref<any, any>;
|
|
21
|
+
activeMember: import("vue").Ref<any, any>;
|
|
22
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useState } from "#app";
|
|
2
|
+
export function useSessionState() {
|
|
3
|
+
const user = useState("user", () => null);
|
|
4
|
+
const session = useState("session", () => null);
|
|
5
|
+
return {
|
|
6
|
+
user,
|
|
7
|
+
session
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export function useOrganizationState() {
|
|
11
|
+
const activeOrganization = useState("activeOrganization", () => null);
|
|
12
|
+
const activeMember = useState("activeMember", () => null);
|
|
13
|
+
return {
|
|
14
|
+
activeOrganization,
|
|
15
|
+
activeMember
|
|
16
|
+
};
|
|
17
|
+
}
|
package/dist/runtime/plugin.d.ts
CHANGED
|
@@ -1,15 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
declare const _default: import("#app").Plugin<{
|
|
3
|
-
auth: {
|
|
4
|
-
client: ReturnType<typeof createAuthClient>;
|
|
5
|
-
getToken: () => Promise<string | null | undefined>;
|
|
6
|
-
refreshToken: () => Promise<string | null | undefined>;
|
|
7
|
-
};
|
|
8
|
-
}> & import("#app").ObjectPlugin<{
|
|
9
|
-
auth: {
|
|
10
|
-
client: ReturnType<typeof createAuthClient>;
|
|
11
|
-
getToken: () => Promise<string | null | undefined>;
|
|
12
|
-
refreshToken: () => Promise<string | null | undefined>;
|
|
13
|
-
};
|
|
14
|
-
}>;
|
|
1
|
+
declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
|
|
15
2
|
export default _default;
|
package/dist/runtime/plugin.js
CHANGED
|
@@ -1,105 +1,90 @@
|
|
|
1
|
-
import { defineNuxtPlugin, useCookie,
|
|
1
|
+
import { defineNuxtPlugin, useCookie, useRuntimeConfig, useRequestURL } from "#app";
|
|
2
2
|
import { watch } from "vue";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { useTelaSession } from "./composables/session.js";
|
|
4
|
+
import { createNuxtAuthClient } from "./shared.js";
|
|
5
|
+
import { useRoute, navigateTo } from "#imports";
|
|
5
6
|
export default defineNuxtPlugin({
|
|
6
|
-
name: "
|
|
7
|
-
|
|
7
|
+
name: "tela-auth",
|
|
8
|
+
enforce: "pre",
|
|
9
|
+
env: {
|
|
10
|
+
islands: false
|
|
11
|
+
},
|
|
8
12
|
async setup() {
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
fetchOptions: {
|
|
30
|
-
// on the client side we include credentials
|
|
31
|
-
credentials: "include",
|
|
32
|
-
// on the server side we forward the cookies
|
|
33
|
-
headers,
|
|
34
|
-
onSuccess: (ctx) => {
|
|
35
|
-
const jwt = ctx.response.headers.get("set-auth-jwt");
|
|
36
|
-
if (jwt) {
|
|
37
|
-
token.value = jwt;
|
|
38
|
-
}
|
|
13
|
+
const authConfig = useRuntimeConfig().public.telaAuth;
|
|
14
|
+
const { session, user, getToken } = useTelaSession();
|
|
15
|
+
const tokenCookie = useCookie(authConfig.jwtCookieName);
|
|
16
|
+
tokenCookie.value = null;
|
|
17
|
+
const authClient = createNuxtAuthClient(authConfig.apiUrl, () => tokenCookie.value ?? null);
|
|
18
|
+
const query = useRoute().query;
|
|
19
|
+
const nonce = query.nonce;
|
|
20
|
+
const origin = useRequestURL();
|
|
21
|
+
if (import.meta.server) {
|
|
22
|
+
if (nonce && typeof nonce === "string") {
|
|
23
|
+
if (nonce !== "null") {
|
|
24
|
+
try {
|
|
25
|
+
const payload = await authClient.session.getNoncePayload(nonce);
|
|
26
|
+
tokenCookie.value = payload.token;
|
|
27
|
+
} catch {
|
|
28
|
+
await navigateTo(`${authConfig.apiUrl}/api/auth/handshake?origin=${origin.toString()}`, {
|
|
29
|
+
external: true,
|
|
30
|
+
redirectCode: 302
|
|
31
|
+
});
|
|
32
|
+
return;
|
|
39
33
|
}
|
|
40
34
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
} else {
|
|
36
|
+
await navigateTo(`${authConfig.apiUrl}/api/auth/handshake?origin=${origin.toString()}`, {
|
|
37
|
+
external: true,
|
|
38
|
+
redirectCode: 302
|
|
39
|
+
});
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
} else if (import.meta.client && !session.value) {
|
|
43
|
+
const token = await getToken();
|
|
44
|
+
if (token) {
|
|
45
|
+
tokenCookie.value = token;
|
|
44
46
|
}
|
|
45
|
-
return token.value;
|
|
46
47
|
}
|
|
47
48
|
async function initializeSession() {
|
|
48
49
|
if (session.value && user.value)
|
|
49
50
|
return;
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
const { data: sessionData, error: sessionError } = await authClient.getSession(
|
|
53
|
-
{
|
|
54
|
-
fetchOptions: {
|
|
55
|
-
// on the client side we include credentials
|
|
56
|
-
credentials: "include",
|
|
57
|
-
// on the server side we forward the cookies
|
|
58
|
-
headers,
|
|
59
|
-
...config.useJwt && {
|
|
60
|
-
onSuccess: (context) => {
|
|
61
|
-
const jwt = context.response.headers.get("Set-Auth-Jwt");
|
|
62
|
-
if (jwt) {
|
|
63
|
-
token.value = jwt;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
);
|
|
70
|
-
if (sessionError || !sessionData) {
|
|
51
|
+
const sessionData = await authClient.session.getSession();
|
|
52
|
+
if (!sessionData) {
|
|
71
53
|
return;
|
|
72
54
|
}
|
|
73
55
|
user.value = sessionData.user;
|
|
74
56
|
session.value = sessionData.session;
|
|
75
57
|
}
|
|
76
|
-
|
|
58
|
+
if (tokenCookie.value) {
|
|
59
|
+
await initializeSession();
|
|
60
|
+
}
|
|
77
61
|
if (import.meta.client) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
62
|
+
let tokenRefreshInterval = null;
|
|
63
|
+
watch(session, async (newVal) => {
|
|
64
|
+
if (tokenRefreshInterval) {
|
|
65
|
+
clearTimeout(tokenRefreshInterval);
|
|
66
|
+
tokenRefreshInterval = null;
|
|
67
|
+
}
|
|
68
|
+
if (newVal) {
|
|
69
|
+
async function createTokenRefreshInterval() {
|
|
70
|
+
const token = await getToken();
|
|
71
|
+
if (token) {
|
|
72
|
+
tokenCookie.value = token;
|
|
89
73
|
}
|
|
90
|
-
createTokenRefreshInterval
|
|
74
|
+
tokenRefreshInterval = window.setTimeout(createTokenRefreshInterval, 6e4);
|
|
91
75
|
}
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return {
|
|
96
|
-
provide: {
|
|
97
|
-
auth: {
|
|
98
|
-
client: authClient,
|
|
99
|
-
getToken,
|
|
100
|
-
refreshToken
|
|
76
|
+
createTokenRefreshInterval();
|
|
101
77
|
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
78
|
+
}, { immediate: true });
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
hooks: {
|
|
82
|
+
"app:mounted": () => {
|
|
83
|
+
const url = new URL(window.location.href);
|
|
84
|
+
url.searchParams.delete("session");
|
|
85
|
+
url.searchParams.delete("session_data");
|
|
86
|
+
url.searchParams.delete("nonce");
|
|
87
|
+
window.history.replaceState({}, "", url.pathname + url.search + url.hash);
|
|
88
|
+
}
|
|
104
89
|
}
|
|
105
90
|
});
|
|
@@ -1,26 +1,21 @@
|
|
|
1
|
+
import { validateToken, extractTokenPayload } from "@meistrari/auth-core";
|
|
1
2
|
import { defineEventHandler, getCookie } from "h3";
|
|
2
3
|
import { useRuntimeConfig } from "nitropack/runtime/config";
|
|
3
|
-
import { createAuthClient } from "@meistrari/auth-core";
|
|
4
4
|
async function setAuthContext(event) {
|
|
5
5
|
event.context.auth = {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
user: null,
|
|
7
|
+
workspace: null
|
|
8
8
|
};
|
|
9
|
-
const
|
|
10
|
-
|
|
9
|
+
const authConfig = useRuntimeConfig(event).public.telaAuth;
|
|
10
|
+
const tokenCookie = getCookie(event, authConfig.jwtCookieName);
|
|
11
|
+
if (!tokenCookie)
|
|
11
12
|
return;
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const { data: sessionData, error: sessionError } = await authClient.getSession({
|
|
15
|
-
fetchOptions: {
|
|
16
|
-
headers: event.headers
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
if (sessionError || !sessionData) {
|
|
13
|
+
const isValid = await validateToken(tokenCookie, authConfig.apiUrl);
|
|
14
|
+
if (!isValid)
|
|
20
15
|
return;
|
|
21
|
-
|
|
22
|
-
event.context.auth.
|
|
23
|
-
event.context.auth.
|
|
16
|
+
const payload = extractTokenPayload(tokenCookie);
|
|
17
|
+
event.context.auth.user = { email: payload.email, ...payload.user };
|
|
18
|
+
event.context.auth.workspace = payload.workspace;
|
|
24
19
|
}
|
|
25
20
|
export function meistrariAuthMiddleware(callback) {
|
|
26
21
|
return defineEventHandler(async (event) => {
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { JWTTokenPayload } from '@meistrari/auth-core'
|
|
2
2
|
import type { H3Event, H3EventContext } from 'h3'
|
|
3
3
|
|
|
4
4
|
declare module 'h3' {
|
|
5
5
|
interface H3EventContext {
|
|
6
6
|
auth?: {
|
|
7
|
-
user:
|
|
8
|
-
|
|
7
|
+
user: { email: string } & JWTTokenPayload['user'] | null
|
|
8
|
+
workspace: JWTTokenPayload['workspace'] | null
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface AuthenticatedH3EventContext extends H3EventContext {
|
|
14
14
|
auth: {
|
|
15
|
-
user:
|
|
16
|
-
|
|
15
|
+
user: { email: string } & JWTTokenPayload['user'] | null
|
|
16
|
+
workspace: JWTTokenPayload['workspace'] | null
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createNuxtAuthClient(apiUrl: string, getAuthToken: () => string | null): any;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { AuthClient } from "@meistrari/auth-core";
|
|
2
|
+
import { version } from "../../package.json";
|
|
3
|
+
export function createNuxtAuthClient(apiUrl, getAuthToken) {
|
|
4
|
+
const serviceName = typeof process !== "undefined" ? process.env.SERVICE_NAME : "";
|
|
5
|
+
const userAgent = `auth-sdk:nuxt:${version}${serviceName ? `@${serviceName}` : ""}`;
|
|
6
|
+
return new AuthClient(apiUrl, {
|
|
7
|
+
headers: {
|
|
8
|
+
"X-User-Agent": userAgent
|
|
9
|
+
},
|
|
10
|
+
onRequest: (context) => {
|
|
11
|
+
const requestUrl = new URL(context.url);
|
|
12
|
+
const token = getAuthToken();
|
|
13
|
+
const isTokenRequest = requestUrl.pathname.endsWith("/api/auth/token");
|
|
14
|
+
if (token && !isTokenRequest) {
|
|
15
|
+
context.headers.set("Authorization", `Bearer ${token}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|