nuxt-auth-utils 0.0.13 → 0.0.15

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 CHANGED
@@ -150,10 +150,12 @@ It can also be set using environment variables:
150
150
  #### Supported OAuth Providers
151
151
 
152
152
  - Auth0
153
+ - AWS Cognito
153
154
  - Battle.net
154
155
  - Discord
155
156
  - GitHub
156
157
  - Google
158
+ - Keycloak
157
159
  - LinkedIn
158
160
  - Microsoft
159
161
  - Spotify
package/dist/module.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "auth-utils",
3
3
  "configKey": "auth",
4
- "version": "0.0.13"
4
+ "version": "0.0.15"
5
5
  }
package/dist/module.mjs CHANGED
@@ -98,10 +98,22 @@ const module = defineNuxtModule({
98
98
  clientId: "",
99
99
  clientSecret: ""
100
100
  });
101
+ runtimeConfig.oauth.keycloak = defu(runtimeConfig.oauth.keycloak, {
102
+ clientId: "",
103
+ clientSecret: "",
104
+ serverUrl: "",
105
+ realm: ""
106
+ });
101
107
  runtimeConfig.oauth.linkedin = defu(runtimeConfig.oauth.linkedin, {
102
108
  clientId: "",
103
109
  clientSecret: ""
104
110
  });
111
+ runtimeConfig.oauth.cognito = defu(runtimeConfig.oauth.cognito, {
112
+ clientId: "",
113
+ clientSecret: "",
114
+ region: "",
115
+ userPoolId: ""
116
+ });
105
117
  }
106
118
  });
107
119
 
@@ -38,5 +38,12 @@ export interface OAuthAuth0Config {
38
38
  * @see https://auth0.com/docs/authenticate/login/max-age-reauthentication
39
39
  */
40
40
  maxAge?: number;
41
+ /**
42
+ * Login connection. If no connection is specified, it will redirect to the standard Auth0 login page and show the Login Widget.
43
+ * @default ''
44
+ * @see https://auth0.com/docs/api/authentication#social
45
+ * @example 'github'
46
+ */
47
+ connection?: string;
41
48
  }
42
49
  export declare function auth0EventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthAuth0Config>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
@@ -32,7 +32,8 @@ export function auth0EventHandler({ config, onSuccess, onError }) {
32
32
  redirect_uri: redirectUrl,
33
33
  scope: config.scope.join(" "),
34
34
  audience: config.audience || "",
35
- max_age: config.maxAge || 0
35
+ max_age: config.maxAge || 0,
36
+ connection: config.connection || ""
36
37
  })
37
38
  );
38
39
  }
