@artatol-acp/auth-nextjs 0.1.1 → 0.2.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.
package/README.md CHANGED
@@ -10,6 +10,19 @@ npm install @artatol-acp/auth-nextjs
10
10
  pnpm add @artatol-acp/auth-nextjs
11
11
  ```
12
12
 
13
+ ## Prerequisites
14
+
15
+ Before using this SDK, you need to obtain from the ACP AUTH service:
16
+
17
+ 1. **API Key** (required) - Contact your system administrator
18
+ 2. **Base URL** (required) - The auth service URL (e.g., `https://sso.artatol.net`)
19
+ 3. **JWT Public Key** (optional) - Only needed for local JWT verification with `getUser()`. Download it from:
20
+ ```bash
21
+ curl https://sso.artatol.net/public-key > public.pem
22
+ ```
23
+
24
+ **Note:** Without the public key, you can still use all auth operations (login, register, logout, 2FA, password reset, etc.), but you must use the `me()` function instead of `getUser()` for user verification, which makes an API call to the auth service.
25
+
13
26
  ## Setup
14
27
 
15
28
  ### 1. Initialize Server-side
@@ -24,6 +37,7 @@ const publicKey = readFileSync('./keys/public.pem', 'utf-8');
24
37
 
25
38
  export const auth = initACPAuth({
26
39
  baseUrl: process.env.ACP_AUTH_URL || 'https://sso.artatol.com',
40
+ apiKey: process.env.ACP_AUTH_API_KEY!,
27
41
  jwtPublicKey: publicKey,
28
42
  });
29
43
  ```
@@ -118,7 +132,8 @@ export async function registerAction(formData: FormData) {
118
132
  const password = formData.get('password') as string;
119
133
 
120
134
  await register(email, password);
121
- redirect('/login');
135
+ // User will receive verification email
136
+ redirect('/check-email');
122
137
  }
123
138
 
124
139
  export async function logoutAction() {
@@ -171,6 +186,7 @@ import { ACPAuthClient } from '@artatol-acp/auth-nextjs/server';
171
186
 
172
187
  const client = new ACPAuthClient({
173
188
  baseUrl: process.env.ACP_AUTH_URL!,
189
+ apiKey: process.env.ACP_AUTH_API_KEY!,
174
190
  });
175
191
 
176
192
  export async function POST(request: Request) {
@@ -182,10 +198,125 @@ export async function POST(request: Request) {
182
198
  }
183
199
  ```
184
200
 
201
+ ## Password Requirements
202
+
203
+ Passwords must meet the following requirements:
204
+ - Minimum 10 characters
205
+ - At least one lowercase letter (a-z)
206
+ - At least one uppercase letter (A-Z)
207
+ - At least one number (0-9)
208
+
209
+ ```typescript
210
+ // Example validation on the client side
211
+ function validatePassword(password: string): string[] {
212
+ const errors: string[] = [];
213
+
214
+ if (password.length < 10) {
215
+ errors.push('Password must be at least 10 characters');
216
+ }
217
+ if (!/[a-z]/.test(password)) {
218
+ errors.push('Password must contain at least one lowercase letter');
219
+ }
220
+ if (!/[A-Z]/.test(password)) {
221
+ errors.push('Password must contain at least one uppercase letter');
222
+ }
223
+ if (!/[0-9]/.test(password)) {
224
+ errors.push('Password must contain at least one number');
225
+ }
226
+
227
+ return errors;
228
+ }
229
+ ```
230
+
231
+ ## Email Verification
232
+
233
+ After registration, users must verify their email address before they can log in. The auth service automatically sends a verification email upon registration.
234
+
235
+ ### Verification Flow
236
+
237
+ 1. User registers → receives verification email
238
+ 2. User clicks link in email → email is verified
239
+ 3. User can now log in
240
+
241
+ ### Server Actions
242
+
243
+ ```typescript
244
+ 'use server';
245
+
246
+ import { verifyEmail, resendVerificationEmail } from '@artatol-acp/auth-nextjs/server';
247
+ import { redirect } from 'next/navigation';
248
+
249
+ export async function verifyEmailAction(token: string) {
250
+ try {
251
+ await verifyEmail(token);
252
+ redirect('/login?verified=true');
253
+ } catch (error) {
254
+ redirect('/verification-error');
255
+ }
256
+ }
257
+
258
+ export async function resendVerificationAction(email: string) {
259
+ await resendVerificationEmail(email);
260
+ // Always succeeds to prevent email enumeration
261
+ return { message: 'If the email exists, a verification link has been sent' };
262
+ }
263
+ ```
264
+
265
+ ### Client Component Example
266
+
267
+ ```typescript
268
+ 'use client';
269
+
270
+ import { useAuth } from '@artatol-acp/auth-nextjs/client';
271
+
272
+ export function ResendVerificationButton({ email }: { email: string }) {
273
+ const { resendVerification } = useAuth();
274
+ const [sent, setSent] = useState(false);
275
+
276
+ const handleResend = async () => {
277
+ await resendVerification(email);
278
+ setSent(true);
279
+ };
280
+
281
+ return (
282
+ <button onClick={handleResend} disabled={sent}>
283
+ {sent ? 'Email Sent' : 'Resend Verification Email'}
284
+ </button>
285
+ );
286
+ }
287
+ ```
288
+
289
+ ### Handling Unverified Users
290
+
291
+ When an unverified user tries to log in, they will receive an error:
292
+
293
+ ```typescript
294
+ export async function loginAction(formData: FormData) {
295
+ const email = formData.get('email') as string;
296
+ const password = formData.get('password') as string;
297
+
298
+ try {
299
+ const result = await login(email, password);
300
+
301
+ if ('requiresTwoFactor' in result) {
302
+ return { requires2FA: true, tempToken: result.tempToken };
303
+ }
304
+
305
+ redirect('/dashboard');
306
+ } catch (error: any) {
307
+ if (error.message?.includes('Email not verified')) {
308
+ return { error: 'Please verify your email before logging in' };
309
+ }
310
+ throw error;
311
+ }
312
+ }
313
+ ```
314
+
185
315
  ## Environment Variables
