@enfyra/sdk-nuxt 0.6.2 → 0.7.0

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.
Files changed (30) hide show
  1. package/dist/module.cjs +15 -0
  2. package/dist/module.d.ts.map +1 -1
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +15 -0
  5. package/dist/runtime/composables/useEnfyraAuth.d.ts.map +1 -1
  6. package/dist/runtime/composables/useEnfyraAuth.js +10 -1
  7. package/dist/runtime/server/api/all.d.ts.map +1 -1
  8. package/dist/runtime/server/api/all.js +11 -1
  9. package/dist/runtime/server/api/auth/[provider]/callback.get.d.ts +3 -0
  10. package/dist/runtime/server/api/auth/[provider]/callback.get.d.ts.map +1 -0
  11. package/dist/runtime/server/api/auth/[provider]/callback.get.js +16 -0
  12. package/dist/runtime/server/api/auth/[provider].get.d.ts +3 -0
  13. package/dist/runtime/server/api/auth/[provider].get.d.ts.map +1 -0
  14. package/dist/runtime/server/api/auth/[provider].get.js +31 -0
  15. package/dist/runtime/server/api/auth/callback.get.d.ts +3 -0
  16. package/dist/runtime/server/api/auth/callback.get.d.ts.map +1 -0
  17. package/dist/runtime/server/api/auth/callback.get.js +29 -0
  18. package/dist/runtime/server/middleware/auth.d.ts.map +1 -1
  19. package/dist/runtime/server/middleware/auth.js +2 -1
  20. package/dist/types/auth.d.ts +2 -0
  21. package/dist/types/auth.d.ts.map +1 -1
  22. package/package.json +1 -1
  23. package/src/module.ts +19 -0
  24. package/src/runtime/composables/useEnfyraAuth.ts +12 -1
  25. package/src/runtime/server/api/all.ts +14 -1
  26. package/src/runtime/server/api/auth/[provider]/callback.get.ts +21 -0
  27. package/src/runtime/server/api/auth/[provider].get.ts +38 -0
  28. package/src/runtime/server/api/auth/callback.get.ts +39 -0
  29. package/src/runtime/server/middleware/auth.ts +6 -2
  30. package/src/types/auth.ts +3 -0
package/dist/module.cjs CHANGED
@@ -98,6 +98,21 @@ declare module '#imports' {
98
98
  handler: resolve("./runtime/server/api/logout.post"),
99
99
  method: "post"
100
100
  });
101
+ kit.addServerHandler({
102
+ route: `${apiPrefix}/auth/:provider`,
103
+ handler: resolve("./runtime/server/api/auth/[provider].get"),
104
+ method: "get"
105
+ });
106
+ kit.addServerHandler({
107
+ route: `${apiPrefix}/auth/:provider/callback`,
108
+ handler: resolve("./runtime/server/api/auth/[provider]/callback.get"),
109
+ method: "get"
110
+ });
111
+ kit.addServerHandler({
112
+ route: `${apiPrefix}/auth/callback`,
113
+ handler: resolve("./runtime/server/api/auth/callback.get"),
114
+ method: "get"
115
+ });
101
116
  kit.addServerHandler({
102
117
  route: "/assets/**",
103
118
  handler: resolve("./runtime/server/api/all")
@@ -1 +1 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;;AAED,wBA6HG"}
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;;AAED,wBAgJG"}
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.0.0"
6
6
  },
7
- "version": "0.6.2",
7
+ "version": "0.7.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.4",
10
10
  "unbuild": "2.0.0"
package/dist/module.mjs CHANGED
@@ -95,6 +95,21 @@ declare module '#imports' {
95
95
  handler: resolve("./runtime/server/api/logout.post"),
96
96
  method: "post"
97
97
  });
