@intelicity/gates-sdk 0.1.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 ADDED
@@ -0,0 +1,375 @@
1
+ # Gates SDK
2
+
3
+ Simple SDK for authenticating users with AWS Cognito JWT tokens and managing user data.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @intelicity/gates-sdk
9
+ ```
10
+
11
+ ## Features
12
+
13
+ - šŸ”’ JWT token verification with AWS Cognito
14
+ - šŸ‘„ User management service with backend integration
15
+ - šŸŽÆ TypeScript support with full type definitions
16
+ - šŸ’¾ Built-in JWKS caching for better performance
17
+ - šŸŽØ Custom error classes for better error handling
18
+ - šŸ” Group-based access control
19
+
20
+ ## Usage
21
+
22
+ ### Authentication Service
23
+
24
+ The `AuthService` provides JWT token verification with AWS Cognito:
25
+
26
+ ```typescript
27
+ import { AuthService } from "@intelicity/gates-sdk";
28
+
29
+ const authService = new AuthService(
30
+ "sa-east-1", // AWS region
31
+ "sa-east-1_xxxxxxxxx", // User Pool ID
32
+ "your-client-id", // Audience (client ID)
33
+ ["admin", "user"] // Optional: required groups
34
+ );
35
+
36
+ // Verify a token
37
+ try {
38
+ const user = await authService.verifyToken(token);
39
+ console.log("Authenticated user:", user);
40
+
41
+ // Check group membership
42
+ const isAdmin = authService.isMemberOf(user.groups || []);
43
+ console.log("Has required group:", isAdmin);
44
+ } catch (error) {
45
+ console.error("Authentication failed:", error.message);
46
+ }
47
+ ```
48
+
49
+ ### User Service
50
+
51
+ The `UserService` provides user management capabilities:
52
+
53
+ ```typescript
54
+ import { UserService } from "@intelicity/gates-sdk";
55
+
56
+ const userService = new UserService(
57
+ "https://api.example.com", // Backend API URL
58
+ "your-system-name" // System identifier
59
+ );
60
+
61
+ // Get all users from the system
62
+ try {
63
+ const users = await userService.getAllUsers(idToken);
64
+ console.log("Users:", users.profiles);
65
+ console.log("Total:", users.total);
66
+ } catch (error) {
67
+ console.error("Failed to fetch users:", error.message);
68
+ }
69
+
70
+ // Get specific user by ID
71
+ try {
72
+ const user = await userService.getUserById(idToken, "user-id-123");
73
+ console.log("User details:", user);
74
+ } catch (error) {
75
+ console.error("Failed to fetch user:", error.message);
76
+ }
77
+ ```
78
+
79
+ ### Complete Integration Example
80
+
81
+ ```typescript
82
+ import { AuthService, UserService } from "@intelicity/gates-sdk";
83
+
84
+ class MyApplication {
85
+ private authService: AuthService;
86
+ private userService: UserService;
87
+
88
+ constructor() {
89
+ this.authService = new AuthService(
90
+ process.env.AWS_REGION!,
91
+ process.env.COGNITO_USER_POOL_ID!,
92
+ process.env.COGNITO_CLIENT_ID!,
93
+ ["admin"] // Only admins can access
94
+ );
95
+
96
+ this.userService = new UserService(
97
+ process.env.BACKEND_URL!,
98
+ process.env.SYSTEM_NAME!
99
+ );
100
+ }
101
+
102
+ async handleRequest(authToken: string) {
103
+ try {
104
+ // 1. Authenticate user
105
+ const user = await this.authService.verifyToken(authToken);
106
+ console.log(`User ${user.name} authenticated successfully`);
107
+
108
+ // 2. Get user list if authorized
109
+ const users = await this.userService.getAllUsers(authToken);
110
+
111
+ return {
112
+ currentUser: user,
113
+ allUsers: users.profiles,
114
+ total: users.total,
115
+ };
116
+ } catch (error) {
117
+ throw new Error(`Operation failed: ${error.message}`);
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ ### Error Handling
124
+
125
+ The SDK provides custom error classes for better error handling:
126
+
127
+ ```typescript
128
+ import {
129
+ AuthService,
130
+ UserService,
131
+ AuthenticationError,
132
+ TokenExpiredError,
133
+ InvalidTokenError,
134
+ MissingAuthorizationError,
135
+ } from "@intelicity/gates-sdk";
136
+
137
+ const authService = new AuthService(region, userPoolId, audience);
138
+
139
+ try {
140
+ const user = await authService.verifyToken(token);
141
+ } catch (error) {
142
+ if (error instanceof TokenExpiredError) {
143
+ console.error("Token expired, please login again");
144
+ } else if (error instanceof InvalidTokenError) {
145
+ console.error("Invalid token provided");
146
+ } else if (error instanceof MissingAuthorizationError) {
147
+ console.error("No authorization token provided");
148
+ } else {
149
+ console.error("Authentication failed:", error.message);
150
+ }
151
+ }
152
+
153
+ // Error handling with User Service
154
+ try {
155
+ const users = await userService.getAllUsers(token);
156
+ } catch (error) {
157
+ if (error.message.includes("HTTP 401")) {
158
+ console.error("Unauthorized - check your token");
159
+ } else if (error.message.includes("HTTP 403")) {
160
+ console.error("Forbidden - insufficient permissions");
161
+ } else {
162
+ console.error("Failed to fetch users:", error.message);
163
+ }
164
+ }
165
+ ```
166
+
167
+ ## API Reference
168
+
169
+ ### `AuthService`
170
+
171
+ Main service for JWT token verification with AWS Cognito.
172
+
173
+ #### Constructor
174
+
175
+ ```typescript
176
+ new AuthService(region, userPoolId, audience, requiredGroup?)
177
+ ```
178
+
179
+ **Parameters:**
180
+
181
+ - `region` (string): AWS region (e.g., 'sa-east-1')
182
+ - `userPoolId` (string): Cognito User Pool ID
183
+ - `audience` (string): Expected audience claim (client ID)
184
+ - `requiredGroup` (string | string[], optional): Required Cognito groups
185
+
186
+ #### Methods
187
+
188
+ ##### `verifyToken(token: string): Promise<GatesUser>`
189
+
190
+ Verifies a JWT token and returns the authenticated user.
191
+
192
+ ##### `isMemberOf(groups: string[]): boolean`
193
+
194
+ Checks if the user groups match the required groups.
195
+
196
+ ### `UserService`
197
+
198
+ Service for managing users through a backend API.
199
+
200
+ #### Constructor
201
+
202
+ ```typescript
203
+ new UserService(baseUrl, system);
204
+ ```
205
+
206
+ **Parameters:**
207
+
208
+ - `baseUrl` (string): Backend API base URL
209
+ - `system` (string): System identifier
210
+
211
+ #### Methods
212
+
213
+ ##### `getAllUsers(idToken: string): Promise<UserListResponse>`
214
+
215
+ Retrieves all users from the system.
216
+
217
+ ##### `getUserById(idToken: string, userId: string): Promise<Profile>`
218
+
219
+ Retrieves a specific user by ID.
220
+
221
+ ### Types
222
+
223
+ #### `GatesUser`
224
+
225
+ ```typescript
226
+ type GatesUser = {
227
+ user_id: string; // Mapped from 'sub' claim
228
+ email: string; // User email
229
+ name: string; // User display name
230
+ role: string; // Mapped from 'custom:general_role'
231
+ exp: number; // Token expiration timestamp
232
+ iat: number; // Token issued at timestamp
233
+ };
234
+ ```
235
+
236
+ #### `Profile`
237
+
238
+ ```typescript
239
+ type Profile = {
240
+ user_id: string;
241
+ email: string;
242
+ name: string;
243
+ enabled: boolean;
244
+ profile_attributes: ProfileAttribute[];
245
+ };
246
+
247
+ type ProfileAttribute = {
248
+ attribute_name: string;
249
+ value: string | boolean | number;
250
+ };
251
+ ```
252
+
253
+ #### `UserListResponse`
254
+
255
+ ```typescript
256
+ type UserListResponse = {
257
+ profiles: Profile[];
258
+ total?: number;
259
+ page?: number;
260
+ limit?: number;
261
+ nextToken?: string;
262
+ };
263
+ ```
264
+
265
+ #### `VerifyOptions`
266
+
267
+ ```typescript
268
+ type VerifyOptions = {
269
+ region: string;
270
+ userPoolId: string;
271
+ audience: string;
272
+ requiredGroup?: string | string[];
273
+ };
274
+ ```
275
+
276
+ #### Custom Errors
277
+
278
+ - `AuthenticationError`: Base authentication error class
279
+ - `TokenExpiredError`: Token has expired
280
+ - `InvalidTokenError`: Token is invalid or malformed
281
+ - `MissingAuthorizationError`: Authorization header is missing
282
+
283
+ ## Environment Variables
284
+
285
+ You can configure the SDK using environment variables:
286
+
287
+ ```bash
288
+ # .env file
289
+ GATES_REGION=sa-east-1
290
+ GATES_USER_POOL_ID=sa-east-1_xxxxxxxxx
291
+ GATES_CLIENT_ID=your-cognito-client-id
292
+ GATES_BACKEND_URL=https://your-backend-api.com
293
+ GATES_SYSTEM_NAME=your-system-name
294
+ ```
295
+
296
+ Example usage with environment variables:
297
+
298
+ ```typescript
299
+ import { AuthService, UserService } from "@intelicity/gates-sdk";
300
+
301
+ const authService = new AuthService(
302
+ process.env.GATES_REGION!,
303
+ process.env.GATES_USER_POOL_ID!,
304
+ process.env.GATES_CLIENT_ID!
305
+ );
306
+
307
+ const userService = new UserService(
308
+ process.env.GATES_BACKEND_URL!,
309
+ process.env.GATES_SYSTEM_NAME!
310
+ );
311
+ ```
312
+
313
+ **Note:** The application is responsible for loading the `.env` file (e.g., using `dotenv` package). The SDK reads from `process.env`.
314
+
315
+ ## Security Best Practices
316
+
317
+ ### Token Handling
318
+
319
+ - Never log or expose JWT tokens in production
320
+ - Always use HTTPS in production environments
321
+ - Implement proper token refresh mechanisms
322
+ - Store tokens securely on the client side
323
+
324
+ ### Error Handling
325
+
326
+ - Don't expose sensitive error details to end users
327
+ - Log authentication failures for security monitoring
328
+ - Implement rate limiting for authentication endpoints
329
+
330
+ ### Configuration
331
+
332
+ - Use environment variables for sensitive configuration
333
+ - Validate all configuration parameters at startup
334
+ - Use strong, unique audience values (client IDs)
335
+
336
+ ```typescript
337
+ // Good: Secure error handling
338
+ try {
339
+ const user = await authService.verifyToken(token);
340
+ } catch (error) {
341
+ // Log for monitoring (server-side only)
342
+ console.error('Auth failed:', error.constructor.name);
343
+
344
+ // Return generic error to client
345
+ throw new Error('Authentication failed');
346
+ }
347
+
348
+ // Bad: Exposing sensitive information
349
+ catch (error) {
350
+ throw new Error(`Auth failed: ${error.message}`); // May expose internal details
351
+ }
352
+ ```
353
+
354
+ ## Development
355
+
356
+ ```bash
357
+ # Install dependencies
358
+ npm install
359
+
360
+ # Build
361
+ npm run build
362
+
363
+ # Lint
364
+ npm run lint
365
+
366
+ # Type check
367
+ npm run typecheck
368
+
369
+ # Run tests
370
+ npm test
371
+ ```
372
+
373
+ ## License
374
+
375
+ MIT
@@ -0,0 +1,40 @@
1
+ // // src/auth/middleware.ts
2
+ // import type { FastifyRequest, FastifyReply } from "fastify";
3
+ // import { verifyToken, type VerifyOptions } from "./verifier.js";
4
+ // import {
5
+ // MissingAuthorizationError,
6
+ // InvalidTokenError,
7
+ // TokenExpiredError,
8
+ // } from "../errors/error.js";
9
+ // import type { GatesUser } from "../models/user.js";
10
+ export {};
11
+ // // Extend FastifyRequest to include user
12
+ // declare module "fastify" {
13
+ // interface FastifyRequest {
14
+ // user?: GatesUser;
15
+ // }
16
+ // }
17
+ // export type GatesMiddlewareConfig = VerifyOptions;
18
+ // /**
19
+ // * Fastify middleware to verify JWT tokens from AWS Cognito
20
+ // * @param config Configuration with region, userPoolId, and optional audience
21
+ // * @returns Fastify preHandler hook
22
+ // */
23
+ // export function gatesMiddleware(config: GatesMiddlewareConfig) {
24
+ // return async (request: FastifyRequest, reply: FastifyReply) => {
25
+ // const authHeader = request.headers.authorization;
26
+ // if (!authHeader) {
27
+ // throw new MissingAuthorizationError();
28
+ // }
29
+ // const token = authHeader.replace(/^Bearer\s+/i, "");
30
+ // try {
31
+ // const user = await verifyToken(token, config);
32
+ // request.user = user;
33
+ // } catch (err) {
34
+ // if (err instanceof Error && err.message.includes("expired")) {
35
+ // throw new TokenExpiredError();
36
+ // }
37
+ // throw new InvalidTokenError();
38
+ // }
39
+ // };
40
+ // }
@@ -0,0 +1,37 @@
1
+ import { jwtVerify } from "jose";
2
+ import { getJwks } from "../cache/jwks-cache.js";
3
+ export async function verifyToken(token, { region, userPoolId, audience, requiredGroup }) {
4
+ if (!token) {
5
+ throw new Error("Token não fornecido");
6
+ }
7
+ const jwks = getJwks(region, userPoolId);
8
+ const issuer = `https://cognito-idp.${region}.amazonaws.com/${userPoolId}`;
9
+ const { payload } = await jwtVerify(token, jwks, {
10
+ issuer,
11
+ audience,
12
+ });
13
+ if (requiredGroup) {
14
+ const userGroups = payload["cognito:groups"];
15
+ if (!userGroups || !Array.isArray(userGroups)) {
16
+ throw new Error("UsuÔrio não pertence ao sistema");
17
+ }
18
+ const requiredGroups = Array.isArray(requiredGroup)
19
+ ? requiredGroup
20
+ : [requiredGroup];
21
+ // Verifica se o usuÔrio tem pelo menos um dos grupos obrigatórios
22
+ const hasRequiredGroup = requiredGroups.some((group) => userGroups.includes(group));
23
+ if (!hasRequiredGroup) {
24
+ throw new Error(`UsuƔrio deve ser membro de um dos seguintes sistemas: ${requiredGroups.join(", ")}`);
25
+ }
26
+ }
27
+ // Mapear o payload do Cognito para o formato do GatesUser
28
+ const user = {
29
+ user_id: payload.sub,
30
+ email: payload.email,
31
+ name: payload.name,
32
+ role: payload["custom:general_role"],
33
+ exp: payload.exp,
34
+ iat: payload.iat,
35
+ };
36
+ return user;
37
+ }
@@ -0,0 +1,21 @@
1
+ // src/cache/jwks-cache.ts
2
+ import { createRemoteJWKSet } from "jose";
3
+ const CACHE = {};
4
+ const DEFAULT_TTL_MS = 60 * 60 * 1000; // 1 hora
5
+ export function jwksUrl(region, userPoolId) {
6
+ return `https://cognito-idp.${region}.amazonaws.com/${userPoolId}/.well-known/jwks.json`;
7
+ }
8
+ /**
9
+ * Retorna um RemoteJWKSet cacheado por (region + userPoolId).
10
+ */
11
+ export function getJwks(region, userPoolId, ttlMs = DEFAULT_TTL_MS) {
12
+ const key = `${region}::${userPoolId}`;
13
+ const now = Date.now();
14
+ if (CACHE[key] && now - CACHE[key].timestamp < ttlMs) {
15
+ return CACHE[key].jwks;
16
+ }
17
+ const url = jwksUrl(region, userPoolId);
18
+ const remote = createRemoteJWKSet(new URL(url));
19
+ CACHE[key] = { jwks: remote, timestamp: now };
20
+ return remote;
21
+ }
@@ -0,0 +1,20 @@
1
+ // src/config/env.ts
2
+ /**
3
+ * Helper to load environment variables for Gates SDK
4
+ * The client application should load their own .env file before importing this SDK
5
+ */
6
+ export const getEnvConfig = () => ({
7
+ region: process.env.GATES_REGION || "sa-east-1",
8
+ userPoolId: process.env.GATES_USER_POOL_ID || "",
9
+ audience: process.env.GATES_AUDIENCE,
10
+ });
11
+ /**
12
+ * Validates that required environment variables are set
13
+ */
14
+ export const validateEnvConfig = () => {
15
+ const config = getEnvConfig();
16
+ if (!config.userPoolId) {
17
+ throw new Error("GATES_USER_POOL_ID is required. Please set it in your .env file or environment variables.");
18
+ }
19
+ return config;
20
+ };
@@ -0,0 +1,43 @@
1
+ // src/errors/error.ts
2
+ /**
3
+ * Base error class for authentication-related errors
4
+ */
5
+ export class AuthenticationError extends Error {
6
+ code;
7
+ constructor(message, code) {
8
+ super(message);
9
+ this.code = code;
10
+ this.name = "AuthenticationError";
11
+ Object.setPrototypeOf(this, AuthenticationError.prototype);
12
+ }
13
+ }
14
+ /**
15
+ * Error thrown when a token has expired
16
+ */
17
+ export class TokenExpiredError extends AuthenticationError {
18
+ constructor(message = "Token has expired") {
19
+ super(message, "TOKEN_EXPIRED");
20
+ this.name = "TokenExpiredError";
21
+ Object.setPrototypeOf(this, TokenExpiredError.prototype);
22
+ }
23
+ }
24
+ /**
25
+ * Error thrown when a token is invalid
26
+ */
27
+ export class InvalidTokenError extends AuthenticationError {
28
+ constructor(message = "Invalid token") {
29
+ super(message, "INVALID_TOKEN");
30
+ this.name = "InvalidTokenError";
31
+ Object.setPrototypeOf(this, InvalidTokenError.prototype);
32
+ }
33
+ }
34
+ /**
35
+ * Error thrown when authorization header is missing
36
+ */
37
+ export class MissingAuthorizationError extends AuthenticationError {
38
+ constructor(message = "Missing Authorization header") {
39
+ super(message, "MISSING_AUTHORIZATION");
40
+ this.name = "MissingAuthorizationError";
41
+ Object.setPrototypeOf(this, MissingAuthorizationError.prototype);
42
+ }
43
+ }
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { UserService, } from "./services/user-service.js";
2
+ export { AuthService } from "./services/auth-service.js";
3
+ export { AuthenticationError, TokenExpiredError, InvalidTokenError, MissingAuthorizationError, } from "./errors/error.js";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,80 @@
1
+ import { jwtVerify } from "jose";
2
+ import { getJwks } from "../cache/jwks-cache.js";
3
+ export class AuthService {
4
+ region;
5
+ userPoolId;
6
+ audience;
7
+ requiredGroup;
8
+ constructor(region, userPoolId, audience, requiredGroup) {
9
+ if (!region || typeof region !== "string" || region.trim().length === 0) {
10
+ throw new Error("Region é obrigatória e deve ser uma string vÔlida");
11
+ }
12
+ if (!userPoolId ||
13
+ typeof userPoolId !== "string" ||
14
+ userPoolId.trim().length === 0) {
15
+ throw new Error("UserPoolId é obrigatório e deve ser uma string vÔlida");
16
+ }
17
+ if (!audience ||
18
+ typeof audience !== "string" ||
19
+ audience.trim().length === 0) {
20
+ throw new Error("Audience é obrigatória e deve ser uma string vÔlida");
21
+ }
22
+ // Validar formato do userPoolId (deve seguir padrão AWS)
23
+ if (!/^[a-zA-Z0-9_-]+$/.test(userPoolId)) {
24
+ throw new Error("UserPoolId possui formato invƔlido");
25
+ }
26
+ this.region = region;
27
+ this.userPoolId = userPoolId;
28
+ this.audience = audience;
29
+ this.requiredGroup = requiredGroup;
30
+ }
31
+ get issuer() {
32
+ return `https://cognito-idp.${this.region}.amazonaws.com/${this.userPoolId}`;
33
+ }
34
+ isMemberOf(groups = []) {
35
+ if (!Array.isArray(groups)) {
36
+ return false;
37
+ }
38
+ if (!this.requiredGroup) {
39
+ return true;
40
+ }
41
+ const requiredGroups = Array.isArray(this.requiredGroup)
42
+ ? this.requiredGroup
43
+ : [this.requiredGroup];
44
+ return groups.some((g) => requiredGroups.includes(g));
45
+ }
46
+ async verifyToken(token) {
47
+ if (!token) {
48
+ throw new Error("Token não fornecido");
49
+ }
50
+ const jwks = getJwks(this.region, this.userPoolId);
51
+ const { payload } = await jwtVerify(token, jwks, {
52
+ issuer: this.issuer,
53
+ audience: this.audience,
54
+ });
55
+ if (this.requiredGroup) {
56
+ const userGroups = payload["cognito:groups"];
57
+ if (!userGroups || !Array.isArray(userGroups)) {
58
+ throw new Error("UsuÔrio não pertence ao sistema");
59
+ }
60
+ const requiredGroups = Array.isArray(this.requiredGroup)
61
+ ? this.requiredGroup
62
+ : [this.requiredGroup];
63
+ // Verifica se o usuÔrio tem pelo menos um dos grupos obrigatórios
64
+ const hasRequiredGroup = requiredGroups.some((group) => userGroups.includes(group));
65
+ if (!hasRequiredGroup) {
66
+ throw new Error(`UsuƔrio deve ser membro de um dos seguintes sistemas: ${requiredGroups.join(", ")}`);
67
+ }
68
+ }
69
+ // Mapear o payload do Cognito para o formato do GatesUser
70
+ const user = {
71
+ user_id: payload.sub,
72
+ email: payload.email,
73
+ name: payload.name,
74
+ role: payload["custom:general_role"],
75
+ exp: payload.exp,
76
+ iat: payload.iat,
77
+ };
78
+ return user;
79
+ }
80
+ }
@@ -0,0 +1,97 @@
1
+ export class UserService {
2
+ baseUrl;
3
+ system;
4
+ defaultHeaders;
5
+ constructor(baseUrl, system) {
6
+ this.baseUrl = baseUrl.replace(/\/$/, "");
7
+ this.system = system;
8
+ this.defaultHeaders = {
9
+ "Content-Type": "application/json",
10
+ };
11
+ }
12
+ endpoints = {
13
+ all: "/get-all-profiles-from-system",
14
+ };
15
+ /**
16
+ * Busca todos os usuƔrios do Cognito atravƩs do backend
17
+ * @param idToken Token de autenticação (ID Token do Cognito)
18
+ * @param options Opções de paginação e filtro
19
+ * @returns Lista de usuƔrios
20
+ */
21
+ async getAllUsers(idToken
22
+ // options: GetAllUsersOptions = {}
23
+ ) {
24
+ if (!idToken) {
25
+ throw new Error("ID Token is required");
26
+ }
27
+ try {
28
+ const queryParams = new URLSearchParams();
29
+ // if (options.page) queryParams.append("page", options.page.toString());
30
+ // if (options.limit) queryParams.append("limit", options.limit.toString());
31
+ // if (options.filter) queryParams.append("filter", options.filter);
32
+ // if (options.group) queryParams.append("group", options.group);
33
+ const url = `${this.baseUrl}/${this.endpoints.all}${queryParams.toString() ? `?${queryParams.toString()}` : ""}`;
34
+ const response = await fetch(url, {
35
+ method: "POST",
36
+ headers: {
37
+ ...this.defaultHeaders,
38
+ Authorization: `Bearer ${idToken}`,
39
+ },
40
+ body: JSON.stringify({
41
+ system_name: this.system,
42
+ }),
43
+ });
44
+ if (!response.ok) {
45
+ const errorText = await response.text();
46
+ throw new Error(`HTTP ${response.status}: ${errorText}`);
47
+ }
48
+ const data = (await response.json());
49
+ // Adicionar total baseado no length se não vier da API
50
+ if (!data.total && data.profiles) {
51
+ data.total = data.profiles.length;
52
+ }
53
+ return data;
54
+ }
55
+ catch (error) {
56
+ if (error instanceof Error) {
57
+ throw new Error(`Failed to fetch users: ${error.message}`);
58
+ }
59
+ throw new Error("Failed to fetch users: Unknown error");
60
+ }
61
+ }
62
+ /**
63
+ * Busca um usuƔrio especƭfico por ID
64
+ * @param idToken Token de autenticação
65
+ * @param userId ID do usuƔrio
66
+ * @returns Dados do usuƔrio
67
+ */
68
+ async getUserById(idToken, userId) {
69
+ if (!idToken) {
70
+ throw new Error("ID Token is required");
71
+ }
72
+ if (!userId) {
73
+ throw new Error("User ID is required");
74
+ }
75
+ try {
76
+ const response = await fetch(`${this.baseUrl}/users/${userId}`, {
77
+ method: "GET",
78
+ headers: {
79
+ ...this.defaultHeaders,
80
+ Authorization: `Bearer ${idToken}`,
81
+ },
82
+ });
83
+ if (!response.ok) {
84
+ const errorText = await response.text();
85
+ throw new Error(`HTTP ${response.status}: ${errorText}`);
86
+ }
87
+ const user = (await response.json());
88
+ return user;
89
+ }
90
+ catch (error) {
91
+ if (error instanceof Error) {
92
+ throw new Error(`Failed to fetch user: ${error.message}`);
93
+ }
94
+ throw new Error("Failed to fetch user: Unknown error");
95
+ }
96
+ }
97
+ }
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@intelicity/gates-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Simple SDK for authenticating users with AWS Cognito JWT tokens",
5
+ "type": "module",
6
+ "exports": "./dist/index.js",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "engines": {
16
+ "node": ">=22.0.0"
17
+ },
18
+ "scripts": {
19
+ "build": "tsc && tsc-alias",
20
+ "typecheck": "tsc --noEmit",
21
+ "test:token": "tsx scripts/test-token.ts",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "keywords": [
25
+ "aws",
26
+ "cognito",
27
+ "jwt",
28
+ "authentication"
29
+ ],
30
+ "author": "Gabriel Godoy",
31
+ "license": "MIT",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/inteli-city/gates-sdk.git"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^24.1.0",
38
+ "tsc-alias": "^1.8.16",
39
+ "tsx": "^4.20.3",
40
+ "typescript": "^5.9.2"
41
+ },
42
+ "dependencies": {
43
+ "jose": "^6.1.1"
44
+ }
45
+ }