@liedsonc/core-auth-kit 0.1.0 → 0.2.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 +802 -759
- package/auth-ui/bin/init.js +126 -0
- package/auth-ui/components/auth-card.tsx +49 -49
- package/auth-ui/components/auth-form.tsx +53 -53
- package/auth-ui/components/error-message.tsx +24 -24
- package/auth-ui/components/form-field.tsx +39 -39
- package/auth-ui/components/loading-spinner.tsx +19 -19
- package/auth-ui/components/oauth-buttons.tsx +49 -49
- package/auth-ui/components/password-input.tsx +93 -93
- package/auth-ui/components/success-message.tsx +24 -24
- package/auth-ui/package.json +59 -55
- package/auth-ui/pages/forgot-password/index.tsx +83 -83
- package/auth-ui/pages/login/index.tsx +119 -119
- package/auth-ui/pages/register/index.tsx +149 -149
- package/auth-ui/pages/reset-password/index.tsx +133 -133
- package/auth-ui/pages/verify-email/index.tsx +143 -143
- package/auth-ui/templates/app/(auth)/forgot-password/page.tsx +5 -0
- package/auth-ui/templates/app/(auth)/layout.tsx +12 -0
- package/auth-ui/templates/app/(auth)/login/page.tsx +5 -0
- package/auth-ui/templates/app/(auth)/register/page.tsx +5 -0
- package/auth-ui/templates/app/(auth)/reset-password/page.tsx +5 -0
- package/auth-ui/templates/app/(auth)/verify-email/page.tsx +5 -0
- package/auth-ui/templates/app/api/auth/forgot-password/route.ts +16 -0
- package/auth-ui/templates/app/api/auth/login/route.ts +16 -0
- package/auth-ui/templates/app/api/auth/logout/route.ts +8 -0
- package/auth-ui/templates/app/api/auth/register/route.ts +16 -0
- package/auth-ui/templates/app/api/auth/reset-password/route.ts +16 -0
- package/auth-ui/templates/app/api/auth/session/route.ts +8 -0
- package/auth-ui/templates/app/api/auth/verify-email/route.ts +16 -0
- package/auth-ui/templates/env.example +25 -0
- package/auth-ui/templates/lib/auth-client.ts +20 -0
- package/auth-ui/templates/lib/auth-config.ts +43 -0
- package/auth-ui/tsconfig.json +4 -15
- package/package.json +17 -6
- package/tailwind.config.ts +41 -41
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
|
|
3
|
+
export async function POST(request: Request) {
|
|
4
|
+
const body = await request.json().catch(() => ({}));
|
|
5
|
+
const { token, newPassword } = body as { token?: string; newPassword?: string };
|
|
6
|
+
if (!token || !newPassword) {
|
|
7
|
+
return NextResponse.json(
|
|
8
|
+
{ error: "Missing token or newPassword" },
|
|
9
|
+
{ status: 400 }
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
return NextResponse.json(
|
|
13
|
+
{ error: "Implement this route: validate token and update password in your backend." },
|
|
14
|
+
{ status: 501 }
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
|
|
3
|
+
export async function POST(request: Request) {
|
|
4
|
+
const body = await request.json().catch(() => ({}));
|
|
5
|
+
const { token } = body as { token?: string };
|
|
6
|
+
if (!token) {
|
|
7
|
+
return NextResponse.json(
|
|
8
|
+
{ error: "Missing token" },
|
|
9
|
+
{ status: 400 }
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
return NextResponse.json(
|
|
13
|
+
{ error: "Implement this route: validate verification token and mark email verified in your backend." },
|
|
14
|
+
{ status: 501 }
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# App URL (used for redirects and OAuth)
|
|
2
|
+
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
|
3
|
+
|
|
4
|
+
# Redirects after auth actions
|
|
5
|
+
NEXT_PUBLIC_AUTH_REDIRECT_AFTER_LOGIN=/
|
|
6
|
+
NEXT_PUBLIC_AUTH_REDIRECT_AFTER_REGISTER=/login
|
|
7
|
+
NEXT_PUBLIC_AUTH_REDIRECT_AFTER_RESET=/login
|
|
8
|
+
|
|
9
|
+
# Google OAuth
|
|
10
|
+
NEXT_PUBLIC_OAUTH_GOOGLE_ENABLED=false
|
|
11
|
+
NEXT_PUBLIC_OAUTH_GOOGLE_CLIENT_ID=your_google_client_id
|
|
12
|
+
NEXT_PUBLIC_OAUTH_GOOGLE_REDIRECT_URI=http://localhost:3000/api/auth/google
|
|
13
|
+
OAUTH_GOOGLE_CLIENT_SECRET=your_google_client_secret
|
|
14
|
+
|
|
15
|
+
# Apple OAuth
|
|
16
|
+
NEXT_PUBLIC_OAUTH_APPLE_ENABLED=false
|
|
17
|
+
NEXT_PUBLIC_OAUTH_APPLE_CLIENT_ID=your_apple_client_id
|
|
18
|
+
NEXT_PUBLIC_OAUTH_APPLE_REDIRECT_URI=http://localhost:3000/api/auth/apple
|
|
19
|
+
OAUTH_APPLE_CLIENT_SECRET=your_apple_client_secret
|
|
20
|
+
|
|
21
|
+
# Resend (optional, for verification and password reset emails)
|
|
22
|
+
RESEND_API_KEY=re_your_resend_api_key
|
|
23
|
+
RESEND_FROM_EMAIL=noreply@yourdomain.com
|
|
24
|
+
RESEND_FROM_NAME=Your App Name
|
|
25
|
+
NEXT_PUBLIC_APP_NAME=Your App Name
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AuthClient } from "@liedsonc/core-auth-kit";
|
|
2
|
+
|
|
3
|
+
const notImplemented = () =>
|
|
4
|
+
Promise.resolve({
|
|
5
|
+
success: false as const,
|
|
6
|
+
error: {
|
|
7
|
+
code: "NOT_IMPLEMENTED",
|
|
8
|
+
message: "Implement auth-client.ts with your backend (e.g. Supabase, custom API).",
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const authClient: AuthClient = {
|
|
13
|
+
login: notImplemented,
|
|
14
|
+
register: notImplemented,
|
|
15
|
+
logout: () => Promise.resolve(),
|
|
16
|
+
forgotPassword: notImplemented,
|
|
17
|
+
resetPassword: notImplemented,
|
|
18
|
+
verifyEmail: notImplemented,
|
|
19
|
+
getSession: () => Promise.resolve(null),
|
|
20
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { AuthUIConfig, OAuthProvider } from "@liedsonc/core-auth-kit";
|
|
2
|
+
import { authClient } from "@/lib/auth-client";
|
|
3
|
+
|
|
4
|
+
export interface OAuthProviderConfig {
|
|
5
|
+
provider: OAuthProvider;
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
clientId?: string;
|
|
8
|
+
redirectUri?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function getOAuthProvidersFromEnv(): OAuthProviderConfig[] {
|
|
12
|
+
const providers: OAuthProviderConfig[] = [];
|
|
13
|
+
|
|
14
|
+
if (process.env.NEXT_PUBLIC_OAUTH_GOOGLE_ENABLED === "true") {
|
|
15
|
+
providers.push({
|
|
16
|
+
provider: "google",
|
|
17
|
+
enabled: true,
|
|
18
|
+
clientId: process.env.NEXT_PUBLIC_OAUTH_GOOGLE_CLIENT_ID,
|
|
19
|
+
redirectUri: process.env.NEXT_PUBLIC_OAUTH_GOOGLE_REDIRECT_URI,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (process.env.NEXT_PUBLIC_OAUTH_APPLE_ENABLED === "true") {
|
|
24
|
+
providers.push({
|
|
25
|
+
provider: "apple",
|
|
26
|
+
enabled: true,
|
|
27
|
+
clientId: process.env.NEXT_PUBLIC_OAUTH_APPLE_CLIENT_ID,
|
|
28
|
+
redirectUri: process.env.NEXT_PUBLIC_OAUTH_APPLE_REDIRECT_URI,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return providers;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function getAuthUIConfig(): AuthUIConfig {
|
|
36
|
+
return {
|
|
37
|
+
authClient,
|
|
38
|
+
oauthProviders: getOAuthProvidersFromEnv(),
|
|
39
|
+
redirectAfterLogin: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_LOGIN || "/",
|
|
40
|
+
redirectAfterRegister: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_REGISTER || "/login",
|
|
41
|
+
redirectAfterReset: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_RESET || "/login",
|
|
42
|
+
};
|
|
43
|
+
}
|
package/auth-ui/tsconfig.json
CHANGED
|
@@ -14,20 +14,9 @@
|
|
|
14
14
|
"forceConsistentCasingInFileNames": true,
|
|
15
15
|
"isolatedModules": true,
|
|
16
16
|
"incremental": true,
|
|
17
|
-
"plugins": [
|
|
18
|
-
|
|
19
|
-
"name": "next"
|
|
20
|
-
}
|
|
21
|
-
],
|
|
22
|
-
"paths": {
|
|
23
|
-
"@/*": ["./*"]
|
|
24
|
-
}
|
|
17
|
+
"plugins": [{ "name": "next" }],
|
|
18
|
+
"paths": { "@/*": ["./*"] }
|
|
25
19
|
},
|
|
26
|
-
"include": [
|
|
27
|
-
|
|
28
|
-
"**/*.tsx"
|
|
29
|
-
],
|
|
30
|
-
"exclude": [
|
|
31
|
-
"node_modules"
|
|
32
|
-
]
|
|
20
|
+
"include": ["**/*.ts", "**/*.tsx"],
|
|
21
|
+
"exclude": ["node_modules", "templates", "bin"]
|
|
33
22
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liedsonc/core-auth-kit",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Production-ready authentication UI package for Next.js App Router",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"
|
|
7
|
-
"
|
|
6
|
+
"dev": "next dev",
|
|
7
|
+
"build": "npm run build --prefix auth-ui",
|
|
8
|
+
"start": "next start",
|
|
9
|
+
"lint": "next lint"
|
|
8
10
|
},
|
|
9
11
|
"keywords": [
|
|
10
12
|
"nextjs",
|
|
@@ -17,9 +19,18 @@
|
|
|
17
19
|
],
|
|
18
20
|
"author": "",
|
|
19
21
|
"license": "MIT",
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@radix-ui/react-label": "^2.1.0",
|
|
24
|
+
"@radix-ui/react-slot": "^1.1.0",
|
|
25
|
+
"class-variance-authority": "^0.7.0",
|
|
26
|
+
"clsx": "^2.1.1",
|
|
27
|
+
"next": "^15.0.0",
|
|
28
|
+
"react": "^19.0.0",
|
|
29
|
+
"react-dom": "^19.0.0",
|
|
30
|
+
"resend": "^4.0.0",
|
|
31
|
+
"tailwind-merge": "^2.5.0",
|
|
32
|
+
"zod": "^3.23.0"
|
|
33
|
+
},
|
|
23
34
|
"devDependencies": {
|
|
24
35
|
"@types/node": "^22.0.0",
|
|
25
36
|
"@types/react": "^19.0.0",
|
package/tailwind.config.ts
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
import type { Config } from "tailwindcss";
|
|
2
|
-
|
|
3
|
-
const config: Config = {
|
|
4
|
-
darkMode: "class",
|
|
5
|
-
content: [
|
|
6
|
-
"./auth-ui/**/*.{js,ts,jsx,tsx,mdx}",
|
|
7
|
-
],
|
|
8
|
-
theme: {
|
|
9
|
-
extend: {
|
|
10
|
-
colors: {
|
|
11
|
-
background: "hsl(var(--background))",
|
|
12
|
-
foreground: "hsl(var(--foreground))",
|
|
13
|
-
card: "hsl(var(--card))",
|
|
14
|
-
"card-foreground": "hsl(var(--card-foreground))",
|
|
15
|
-
popover: "hsl(var(--popover))",
|
|
16
|
-
"popover-foreground": "hsl(var(--popover-foreground))",
|
|
17
|
-
primary: "hsl(var(--primary))",
|
|
18
|
-
"primary-foreground": "hsl(var(--primary-foreground))",
|
|
19
|
-
secondary: "hsl(var(--secondary))",
|
|
20
|
-
"secondary-foreground": "hsl(var(--secondary-foreground))",
|
|
21
|
-
muted: "hsl(var(--muted))",
|
|
22
|
-
"muted-foreground": "hsl(var(--muted-foreground))",
|
|
23
|
-
accent: "hsl(var(--accent))",
|
|
24
|
-
"accent-foreground": "hsl(var(--accent-foreground))",
|
|
25
|
-
destructive: "hsl(var(--destructive))",
|
|
26
|
-
"destructive-foreground": "hsl(var(--destructive-foreground))",
|
|
27
|
-
border: "hsl(var(--border))",
|
|
28
|
-
input: "hsl(var(--input))",
|
|
29
|
-
ring: "hsl(var(--ring))",
|
|
30
|
-
},
|
|
31
|
-
borderRadius: {
|
|
32
|
-
lg: "var(--radius)",
|
|
33
|
-
md: "calc(var(--radius) - 2px)",
|
|
34
|
-
sm: "calc(var(--radius) - 4px)",
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
plugins: [],
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export default config;
|
|
1
|
+
import type { Config } from "tailwindcss";
|
|
2
|
+
|
|
3
|
+
const config: Config = {
|
|
4
|
+
darkMode: "class",
|
|
5
|
+
content: [
|
|
6
|
+
"./auth-ui/**/*.{js,ts,jsx,tsx,mdx}",
|
|
7
|
+
],
|
|
8
|
+
theme: {
|
|
9
|
+
extend: {
|
|
10
|
+
colors: {
|
|
11
|
+
background: "hsl(var(--background))",
|
|
12
|
+
foreground: "hsl(var(--foreground))",
|
|
13
|
+
card: "hsl(var(--card))",
|
|
14
|
+
"card-foreground": "hsl(var(--card-foreground))",
|
|
15
|
+
popover: "hsl(var(--popover))",
|
|
16
|
+
"popover-foreground": "hsl(var(--popover-foreground))",
|
|
17
|
+
primary: "hsl(var(--primary))",
|
|
18
|
+
"primary-foreground": "hsl(var(--primary-foreground))",
|
|
19
|
+
secondary: "hsl(var(--secondary))",
|
|
20
|
+
"secondary-foreground": "hsl(var(--secondary-foreground))",
|
|
21
|
+
muted: "hsl(var(--muted))",
|
|
22
|
+
"muted-foreground": "hsl(var(--muted-foreground))",
|
|
23
|
+
accent: "hsl(var(--accent))",
|
|
24
|
+
"accent-foreground": "hsl(var(--accent-foreground))",
|
|
25
|
+
destructive: "hsl(var(--destructive))",
|
|
26
|
+
"destructive-foreground": "hsl(var(--destructive-foreground))",
|
|
27
|
+
border: "hsl(var(--border))",
|
|
28
|
+
input: "hsl(var(--input))",
|
|
29
|
+
ring: "hsl(var(--ring))",
|
|
30
|
+
},
|
|
31
|
+
borderRadius: {
|
|
32
|
+
lg: "var(--radius)",
|
|
33
|
+
md: "calc(var(--radius) - 2px)",
|
|
34
|
+
sm: "calc(var(--radius) - 4px)",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
plugins: [],
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default config;
|