@authaz/next 0.0.1 → 1.0.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/CLAUDE.md DELETED
@@ -1,118 +0,0 @@
1
- # CLAUDE.md
2
-
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
-
5
- ## Project Overview
6
-
7
- This is the **Authaz SDK for JavaScript/TypeScript**, providing authentication and user management for the Authaz platform. The SDK supports Universal Login flow with OAuth2/OIDC, PKCE, and secure session management.
8
-
9
- ## Development Commands
10
-
11
- ### Building
12
- ```bash
13
- npm run build # Build using tsdown (outputs to dist/)
14
- npm run prepare # Build script (runs on npm install)
15
- ```
16
-
17
- ### Testing
18
- ```bash
19
- npm test # Run Jest tests
20
- npm run test:watch # Run tests in watch mode
21
- npm run test:coverage # Run tests with coverage report (80% threshold)
22
- ```
23
-
24
- ### Linting
25
- ```bash
26
- npm run lint # Check code with ESLint
27
- npm run lint:fix # Fix linting issues automatically
28
- ```
29
-
30
- ### Releasing
31
- ```bash
32
- npm run release # Build and create patch release
33
- npm run release:patch # Bump patch version and push with tags
34
- npm run release:minor # Bump minor version and push with tags
35
- npm run release:major # Bump major version and push with tags
36
- ```
37
-
38
- ## Architecture Overview
39
-
40
- ### Core Service Structure
41
-
42
- The SDK follows a **layered service architecture**:
43
-
44
- 1. **ApiService** (`src/api.ts`) - Main entry point that orchestrates child services
45
- - Initializes configuration via `createConfig()`
46
- - Delegates to specialized services: `UserApiService`, `UniversalLoginApiService`
47
- - Provides high-level methods: `getMe()`, `getUniversalLoginUrl()`, `getUniversalLoginAccessToken()`
48
-
49
- 2. **BaseApiService** (`src/shared/base-api.ts`) - Abstract base class for all API services
50
- - Manages authentication tokens (API token, CSRF token, Session token)
51
- - Initializes on construction: fetches CSRF token → gets API token (client credentials grant)
52
- - Updates Axios instances with tokens via `updateAxiosTokens()`
53
- - Provides two Axios instances: `apiAxiosInstance` (for API calls) and `universalLoginAxiosInstance` (for OAuth flow)
54
-
55
- 3. **Specialized Services** (extend BaseApiService)
56
- - `UserApiService` (`src/general/user/api.ts`) - User profile operations
57
- - `UniversalLoginApiService` (`src/flows/universal-login/api.ts`) - OAuth2/OIDC Universal Login flow
58
-
59
- ### HTTP Client Layer
60
-
61
- **AuthazAxiosInstance** (`src/shared/axios-instance.ts`) - Wraps Axios with automatic token injection
62
- - Request interceptor adds: `X-Client-Authorization`, `X-CSRF-Token`, `X-Session-Token` headers
63
- - Tokens are updated via `updateTokens()` method
64
- - All HTTP methods (get, post, put, delete, patch) return typed responses
65
-
66
- ### Configuration System
67
-
68
- **Config** (`src/config.ts`) - Environment-aware configuration
69
- - Detects production vs development via `NODE_ENV`
70
- - Production defaults: `api.authaz.com`, `authaz.com`
71
- - Development defaults: `localhost:5138`
72
- - Validates required fields: `clientId`, `clientSecret`, `organizationId`, `redirectUri`, `tenantId`
73
-
74
- ### Type System
75
-
76
- The SDK uses a **dual-type approach**:
77
-
78
- 1. **Raw HTTP Types** (`src/http-types.ts`) - Direct server responses (e.g., `RawApiTokenResponse`, `RawUserProfileResponse`)
79
- 2. **Processed Types** (`src/types.ts` + flow-specific types) - SDK-transformed responses with status codes
80
-
81
- Exported via namespace: `import type * as HttpTypes from "@authaz/sdk"`
82
-
83
- ### Universal Login Flow
84
-
85
- OAuth2/OIDC with PKCE implementation (`src/flows/universal-login/api.ts`):
86
- 1. `redirectToLogin()` - Generates PKCE challenge, state parameter, and authorization URL
87
- 2. `getUniversalLoginAccessToken()` - Exchanges authorization code for access/refresh tokens
88
- 3. Uses Web Crypto API for SHA-256 hashing and secure random generation
89
-
90
- ## Key Implementation Details
91
-
92
- ### Token Management
93
- - All services extend `BaseApiService` which handles 3-token system: API token (client credentials), CSRF token, Session token
94
- - Tokens are automatically injected into requests via Axios interceptors
95
- - Base service constructor chains: get CSRF → get API token → update Axios instances
96
-
97
- ### Build Configuration
98
- - Uses `tsdown` for bundling (not tsc)
99
- - Output: ESM format only, with TypeScript declarations
100
- - External dependencies: Next.js, React, routing libraries (not bundled)
101
- - Tree-shaking enabled for optimal bundle size
102
-
103
- ### Testing Setup
104
- - Jest with ts-jest preset
105
- - 80% coverage threshold required (branches, functions, lines, statements)
106
- - Test files: `**/__tests__/**/*.ts` or `**/*.{spec,test}.ts`
107
-
108
- ### Peer Dependencies
109
- - Next.js >=13.0.0
110
- - nookies >=2.5.2 (for cookie management in Next.js)
111
-
112
- ## Important Notes
113
-
114
- - The SDK is designed for Next.js applications (see peer dependencies)
115
- - Environment detection relies on `process.env.NODE_ENV`
116
- - All API calls use `withCredentials: true` for cookie handling
117
- - PKCE implementation uses `S256` method (SHA-256)
118
- - Session management utilities are exported but implementation is in `src/utils/session.ts`
@@ -1,171 +0,0 @@
1
- # Environment Configuration - Authaz SDK
2
-
3
- The SDK now automatically detects the environment (development or production) and applies the appropriate configurations.
4
-
5
- ## 🔧 How It Works
6
-
7
- The `DEFAULT_CONFIG` now reads from environment variables first, with fallback based on `NODE_ENV`:
8
-
9
- ### 📋 Environment Variables (Priority)
10
- - `AUTHAZ_API_URL` - API URL
11
- - `AUTHAZ_DOMAIN` - Authaz Domain
12
- - `AUTHAZ_UNIVERSAL_LOGIN_URL` - Universal Login URL
13
-
14
- ### 🏠 Development (Fallback)
15
- - **When**: `NODE_ENV !== 'production'` and environment variables are not defined
16
- - **URLs**:
17
- - `baseUrl`: `http://localhost:5138/api`
18
- - `universalLoginUrl`: `http://localhost:5138`
19
- - `authazDomain`: `http://localhost:5138`
20
-
21
- ### 🚀 Production (Fallback)
22
- - **When**: `NODE_ENV === 'production'` and environment variables are not defined
23
- - **URLs**:
24
- - `baseUrl`: `https://api.authaz.com`
25
- - `universalLoginUrl`: `https://authaz.com`
26
- - `authazDomain`: `https://authaz.com`
27
-
28
- ## 💻 Practical Usage
29
-
30
- ### Automatic Configuration (Recommended)
31
- ```typescript
32
- import { ApiService } from 'authaz-sdk-js'
33
-
34
- // URLs are automatically detected based on environment
35
- const authazClient = new ApiService({
36
- clientId: 'your-client-id',
37
- clientSecret: 'your-client-secret',
38
- authPoolId: 'your-auth-pool-id',
39
- organizationId: 'your-organization-id',
40
- redirectUri: 'your-redirect-uri'
41
- // baseUrl, authazDomain and universalLoginUrl are set automatically
42
- })
43
- ```
44
-
45
- ### Manual Override (Optional)
46
- ```typescript
47
- // You can still override URLs if needed
48
- const authazClient = new ApiService({
49
- clientId: 'your-client-id',
50
- clientSecret: 'your-client-secret',
51
- authPoolId: 'your-auth-pool-id',
52
- organizationId: 'your-organization-id',
53
- redirectUri: 'your-redirect-uri',
54
- baseUrl: 'https://api-custom.authaz.com', // Manual override
55
- authazDomain: 'https://custom.authaz.com'
56
- })
57
- ```
58
-
59
- ## 🌍 Environment Detection
60
-
61
- ### Node.js (Backend)
62
- ```javascript
63
- // Development
64
- process.env.NODE_ENV = 'development' // or undefined
65
-
66
- // Production
67
- process.env.NODE_ENV = 'production'
68
- ```
69
-
70
- ### Browser (Frontend)
71
- ```javascript
72
- // Development
73
- window.location.hostname = 'localhost' // or '127.0.0.1'
74
-
75
- // Production
76
- window.location.hostname = 'myapp.com' // any domain that is not localhost
77
- ```
78
-
79
- ## 🔍 Debug
80
-
81
- To verify which environment was detected, you can check in the console:
82
-
83
- ```typescript
84
- import { DEFAULT_CONFIG } from 'authaz-sdk-js'
85
-
86
- console.log('Detected configuration:', DEFAULT_CONFIG)
87
- // Development: { baseUrl: 'http://localhost:5138/api', ... }
88
- // Production: { baseUrl: 'https://api.authaz.com', ... }
89
- ```
90
-
91
- ## 📝 Complete Example
92
-
93
- ```typescript
94
- // authaz.config.ts
95
- import { ApiService } from 'authaz-sdk-js'
96
-
97
- export const createAuthazClient = () => {
98
- return new ApiService({
99
- clientId: process.env.NEXT_PUBLIC_CLIENT_ID!,
100
- clientSecret: process.env.CLIENT_SECRET!,
101
- authPoolId: process.env.NEXT_PUBLIC_AUTH_POOL_ID!,
102
- organizationId: process.env.NEXT_PUBLIC_ORGANIZATION_ID!,
103
- redirectUri: process.env.NEXT_PUBLIC_REDIRECT_URI!
104
- // URLs are automatically set based on environment
105
- })
106
- }
107
-
108
- // In development: will use localhost:5138
109
- // In production: will use api.authaz.com
110
- ```
111
-
112
- ## ⚙️ Environment Variables
113
-
114
- ### Development (.env.local)
115
- ```env
116
- NODE_ENV=development
117
-
118
- # Authaz URLs (optional - uses localhost if not defined)
119
- AUTHAZ_API_URL=http://localhost:5138/api
120
- AUTHAZ_DOMAIN=http://localhost:5138
121
- AUTHAZ_UNIVERSAL_LOGIN_URL=http://localhost:5138
122
-
123
- # Credentials
124
- NEXT_PUBLIC_CLIENT_ID=dev-client-id
125
- CLIENT_SECRET=dev-client-secret
126
- NEXT_PUBLIC_AUTH_POOL_ID=dev-auth-pool
127
- NEXT_PUBLIC_ORGANIZATION_ID=dev-org-id
128
- NEXT_PUBLIC_REDIRECT_URI=http://localhost:3000/auth/callback
129
- ```
130
-
131
- ### Production (.env.production)
132
- ```env
133
- NODE_ENV=production
134
-
135
- # Authaz URLs (optional - uses api.authaz.com if not defined)
136
- AUTHAZ_API_URL=https://api.authaz.com
137
- AUTHAZ_DOMAIN=https://authaz.com
138
- AUTHAZ_UNIVERSAL_LOGIN_URL=https://authaz.com
139
-
140
- # Credentials
141
- NEXT_PUBLIC_CLIENT_ID=prod-client-id
142
- CLIENT_SECRET=prod-client-secret
143
- NEXT_PUBLIC_AUTH_POOL_ID=prod-auth-pool
144
- NEXT_PUBLIC_ORGANIZATION_ID=prod-org-id
145
- NEXT_PUBLIC_REDIRECT_URI=https://myapp.com/auth/callback
146
- ```
147
-
148
- ### Staging/Custom (.env.staging)
149
- ```env
150
- NODE_ENV=staging
151
-
152
- # Custom URLs
153
- AUTHAZ_API_URL=https://api-staging.authaz.com
154
- AUTHAZ_DOMAIN=https://staging.authaz.com
155
- AUTHAZ_UNIVERSAL_LOGIN_URL=https://staging.authaz.com
156
-
157
- # Credentials
158
- NEXT_PUBLIC_CLIENT_ID=staging-client-id
159
- CLIENT_SECRET=staging-client-secret
160
- NEXT_PUBLIC_AUTH_POOL_ID=staging-auth-pool
161
- NEXT_PUBLIC_ORGANIZATION_ID=staging-org-id
162
- NEXT_PUBLIC_REDIRECT_URI=https://staging.myapp.com/auth/callback
163
- ```
164
-
165
- ## ✅ Advantages
166
-
167
- 1. **Automatic**: No need to manually configure URLs
168
- 2. **Safe**: Prevents using development URLs in production
169
- 3. **Simple**: Just configure credentials, URLs are automatic
170
- 4. **Flexible**: Still allows manual override when needed
171
- 5. **Compatible**: Works in both Node.js and Browser
@@ -1,276 +0,0 @@
1
- # Authaz SDK - Axios Instance
2
-
3
- ## Overview
4
-
5
- The SDK now uses a custom Axios instance that automatically adds the necessary authentication tokens (`ApiToken` and `CsrfToken`) to the headers of all requests.
6
-
7
- ## Architecture
8
-
9
- ### AuthazAxiosInstance
10
-
11
- The `AuthazAxiosInstance` class manages an Axios instance with configured interceptors:
12
-
13
- ```typescript
14
- import { AuthazAxiosInstance } from './shared/axios-instance';
15
-
16
- // Create an instance with base URL
17
- const axiosInstance = new AuthazAxiosInstance('https://api.authaz.com');
18
-
19
- // Update tokens
20
- axiosInstance.updateTokens(apiToken, csrfToken);
21
-
22
- // Make requests that automatically include tokens
23
- const data = await axiosInstance.get('/users');
24
- const response = await axiosInstance.post('/auth/login', { email, password });
25
- ```
26
-
27
- ### Automatic Interceptors
28
-
29
- The Axios instance includes interceptors that:
30
-
31
- 1. **Request Interceptor**: Automatically adds headers:
32
- - `X-Client-Authorization: Bearer {apiToken}`
33
- - `X-CSRF-Token: {csrfToken}`
34
-
35
- 2. **Response Interceptor**: Handles errors consistently
36
-
37
- ### Integration with BaseApiService
38
-
39
- The `BaseApiService` class now includes an instance of `AuthazAxiosInstance`:
40
-
41
- ```typescript
42
- export abstract class BaseApiService {
43
- protected axiosInstance: AuthazAxiosInstance;
44
-
45
- constructor(...) {
46
- this.axiosInstance = new AuthazAxiosInstance(baseUrl);
47
- // ...
48
- }
49
-
50
- // Method to update tokens in the axios instance
51
- protected updateAxiosTokens(): void {
52
- this.axiosInstance.updateTokens(this.ApiToken, this.CsrfToken);
53
- }
54
- }
55
- ```
56
-
57
- ## Benefits
58
-
59
- 1. **Automation**: No longer necessary to manually add authentication headers
60
- 2. **Consistency**: All services inherit the same authentication configuration
61
- 3. **Maintainability**: Changes to authentication logic are centralized
62
- 4. **Type Safety**: Full TypeScript support with generic types
63
-
64
- ## Usage in Services
65
-
66
- ### Before (with fetch)
67
-
68
- ```typescript
69
- const response = await fetch(`${this.baseUrl}/auth/login`, {
70
- method: 'POST',
71
- headers: {
72
- 'Content-Type': 'application/json',
73
- 'X-Client-Authorization': `Bearer ${apiToken}`,
74
- 'X-CSRF-Token': csrfToken,
75
- },
76
- body: JSON.stringify({ email, password }),
77
- });
78
- ```
79
-
80
- ### After (with axios instance)
81
-
82
- ```typescript
83
- const data = await this.axiosInstance.post<LoginResponse>(
84
- '/auth/login',
85
- { email, password }
86
- );
87
- ```
88
-
89
- ## Available Methods
90
-
91
- The Axios instance offers convenient methods:
92
-
93
- - `get<T>(url, config?)`: GET requests
94
- - `post<T>(url, data?, config?)`: POST requests
95
- - `put<T>(url, data?, config?)`: PUT requests
96
- - `delete<T>(url, config?)`: DELETE requests
97
- - `patch<T>(url, data?, config?)`: PATCH requests
98
-
99
- ## Token Updates
100
-
101
- Tokens are automatically updated when:
102
-
103
- 1. CSRF token is obtained via `getCsrfToken()`
104
- 2. API token is obtained via `getApiToken()`
105
- 3. Both are updated in the axios instance via `updateAxiosTokens()`
106
-
107
- ## Error Handling
108
-
109
- The Axios instance includes consistent error handling:
110
-
111
- ```typescript
112
- try {
113
- const data = await this.axiosInstance.post('/auth/login', credentials);
114
- return { status: 'success', data };
115
- } catch (error) {
116
- const axiosError = error as { response?: { status: number; data?: unknown } };
117
-
118
- if (axiosError.response?.status === 401) {
119
- return { status: 'error', message: 'Unauthorized' };
120
- }
121
-
122
- return { status: 'error', message: 'Internal error' };
123
- }
124
- ```
125
-
126
- ## Migration
127
-
128
- To migrate existing services:
129
-
130
- 1. Remove manual `fetch` calls
131
- 2. Replace with calls to `this.axiosInstance`
132
- 3. Remove manual addition of authentication headers
133
- 4. Update error handling to use Axios structure
134
-
135
- ## Complete Example
136
-
137
- ```typescript
138
- export class MyApiService extends BaseApiService {
139
- public async getUserData(userId: string): Promise<UserData> {
140
- try {
141
- // Ensure tokens are up to date
142
- await this.getApiToken();
143
-
144
- // Make request - headers are added automatically
145
- const data = await this.axiosInstance.get<UserData>(`/users/${userId}`);
146
-
147
- return data;
148
- } catch (error: unknown) {
149
- const axiosError = error as { response?: { status: number } };
150
-
151
- if (axiosError.response?.status === 404) {
152
- throw new Error('User not found');
153
- }
154
-
155
- throw new Error('Error fetching user data');
156
- }
157
- }
158
- }
159
- ```
160
-
161
- # AuthazAxiosInstance - Per-Request Cookies
162
-
163
- This document explains how to use request-specific cookies in `AuthazAxiosInstance`.
164
-
165
- ## Configuration
166
-
167
- The `AuthazAxiosInstance` now supports request-specific cookies through the `cookies` property in the configuration.
168
-
169
- ## Interface
170
-
171
- ```typescript
172
- interface AuthazRequestConfig extends AxiosRequestConfig {
173
- cookies?: Record<string, string>;
174
- }
175
- ```
176
-
177
- ## Usage Examples
178
-
179
- ### 1. GET Request with cookies
180
-
181
- ```typescript
182
- const axiosInstance = new AuthazAxiosInstance('https://api.example.com');
183
-
184
- // GET request with specific cookies
185
- const response = await axiosInstance.get('/users', {
186
- cookies: {
187
- 'sessionId': 'abc123',
188
- 'userId': 'user456'
189
- }
190
- });
191
- ```
192
-
193
- ### 2. POST Request with cookies
194
-
195
- ```typescript
196
- // POST request with cookies
197
- const response = await axiosInstance.post('/login', {
198
- email: 'user@example.com',
199
- password: 'password123'
200
- }, {
201
- cookies: {
202
- 'sessionId': 'new-session-123',
203
- 'theme': 'dark'
204
- }
205
- });
206
- ```
207
-
208
- ### 3. PUT Request with cookies
209
-
210
- ```typescript
211
- // PUT request with cookies
212
- const response = await axiosInstance.put('/users/123', {
213
- name: 'John Doe',
214
- email: 'john@example.com'
215
- }, {
216
- cookies: {
217
- 'sessionId': 'abc123',
218
- 'lastUpdate': Date.now().toString()
219
- }
220
- });
221
- ```
222
-
223
- ### 4. DELETE Request with cookies
224
-
225
- ```typescript
226
- // DELETE request with cookies
227
- const response = await axiosInstance.delete('/users/123', {
228
- cookies: {
229
- 'sessionId': 'abc123',
230
- 'action': 'delete'
231
- }
232
- });
233
- ```
234
-
235
- ### 5. PATCH Request with cookies
236
-
237
- ```typescript
238
- // PATCH request with cookies
239
- const response = await axiosInstance.patch('/users/123', {
240
- name: 'Jane Doe'
241
- }, {
242
- cookies: {
243
- 'sessionId': 'abc123',
244
- 'updateType': 'name'
245
- }
246
- });
247
- ```
248
-
249
- ## Advantages
250
-
251
- 1. **Flexibility**: Each request can have its own cookies
252
- 2. **Isolation**: Cookies from one request don't affect others
253
- 3. **Control**: Allows granular control over cookies per operation
254
- 4. **Security**: Prevents cookie leakage between different contexts
255
-
256
- ## Global Tokens
257
-
258
- API and CSRF tokens continue to be configured globally:
259
-
260
- ```typescript
261
- // Configure global tokens
262
- axiosInstance.updateTokens('api-token-123', 'csrf-token-456');
263
-
264
- // Or individually
265
- axiosInstance.updateApiToken('api-token-123');
266
- axiosInstance.updateCsrfToken('csrf-token-456');
267
- ```
268
-
269
- ## Interceptor
270
-
271
- The interceptor automatically:
272
- 1. Adds API token if configured
273
- 2. Adds CSRF token if configured
274
- 3. Adds request-specific cookies if configured
275
-
276
- All headers are added automatically in each request.