@@ -0,0 +1,29 @@
1
+ import type { OAuthConfig } from '#auth-utils';
2
+ export interface OAuthCognitoConfig {
3
+ /**
4
+ * AWS Cognito App Client ID
5
+ * @default process.env.NUXT_OAUTH_COGNITO_CLIENT_ID
6
+ */
7
+ clientId?: string;
8
+ /**
9
+ * AWS Cognito App Client Secret
10
+ * @default process.env.NUXT_OAUTH_COGNITO_CLIENT_SECRET
11
+ */
12
+ clientSecret?: string;
13
+ /**
14
+ * AWS Cognito User Pool ID
15
+ * @default process.env.NUXT_OAUTH_COGNITO_USER_POOL_ID
16
+ */
17
+ userPoolId?: string;
18
+ /**
19
+ * AWS Cognito Region
20
+ * @default process.env.NUXT_OAUTH_COGNITO_REGION
21
+ */
22
+ region?: string;
23
+ /**
24
+ * AWS Cognito Scope
25
+ * @default []
26
+ */
27
+ scope?: string[];
28
+ }
29
+ export declare function cognitoEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthCognitoConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
@@ -0,0 +1,68 @@
1
+ import { eventHandler, createError, getQuery, getRequestURL, sendRedirect } from "h3";
2
+ import { withQuery, parsePath } from "ufo";
3
+ import { ofetch } from "ofetch";
4
+ import { defu } from "defu";
5
+ import { useRuntimeConfig } from "#imports";
6
+ export function cognitoEventHandler({ config, onSuccess, onError }) {
7
+ return eventHandler(async (event) => {
8
+ config = defu(config, useRuntimeConfig(event).oauth?.cognito);
9
+ const { code } = getQuery(event);
10
+ if (!config.clientId || !config.clientSecret || !config.userPoolId || !config.region) {
11
+ const error = createError({
12
+ statusCode: 500,
13
+ message: "Missing NUXT_OAUTH_COGNITO_CLIENT_ID, NUXT_OAUTH_COGNITO_CLIENT_SECRET, NUXT_OAUTH_COGNITO_USER_POOL_ID, or NUXT_OAUTH_COGNITO_REGION env variables."
14
+ });
15
+ if (!onError)
16
+ throw error;
17
+ return onError(event, error);
18
+ }
19
+ const authorizationURL = `https://${config.userPoolId}.auth.${config.region}.amazoncognito.com/oauth2/authorize`;
20
+ const tokenURL = `https://${config.userPoolId}.auth.${config.region}.amazoncognito.com/oauth2/token`;
21
+ const redirectUrl = getRequestURL(event).href;
22
+ if (!code) {
23
+ config.scope = config.scope || ["openid", "profile"];
24
+ return sendRedirect(
25
+ event,
26
+ withQuery(authorizationURL, {
27
+ client_id: config.clientId,
28
+ redirect_uri: redirectUrl,
29
+ response_type: "code",
30
+ scope: config.scope.join(" ")
31
+ })
32
+ );
33
+ }
34
+ const tokens = await ofetch(
35
+ tokenURL,
36
+ {
37
+ method: "POST",
38
+ headers: {
39
+ "Content-Type": "application/x-www-form-urlencoded"
40
+ },
41
+ body: `grant_type=authorization_code&client_id=${config.clientId}&client_secret=${config.clientSecret}&redirect_uri=${parsePath(redirectUrl).pathname}&code=${code}`
42
+ }
43
+ ).catch((error) => {
44
+ return { error };
45
+ });
46
+ if (tokens.error) {
47
+ const error = createError({
48
+ statusCode: 401,
49
+ message: `Cognito login failed: ${tokens.error_description || "Unknown error"}`,
50
+ data: tokens
51
+ });
52
+ if (!onError)
53
+ throw error;
54
+ return onError(event, error);
55
+ }
56
+ const tokenType = tokens.token_type;
57
+ const accessToken = tokens.access_token;
58
+ const user = await ofetch(`https://${config.userPoolId}.auth.${config.region}.amazoncognito.com/oauth2/userInfo`, {
59
+ headers: {
60
+ Authorization: `${tokenType} ${accessToken}`
61
+ }
62
+ });
63
+ return onSuccess(event, {
64
+ tokens,
65
+ user
66
+ });
67
+ });
68
+ }
@@ -30,7 +30,7 @@ export function githubEventHandler({ config, onSuccess, onError }) {
30
30
  withQuery(config.authorizationURL, {
31
31
  client_id: config.clientId,
32
32
  redirect_uri: redirectUrl,
33
- scope: config.scope.join("%20")
33
+ scope: config.scope.join(" ")
34
34
  })
35
35
  );
36
36
  }