98
+ addServerHandler({
99
+ route: `${apiPrefix}/auth/:provider`,
100
+ handler: resolve("./runtime/server/api/auth/[provider].get"),
101
+ method: "get"
102
+ });
103
+ addServerHandler({
104
+ route: `${apiPrefix}/auth/:provider/callback`,
105
+ handler: resolve("./runtime/server/api/auth/[provider]/callback.get"),
106
+ method: "get"
107
+ });
108
+ addServerHandler({
109
+ route: `${apiPrefix}/auth/callback`,
110
+ handler: resolve("./runtime/server/api/auth/callback.get"),
111
+ method: "get"
112
+ });
98
113
  addServerHandler({
99
114
  route: "/assets/**",
100
115
  handler: resolve("./runtime/server/api/all")
@@ -1 +1 @@
1
- {"version":3,"file":"useEnfyraAuth.d.ts","sourceRoot":"","sources":["../../../src/runtime/composables/useEnfyraAuth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAsB,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAOhF,wBAAgB,aAAa,IAAI,mBAAmB,CAiFnD"}
1
+ {"version":3,"file":"useEnfyraAuth.d.ts","sourceRoot":"","sources":["../../../src/runtime/composables/useEnfyraAuth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAsB,mBAAmB,EAAiB,MAAM,kBAAkB,CAAC;AAO/F,wBAAgB,aAAa,IAAI,mBAAmB,CA4FnD"}
@@ -64,11 +64,20 @@ export function useEnfyraAuth() {
64
64
  }
65
65
  };
66
66
  const isLoggedIn = computed(() => !!me.value);
67
+ const oauthLogin = (provider) => {
68
+ if (typeof window === "undefined") {
69
+ console.error("[Enfyra Auth] oauthLogin can only be called on the client side");
70
+ return;
71
+ }
72
+ const currentUrl = window.location.href;
73
+ window.location.href = `/api/auth/${provider}?redirect=${encodeURIComponent(currentUrl)}`;
74
+ };
67
75
  return {
68
76
  me,
69
77
  login,
70
78
  logout,
71
79
  fetchUser,
72
- isLoggedIn
80
+ isLoggedIn,
81
+ oauthLogin
73
82
  };
74
83
  }
@@ -1 +1 @@
1
- {"version":3,"file":"all.d.ts","sourceRoot":"","sources":["../../../../src/runtime/server/api/all.ts"],"names":[],"mappings":";AAGA,wBAEG"}
1
+ {"version":3,"file":"all.d.ts","sourceRoot":"","sources":["../../../../src/runtime/server/api/all.ts"],"names":[],"mappings":";AAUA,wBAQG"}
@@ -1,5 +1,15 @@
1
- import { defineEventHandler } from "h3";
1
+ import { defineEventHandler, setResponseHeaders } from "h3";
2
2
  import { proxyToAPI } from "../../utils/server/proxy.js";
3
+ const CORS_HEADERS = {
4
+ "Access-Control-Allow-Origin": "*",
5
+ "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
6
+ "Access-Control-Allow-Headers": "Content-Type, Authorization",
7
+ "Access-Control-Max-Age": "86400"
8
+ };
3
9
  export default defineEventHandler(async (event) => {
10
+ setResponseHeaders(event, CORS_HEADERS);
11
+ if (event.method === "OPTIONS") {
12
+ return "";
13
+ }
4
14
  return proxyToAPI(event);
5
15
  });
@@ -0,0 +1,3 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
2
+ export default _default;
3
+ //# sourceMappingURL=callback.get.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callback.get.d.ts","sourceRoot":"","sources":["../../../../../../src/runtime/server/api/auth/[provider]/callback.get.ts"],"names":[],"mappings":";AAQA,wBAYG"}
@@ -0,0 +1,16 @@
1
+ import {
2
+ defineEventHandler,
3
+ getQuery,
4
+ sendRedirect
5
+ } from "h3";
6
+ import { useRuntimeConfig } from "#imports";
7
+ import { normalizeUrl } from "../../../../utils/url.js";
8
+ export default defineEventHandler(async (event) => {
9
+ const config = useRuntimeConfig();
10
+ const apiUrl = config.public.enfyraSDK?.apiUrl;
11
+ const provider = event.context.params?.provider;
12
+ const query = getQuery(event);
13
+ const queryString = new URLSearchParams(query).toString();
14
+ const backendUrl = normalizeUrl(apiUrl, `/auth/${provider}/callback?${queryString}`);
15
+ return sendRedirect(event, backendUrl, 302);
16
+ });
@@ -0,0 +1,3 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
2
+ export default _default;
3
+ //# sourceMappingURL=%5Bprovider%5D.get.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"[provider].get.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/server/api/auth/[provider].get.ts"],"names":[],"mappings":";AAYA,wBAyBG"}
@@ -0,0 +1,31 @@
1
+ import {
2
+ defineEventHandler,
3
+ getQuery,
4
+ createError,
5
+ sendError,
6
+ sendRedirect
7
+ } from "h3";
8
+ import { useRuntimeConfig } from "#imports";
9
+ import { normalizeUrl } from "../../../utils/url.js";
10
+ const VALID_PROVIDERS = ["google", "facebook", "github"];
11
+ export default defineEventHandler(async (event) => {
12
+ const config = useRuntimeConfig();
13
+ const apiUrl = config.public.enfyraSDK?.apiUrl;
14
+ const provider = event.context.params?.provider;
15
+ if (!provider || !VALID_PROVIDERS.includes(provider)) {
16
+ return sendError(
17
+ event,
18
+ createError({
19
+ statusCode: 400,
20
+ statusMessage: `Invalid OAuth provider: ${provider}`
21
+ })
22
+ );
23
+ }
24
+ const query = getQuery(event);
25
+ const redirectUrl = query.redirect;
26
+ let oauthUrl = normalizeUrl(apiUrl, `/auth/${provider}`);
27
+ if (redirectUrl) {
28
+ oauthUrl += `?redirect=${encodeURIComponent(redirectUrl)}`;
29
+ }
30
+ return sendRedirect(event, oauthUrl, 302);
31
+ });
@@ -0,0 +1,3 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
2
+ export default _default;
3
+ //# sourceMappingURL=callback.get.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callback.get.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/server/api/auth/callback.get.ts"],"names":[],"mappings":";AAaA,wBAyBG"}
@@ -0,0 +1,29 @@
1
+ import {
2
+ defineEventHandler,
3
+ getQuery,
4
+ setCookie,
5
+ sendRedirect
6
+ } from "h3";
7
+ import {
8
+ ACCESS_TOKEN_KEY,
9
+ REFRESH_TOKEN_KEY,
10
+ EXP_TIME_KEY
11
+ } from "../../../constants/auth.js";
12
+ export default defineEventHandler(async (event) => {
13
+ const query = getQuery(event);
14
+ const { accessToken, refreshToken, expTime, redirect } = query;
15
+ if (!accessToken || !refreshToken || !expTime) {
16
+ return sendRedirect(event, "/login?error=oauth_callback_failed");
17
+ }
18
+ const cookieOptions = {
19
+ httpOnly: true,
20
+ secure: true,
21
+ sameSite: "lax",
22
+ path: "/"
23
+ };
24
+ setCookie(event, ACCESS_TOKEN_KEY, accessToken, cookieOptions);
25
+ setCookie(event, REFRESH_TOKEN_KEY, refreshToken, cookieOptions);
26
+ setCookie(event, EXP_TIME_KEY, expTime, cookieOptions);
27
+ const redirectUrl = redirect || "/";
28
+ return sendRedirect(event, redirectUrl);
29
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../../src/runtime/server/middleware/auth.ts"],"names":[],"mappings":";AAQA,wBAmCG"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../../src/runtime/server/middleware/auth.ts"],"names":[],"mappings":";AAQA,wBAuCG"}
@@ -6,7 +6,8 @@ import {
6
6
  } from "../../utils/server/refreshToken.js";
7
7
  import { REFRESH_TOKEN_KEY } from "../../constants/auth.js";
8
8
  export default defineEventHandler(async (event) => {
9
- if (event.node.req.url === "/api/login" || event.node.req.url === "/api/logout") {
9
+ const url = event.node.req.url || "";
10
+ if (url === "/api/login" || url === "/api/logout" || url.startsWith("/api/auth/")) {
10
11
  return;
11
12
  }
12
13
  const { accessToken, needsRefresh } = validateTokens(event);
@@ -1,4 +1,5 @@
1
1
  import type { Ref } from 'vue';
2
+ export type OAuthProvider = 'google' | 'facebook' | 'github';
2
3
  export interface User {
3
4
  id: string;
4
5
  email: string;
@@ -39,5 +40,6 @@ export interface UseEnfyraAuthReturn {
39
40
  fields?: string[];
40
41
  }) => Promise<void>;
41
42
  isLoggedIn: Ref<boolean>;
43
+ oauthLogin: (provider: OAuthProvider) => void;
42
44
  }
43
45
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/types/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAE9B,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE;QACL,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,MAAM,CAAA;QACZ,gBAAgB,EAAE,eAAe,EAAE,CAAA;KACpC,CAAA;IACD,uBAAuB,CAAC,EAAE,eAAe,EAAE,CAAA;CAC5C;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC/B,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAA;IACpB,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IAC9C,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7D,UAAU,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;CACzB"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/types/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAE9B,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAA;AAE5D,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE;QACL,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,MAAM,CAAA;QACZ,gBAAgB,EAAE,eAAe,EAAE,CAAA;KACpC,CAAA;IACD,uBAAuB,CAAC,EAAE,eAAe,EAAE,CAAA;CAC5C;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC/B,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAA;IACpB,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IAC9C,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7D,UAAU,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACxB,UAAU,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAA;CAC9C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enfyra/sdk-nuxt",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
4
4
  "type": "module",
5
5
  "description": "Nuxt SDK for Enfyra CMS",
6
6
  "repository": {
package/src/module.ts CHANGED
@@ -130,6 +130,25 @@ declare module '#imports' {
130
130
  method: "post",
131
131
  });
132
132
 
133
+ // OAuth routes
134
+ addServerHandler({
135
+ route: `${apiPrefix}/auth/:provider`,
136
+ handler: resolve("./runtime/server/api/auth/[provider].get"),
137
+ method: "get",
138
+ });
139
+
140
+ addServerHandler({
141
+ route: `${apiPrefix}/auth/:provider/callback`,
142
+ handler: resolve("./runtime/server/api/auth/[provider]/callback.get"),
143
+ method: "get",
144
+ });
145
+
146
+ addServerHandler({
147
+ route: `${apiPrefix}/auth/callback`,
148
+ handler: resolve("./runtime/server/api/auth/callback.get"),
149
+ method: "get",
150
+ });
151
+
133
152
  addServerHandler({
134
153
  route: "/assets/**",
135
154
  handler: resolve("./runtime/server/api/all"),
@@ -1,5 +1,5 @@
1
1
  import { ref, computed } from "vue";
2
- import type { LoginPayload, User, UseEnfyraAuthReturn } from "../../types/auth";
2
+ import type { LoginPayload, User, UseEnfyraAuthReturn, OAuthProvider } from "../../types/auth";
3
3
  import { $fetch } from "ofetch";
4
4
  import { useEnfyra } from "./useEnfyra";
5
5
 
@@ -80,11 +80,22 @@ export function useEnfyraAuth(): UseEnfyraAuthReturn {
80
80
 
81
81
  const isLoggedIn = computed(() => !!me.value);
82
82
 
83
+ const oauthLogin = (provider: OAuthProvider) => {
84
+ if (typeof window === "undefined") {
85
+ console.error("[Enfyra Auth] oauthLogin can only be called on the client side");
86
+ return;
87
+ }
88
+
89
+ const currentUrl = window.location.href;
90
+ window.location.href = `/api/auth/${provider}?redirect=${encodeURIComponent(currentUrl)}`;
91
+ };
92
+
83
93
  return {
84
94
  me,
85
95
  login,
86
96
  logout,
87
97
  fetchUser,
88
98
  isLoggedIn,
99
+ oauthLogin,
89
100
  } as const;
90
101
  }
@@ -1,6 +1,19 @@
1
- import { defineEventHandler } from "h3";
1
+ import { defineEventHandler, setResponseHeaders } from "h3";
2
2
  import { proxyToAPI } from "../../utils/server/proxy";
3
3
 
4
+ const CORS_HEADERS = {
5
+ 'Access-Control-Allow-Origin': '*',
6
+ 'Access-Control-Allow-Methods': 'GET, POST, PUT, PATCH, DELETE, OPTIONS',
7
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization',
8
+ 'Access-Control-Max-Age': '86400',
9
+ };
10
+
4
11
  export default defineEventHandler(async (event) => {
12
+ setResponseHeaders(event, CORS_HEADERS);
13
+
14
+ if (event.method === 'OPTIONS') {
15
+ return '';
16
+ }
17
+
5
18
  return proxyToAPI(event);
6
19
  });
@@ -0,0 +1,21 @@
1
+ import {
2
+ defineEventHandler,
3
+ getQuery,
4
+ sendRedirect,
5
+ } from "h3";
6
+ import { useRuntimeConfig } from "#imports";
7
+ import { normalizeUrl } from "../../../../utils/url";
8
+
9
+ export default defineEventHandler(async (event) => {
10
+ const config = useRuntimeConfig();
11
+ const apiUrl = config.public.enfyraSDK?.apiUrl;
12
+ const provider = event.context.params?.provider;
13
+
14
+ const query = getQuery(event);
15
+ const queryString = new URLSearchParams(query as Record<string, string>).toString();
16
+
17
+ // Redirect to backend OAuth callback
18
+ const backendUrl = normalizeUrl(apiUrl, `/auth/${provider}/callback?${queryString}`);
19
+
20
+ return sendRedirect(event, backendUrl, 302);
21
+ });
@@ -0,0 +1,38 @@
1
+ import {
2
+ defineEventHandler,
3
+ getQuery,
4
+ createError,
5
+ sendError,
6
+ sendRedirect,
7
+ } from "h3";
8
+ import { useRuntimeConfig } from "#imports";
9
+ import { normalizeUrl } from "../../../utils/url";
10
+
11
+ const VALID_PROVIDERS = ["google", "facebook", "github"];
12
+
13
+ export default defineEventHandler(async (event) => {
14
+ const config = useRuntimeConfig();
15
+ const apiUrl = config.public.enfyraSDK?.apiUrl;
16
+ const provider = event.context.params?.provider;
17
+
18
+ if (!provider || !VALID_PROVIDERS.includes(provider)) {
19
+ return sendError(
20
+ event,
21
+ createError({
22
+ statusCode: 400,
23
+ statusMessage: `Invalid OAuth provider: ${provider}`,
24
+ })
25
+ );
26
+ }
27
+
28
+ const query = getQuery(event);
29
+ const redirectUrl = query.redirect as string | undefined;
30
+
31
+ // Build backend OAuth URL
32
+ let oauthUrl = normalizeUrl(apiUrl, `/auth/${provider}`);
33
+ if (redirectUrl) {
34
+ oauthUrl += `?redirect=${encodeURIComponent(redirectUrl)}`;
35
+ }
36
+
37
+ return sendRedirect(event, oauthUrl, 302);
38
+ });
@@ -0,0 +1,39 @@
1
+ import {
2
+ defineEventHandler,
3
+ getQuery,
4
+ setCookie,
5
+ sendRedirect,
6
+ } from "h3";
7
+ import { useRuntimeConfig } from "#imports";
8
+ import {
9
+ ACCESS_TOKEN_KEY,
10
+ REFRESH_TOKEN_KEY,
11
+ EXP_TIME_KEY,
12
+ } from "../../../constants/auth";
13
+
14
+ export default defineEventHandler(async (event) => {
15
+ const query = getQuery(event);
16
+
17
+ const { accessToken, refreshToken, expTime, redirect } = query;
18
+
19
+ // Validate required tokens
20
+ if (!accessToken || !refreshToken || !expTime) {
21
+ return sendRedirect(event, "/login?error=oauth_callback_failed");
22
+ }
23
+
24
+ // Set cookies (same as login.post.ts)
25
+ const cookieOptions = {
26
+ httpOnly: true,
27
+ secure: true,
28
+ sameSite: "lax" as const,
29
+ path: "/",
30
+ };
31
+
32
+ setCookie(event, ACCESS_TOKEN_KEY, accessToken as string, cookieOptions);
33
+ setCookie(event, REFRESH_TOKEN_KEY, refreshToken as string, cookieOptions);
34
+ setCookie(event, EXP_TIME_KEY, expTime as string, cookieOptions);
35
+
36
+ // Redirect to original page or home
37
+ const redirectUrl = (redirect as string) || "/";
38
+ return sendRedirect(event, redirectUrl);
39
+ });
@@ -7,9 +7,13 @@ import {
7
7
  import { REFRESH_TOKEN_KEY } from "../../constants/auth";
8
8
 
9
9
  export default defineEventHandler(async (event) => {
10
+ const url = event.node.req.url || "";
11
+
12
+ // Skip token validation for auth endpoints
10
13
  if (
11
- event.node.req.url === "/api/login" ||
12
- event.node.req.url === "/api/logout"
14
+ url === "/api/login" ||
15
+ url === "/api/logout" ||
16
+ url.startsWith("/api/auth/")
13
17
  ) {
14
18
  return;
15
19
  }
package/src/types/auth.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import type { Ref } from 'vue'
2
2
 
3
+ export type OAuthProvider = 'google' | 'facebook' | 'github'
4
+
3
5
  export interface User {
4
6
  id: string
5
7
  email: string
@@ -33,4 +35,5 @@ export interface UseEnfyraAuthReturn {
33
35
  logout: () => Promise<void>
34
36
  fetchUser: (options?: { fields?: string[] }) => Promise<void>
35
37
  isLoggedIn: Ref<boolean>
38
+ oauthLogin: (provider: OAuthProvider) => void
36
39
  }