186
316
 
187
317
  ```env
188
318
  ACP_AUTH_URL=https://sso.artatol.com
319
+ ACP_AUTH_API_KEY=your-api-key-here
189
320
  NEXT_PUBLIC_ACP_AUTH_URL=https://sso.artatol.com
190
321
  ```
191
322
 
@@ -200,7 +331,9 @@ NEXT_PUBLIC_ACP_AUTH_URL=https://sso.artatol.com
200
331
  - `refreshAccessToken()` - Refresh access token using refresh token cookie
201
332
  - `login(email, password)` - Login user
202
333
  - `logout()` - Logout user
203
- - `register(email, password)` - Register new user
334
+ - `register(email, password)` - Register new user (sends verification email)
335
+ - `verifyEmail(token)` - Verify user's email address
336
+ - `resendVerificationEmail(email)` - Resend verification email
204
337
 
205
338
  ### Client Hooks
206
339
 
@@ -6,7 +6,7 @@ const ACPAuthContext = createContext(null);
6
6
  export function ACPAuthProvider({ children, baseUrl }) {
7
7
  const [user, setUser] = useState(null);
8
8
  const [isLoading, setIsLoading] = useState(true);
9
- const [client] = useState(() => new ACPAuthClient({ baseUrl }));
9
+ const [client] = useState(() => new ACPAuthClient({ baseUrl, apiKey: '' }));
10
10
  const refresh = async () => {
11
11
  try {
12
12
  await client.refresh();
@@ -1,6 +1,7 @@
1
1
  import { ACPAuthClient, type User, type LoginResult } from '@artatol-acp/auth-js';
2
2
  export type ACPAuthServerOptions = {
3
3
  baseUrl: string;
4
+ apiKey: string;
4
5
  jwtPublicKey: string;
5
6
  };
6
7
  export declare function initACPAuth(options: ACPAuthServerOptions): ACPAuthClient;
@@ -6,7 +6,10 @@ let publicKey = null;
6
6
  let config = null;
7
7
  export function initACPAuth(options) {
8
8
  config = options;
9
- authClient = new ACPAuthClient({ baseUrl: options.baseUrl });
9
+ authClient = new ACPAuthClient({
10
+ baseUrl: options.baseUrl,
11
+ apiKey: options.apiKey,
12
+ });
10
13
  return authClient;
11
14
  }
12
15
  async function getPublicKey() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artatol-acp/auth-nextjs",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Next.js SDK for Artatol Cloud Platform Authentication",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -27,11 +27,6 @@
27
27
  "files": [
28
28
  "dist"
29
29
  ],
30
- "scripts": {
31
- "build": "tsc",
32
- "dev": "tsc --watch",
33
- "typecheck": "tsc --noEmit"
34
- },
35
30
  "keywords": [
36
31
  "acp",
37
32
  "auth",
@@ -45,8 +40,8 @@
45
40
  "author": "Artatol",
46
41
  "license": "MIT",
47
42
  "dependencies": {
48
- "@artatol-acp/auth-js": "workspace:*",
49
- "jose": "^6.1.3"
43
+ "jose": "^6.1.3",
44
+ "@artatol-acp/auth-js": "0.2.0"
50
45
  },
51
46
  "peerDependencies": {
52
47
  "next": ">=15.0.0",
@@ -61,5 +56,10 @@
61
56
  },
62
57
  "publishConfig": {
63
58
  "access": "public"
59
+ },
60
+ "scripts": {
61
+ "build": "tsc",
62
+ "dev": "tsc --watch",
63
+ "typecheck": "tsc --noEmit"
64
64
  }
65
- }
65
+ }