@@ -0,0 +1,32 @@
1
+ import type { OAuthConfig } from '#auth-utils';
2
+ export interface OAuthKeycloakConfig {
3
+ /**
4
+ * Keycloak OAuth Client ID
5
+ * @default process.env.NUXT_OAUTH_KEYCLOAK_CLIENT_ID
6
+ */
7
+ clientId?: string;
8
+ /**
9
+ * Keycloak OAuth Client Secret
10
+ * @default process.env.NUXT_OAUTH_KEYCLOAK_CLIENT_SECRET
11
+ */
12
+ clientSecret?: string;
13
+ /**
14
+ * Keycloak OAuth Server URL
15
+ * @example http://192.168.1.10:8080/auth
16
+ * @default process.env.NUXT_OAUTH_KEYCLOAK_SERVER_URL
17
+ */
18
+ serverUrl?: string;
19
+ /**
20
+ * Keycloak OAuth Realm
21
+ * @default process.env.NUXT_OAUTH_KEYCLOAK_REALM
22
+ */
23
+ realm?: string;
24
+ /**
25
+ * Keycloak OAuth Scope
26
+ * @default []
27
+ * @see https://www.keycloak.org/docs/latest/authorization_services/
28
+ * @example ['openid']
29
+ */
30
+ scope?: string[];
31
+ }
32
+ export declare function keycloakEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthKeycloakConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
@@ -0,0 +1,114 @@
1
+ import {
2
+ eventHandler,
3
+ createError,
4
+ getQuery,
5
+ getRequestURL,
6
+ sendRedirect
7
+ } from "h3";
8
+ import { ofetch } from "ofetch";
9
+ import { withQuery, parsePath } from "ufo";
10
+ import { defu } from "defu";
11
+ import { useRuntimeConfig } from "#imports";
12
+ export function keycloakEventHandler({
13
+ config,
14
+ onSuccess,
15
+ onError
16
+ }) {
17
+ return eventHandler(async (event) => {
18
+ config = defu(
19
+ config,
20
+ // @ts-ignore
21
+ useRuntimeConfig(event).oauth?.keycloak
22
+ );
23
+ const query = getQuery(event);
24
+ const { code } = query;
25
+ if (query.error) {
26
+ const error = createError({
27
+ statusCode: 401,
28
+ message: `Keycloak login failed: ${query.error || "Unknown error"}`,
29
+ data: query
30
+ });
31
+ if (!onError)
32
+ throw error;
33
+ return onError(event, error);
34
+ }
35
+ if (!config.clientId || !config.clientSecret || !config.serverUrl || !config.realm) {
36
+ const error = createError({
37
+ statusCode: 500,
38
+ message: "Missing NUXT_OAUTH_KEYCLOAK_CLIENT_ID or NUXT_OAUTH_KEYCLOAK_CLIENT_SECRET or NUXT_OAUTH_KEYCLOAK_SERVER_URL or NUXT_OAUTH_KEYCLOAK_REALM env variables."
39
+ });
40
+ if (!onError)
41
+ throw error;
42
+ return onError(event, error);
43
+ }
44
+ const realmURL = `${config.serverUrl}/realms/${config.realm}`;
45
+ const authorizationURL = `${realmURL}/protocol/openid-connect/auth`;
46
+ const tokenURL = `${realmURL}/protocol/openid-connect/token`;
47
+ const redirectUrl = getRequestURL(event).href;
48
+ if (!code) {
49
+ config.scope = config.scope || ["openid"];
50
+ return sendRedirect(
51
+ event,
52
+ withQuery(authorizationURL, {
53
+ client_id: config.clientId,
54
+ redirect_uri: redirectUrl,
55
+ scope: config.scope.join(" "),
56
+ response_type: "code"
57
+ })
58
+ );
59
+ }
60
+ config.scope = config.scope || [];
61
+ if (!config.scope.includes("openid")) {
62
+ config.scope.push("openid");
63
+ }
64
+ const tokens = await ofetch(tokenURL, {
65
+ method: "POST",
66
+ headers: {
67
+ "Content-Type": "application/x-www-form-urlencoded"
68
+ },
69
+ body: new URLSearchParams({
70
+ client_id: config.clientId,
71
+ client_secret: config.clientSecret,
72
+ grant_type: "authorization_code",
73
+ redirect_uri: parsePath(redirectUrl).pathname,
74
+ code
75
+ }).toString()
76
+ }).catch((error) => {
77
+ return { error };
78
+ });
79
+ if (tokens.error) {
80
+ const error = createError({
81
+ statusCode: 401,
82
+ message: `Keycloak login failed: ${tokens.error?.data?.error_description || "Unknown error"}`,
83
+ data: tokens
84
+ });
85
+ if (!onError)
86
+ throw error;
87
+ return onError(event, error);
88
+ }
89
+ const accessToken = tokens.access_token;
90
+ const user = await ofetch(
91
+ `${realmURL}/protocol/openid-connect/userinfo`,
92
+ {
93
+ headers: {
94
+ Authorization: `Bearer ${accessToken}`,
95
+ Accept: "application/json"
96
+ }
97
+ }
98
+ );
99
+ if (!user) {
100
+ const error = createError({
101
+ statusCode: 500,
102
+ message: "Could not get Keycloak user",
103
+ data: tokens
104
+ });
105
+ if (!onError)
106
+ throw error;
107
+ return onError(event, error);
108
+ }
109
+ return onSuccess(event, {
110
+ user,
111
+ tokens
112
+ });
113
+ });
114
+ }
@@ -27,7 +27,7 @@ export function microsoftEventHandler({ config, onSuccess, onError }) {
27
27
  client_id: config.clientId,
28
28
  response_type: "code",
29
29
  redirect_uri: redirectUrl,
30
- scope: scope.join("%20")
30
+ scope: scope.join(" ")
31
31
  })
32
32
  );
33
33
  }
@@ -31,7 +31,7 @@ export function spotifyEventHandler({ config, onSuccess, onError }) {
31
31
  response_type: "code",
32
32
  client_id: config.clientId,
33
33
  redirect_uri: redirectUrl,
34
- scope: config.scope.join("%20")
34
+ scope: config.scope.join(" ")
35
35
  })
36
36
  );
37
37
  }
@@ -31,7 +31,7 @@ export function twitchEventHandler({ config, onSuccess, onError }) {
31
31
  response_type: "code",
32
32
  client_id: config.clientId,
33
33
  redirect_uri: redirectUrl,
34
- scope: config.scope.join("%20")
34
+ scope: config.scope.join(" ")
35
35
  })
36
36
  );
37
37
  }
@@ -6,7 +6,9 @@ import { auth0EventHandler } from '../lib/oauth/auth0';
6
6
  import { microsoftEventHandler } from '../lib/oauth/microsoft';
7
7
  import { discordEventHandler } from '../lib/oauth/discord';
8
8
  import { battledotnetEventHandler } from '../lib/oauth/battledotnet';
9
+ import { keycloakEventHandler } from '../lib/oauth/keycloak';
9
10
  import { linkedinEventHandler } from '../lib/oauth/linkedin';
11
+ import { cognitoEventHandler } from '../lib/oauth/cognito';
10
12
  export declare const oauth: {
11
13
  githubEventHandler: typeof githubEventHandler;
12
14
  spotifyEventHandler: typeof spotifyEventHandler;
@@ -16,5 +18,7 @@ export declare const oauth: {
16
18
  microsoftEventHandler: typeof microsoftEventHandler;
17
19
  discordEventHandler: typeof discordEventHandler;
18
20
  battledotnetEventHandler: typeof battledotnetEventHandler;
21
+ keycloakEventHandler: typeof keycloakEventHandler;
19
22
  linkedinEventHandler: typeof linkedinEventHandler;
23
+ cognitoEventHandler: typeof cognitoEventHandler;
20
24
  };
@@ -6,7 +6,9 @@ import { auth0EventHandler } from "../lib/oauth/auth0.mjs";
6
6
  import { microsoftEventHandler } from "../lib/oauth/microsoft.mjs";
7
7
  import { discordEventHandler } from "../lib/oauth/discord.mjs";
8
8
  import { battledotnetEventHandler } from "../lib/oauth/battledotnet.mjs";
9
+ import { keycloakEventHandler } from "../lib/oauth/keycloak.mjs";
9
10
  import { linkedinEventHandler } from "../lib/oauth/linkedin.mjs";
11
+ import { cognitoEventHandler } from "../lib/oauth/cognito.mjs";
10
12
  export const oauth = {
11
13
  githubEventHandler,
12
14
  spotifyEventHandler,
@@ -16,5 +18,7 @@ export const oauth = {
16
18
  microsoftEventHandler,
17
19
  discordEventHandler,
18
20
  battledotnetEventHandler,
19
- linkedinEventHandler
21
+ keycloakEventHandler,
22
+ linkedinEventHandler,
23
+ cognitoEventHandler
20
24
  };
package/dist/types.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- import type { ModuleOptions } from './module'
2
+ import type { ModuleOptions } from './module.js'
3
3
 
4
4
 
5
5
  declare module '@nuxt/schema' {
@@ -13,4 +13,4 @@ declare module 'nuxt/schema' {
13
13
  }
14
14
 
15
15
 
16
- export type { ModuleOptions, default } from './module'
16
+ export type { ModuleOptions, default } from './module.js'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-auth-utils",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "description": "Minimalist Auth module for Nuxt with SSR",
5
5
  "repository": "Atinux/nuxt-auth-utils",
6
6
  "license": "MIT",
@@ -30,27 +30,27 @@
30
30
  "test:watch": "vitest watch"
31
31
  },
32
32
  "dependencies": {
33
- "@nuxt/kit": "^3.8.2",
34
- "defu": "^6.1.3",
33
+ "@nuxt/kit": "^3.9.3",
34
+ "defu": "^6.1.4",
35
35
  "hookable": "^5.5.3",
36
36
  "ofetch": "^1.3.3",
37
37
  "ohash": "^1.1.3"
38
38
  },
39
39
  "devDependencies": {
40
- "@iconify-json/simple-icons": "^1.1.82",
40
+ "@iconify-json/simple-icons": "^1.1.90",
41
41
  "@nuxt/devtools": "latest",
42
42
  "@nuxt/eslint-config": "^0.2.0",
43
- "@nuxt/module-builder": "^0.5.4",
44
- "@nuxt/schema": "^3.8.2",
45
- "@nuxt/test-utils": "^3.8.1",
46
- "@nuxt/ui": "^2.11.0",
47
- "@nuxt/ui-pro": "^0.5.0",
48
- "@types/node": "^20.10.4",
43
+ "@nuxt/module-builder": "^0.5.5",
44
+ "@nuxt/schema": "^3.9.3",
45
+ "@nuxt/test-utils": "^3.11.0",
46
+ "@nuxt/ui": "^2.12.3",
47
+ "@nuxt/ui-pro": "^0.7.3",
48
+ "@types/node": "^20.11.10",
49
49
  "changelogen": "^0.5.5",
50
- "eslint": "^8.55.0",
51
- "nuxt": "^3.8.2",
50
+ "eslint": "^8.56.0",
51
+ "nuxt": "^3.9.3",
52
52
  "typescript": "^5.3.3",
53
- "vitest": "^1.0.2",
54
- "vue-tsc": "^1.8.25"
53
+ "vitest": "^1.2.2",
54
+ "vue-tsc": "^1.8.27"
55
55
  }
56
56
  }