@intelicity/gates-sdk 0.1.6 → 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.
@@ -1,40 +1,31 @@
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
- // }
1
+ import { MissingAuthorizationError, UnauthorizedGroupError, } from "../errors/error.js";
2
+ export function extractToken(authorizationHeader) {
3
+ if (!authorizationHeader) {
4
+ throw new MissingAuthorizationError();
5
+ }
6
+ const match = /^Bearer\s+(.+)$/i.exec(authorizationHeader);
7
+ if (!match) {
8
+ throw new MissingAuthorizationError("Authorization header must use Bearer scheme");
9
+ }
10
+ return match[1];
11
+ }
12
+ export async function authenticate(token, service) {
13
+ return service.verifyToken(token);
14
+ }
15
+ export function authorize(user, requiredGroups) {
16
+ const groups = Array.isArray(requiredGroups)
17
+ ? requiredGroups
18
+ : [requiredGroups];
19
+ const hasGroup = user.groups.some((g) => groups.includes(g));
20
+ if (!hasGroup) {
21
+ throw new UnauthorizedGroupError(`User must be a member of one of the following groups: ${groups.join(", ")}`, groups);
22
+ }
23
+ }
24
+ export async function handleAuth(authorizationHeader, config) {
25
+ const token = extractToken(authorizationHeader);
26
+ const user = await authenticate(token, config.service);
27
+ if (config.requiredGroups) {
28
+ authorize(user, config.requiredGroups);
29
+ }
30
+ return user;
31
+ }
@@ -1,69 +1,33 @@
1
- /**
2
- * Base error class for all Gates SDK errors
3
- */
4
1
  export declare class GatesError extends Error {
5
2
  readonly code?: string | undefined;
6
3
  constructor(message: string, code?: string | undefined);
7
4
  }
8
- /**
9
- * Base error class for authentication-related errors
10
- */
11
5
  export declare class AuthenticationError extends GatesError {
12
6
  constructor(message: string, code?: string);
13
7
  }
14
- /**
15
- * Error thrown when a token has expired
16
- */
17
8
  export declare class TokenExpiredError extends AuthenticationError {
18
9
  constructor(message?: string);
19
10
  }
20
- /**
21
- * Error thrown when a token is invalid
22
- */
23
11
  export declare class InvalidTokenError extends AuthenticationError {
24
12
  constructor(message?: string);
25
13
  }
26
- /**
27
- * Error thrown when authorization header is missing
28
- */
29
14
  export declare class MissingAuthorizationError extends AuthenticationError {
30
15
  constructor(message?: string);
31
16
  }
32
- /**
33
- * Error thrown when user is not a member of required group
34
- */
35
17
  export declare class UnauthorizedGroupError extends AuthenticationError {
36
18
  readonly requiredGroups: string[];
37
19
  constructor(message: string, requiredGroups: string[]);
38
20
  }
39
- /**
40
- * Base error class for API-related errors
41
- */
42
21
  export declare class ApiError extends GatesError {
43
22
  readonly statusCode?: number | undefined;
44
23
  constructor(message: string, statusCode?: number | undefined, code?: string);
45
24
  }
46
- /**
47
- * Error thrown when API request fails
48
- */
49
25
  export declare class ApiRequestError extends ApiError {
50
26
  constructor(message: string, statusCode?: number);
51
27
  }
52
- /**
53
- * Error thrown when API response is invalid
54
- */
55
- export declare class InvalidResponseError extends ApiError {
56
- constructor(message?: string);
57
- }
58
- /**
59
- * Error thrown when a required parameter is missing
60
- */
61
28
  export declare class MissingParameterError extends GatesError {
62
29
  constructor(parameterName: string);
63
30
  }
64
- /**
65
- * Error thrown when a parameter has an invalid value
66
- */
67
31
  export declare class InvalidParameterError extends GatesError {
68
32
  constructor(parameterName: string, reason?: string);
69
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/errors/error.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,qBAAa,UAAW,SAAQ,KAAK;aACU,IAAI,CAAC,EAAE,MAAM;gBAA9C,OAAO,EAAE,MAAM,EAAkB,IAAI,CAAC,EAAE,MAAM,YAAA;CAK3D;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,UAAU;gBACrC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;CAK3C;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,mBAAmB;gBAC5C,OAAO,SAAmB;CAKvC;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,mBAAmB;gBAC5C,OAAO,SAAmB;CAKvC;AAED;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,mBAAmB;gBACpD,OAAO,SAAwC;CAK5D;AAED;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,mBAAmB;aAChB,cAAc,EAAE,MAAM,EAAE;gBAAzD,OAAO,EAAE,MAAM,EAAkB,cAAc,EAAE,MAAM,EAAE;CAKtE;AAED;;GAEG;AACH,qBAAa,QAAS,SAAQ,UAAU;aAGpB,UAAU,CAAC,EAAE,MAAM;gBADnC,OAAO,EAAE,MAAM,EACC,UAAU,CAAC,EAAE,MAAM,YAAA,EACnC,IAAI,CAAC,EAAE,MAAM;CAMhB;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,QAAQ;gBAC/B,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAKjD;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,QAAQ;gBACpC,OAAO,SAAwC;CAK5D;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,UAAU;gBACvC,aAAa,EAAE,MAAM;CAQlC;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,UAAU;gBACvC,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAQnD"}
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/errors/error.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAW,SAAQ,KAAK;aACU,IAAI,CAAC,EAAE,MAAM;gBAA9C,OAAO,EAAE,MAAM,EAAkB,IAAI,CAAC,EAAE,MAAM,YAAA;CAK3D;AAED,qBAAa,mBAAoB,SAAQ,UAAU;gBACrC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;CAK3C;AAED,qBAAa,iBAAkB,SAAQ,mBAAmB;gBAC5C,OAAO,SAAsB;CAK1C;AAED,qBAAa,iBAAkB,SAAQ,mBAAmB;gBAC5C,OAAO,SAAkB;CAKtC;AAED,qBAAa,yBAA0B,SAAQ,mBAAmB;gBACpD,OAAO,SAAoC;CAKxD;AAED,qBAAa,sBAAuB,SAAQ,mBAAmB;aAChB,cAAc,EAAE,MAAM,EAAE;gBAAzD,OAAO,EAAE,MAAM,EAAkB,cAAc,EAAE,MAAM,EAAE;CAKtE;AAED,qBAAa,QAAS,SAAQ,UAAU;aAGpB,UAAU,CAAC,EAAE,MAAM;gBADnC,OAAO,EAAE,MAAM,EACC,UAAU,CAAC,EAAE,MAAM,YAAA,EACnC,IAAI,CAAC,EAAE,MAAM;CAMhB;AAED,qBAAa,eAAgB,SAAQ,QAAQ;gBAC/B,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAKjD;AAED,qBAAa,qBAAsB,SAAQ,UAAU;gBACvC,aAAa,EAAE,MAAM;CAKlC;AAED,qBAAa,qBAAsB,SAAQ,UAAU;gBACvC,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAQnD"}
@@ -1,7 +1,3 @@
1
- // src/errors/error.ts
2
- /**
3
- * Base error class for all Gates SDK errors
4
- */
5
1
  export class GatesError extends Error {
6
2
  code;
7
3
  constructor(message, code) {
@@ -11,9 +7,6 @@ export class GatesError extends Error {
11
7
  Object.setPrototypeOf(this, GatesError.prototype);
12
8
  }
13
9
  }
14
- /**
15
- * Base error class for authentication-related errors
16
- */
17
10
  export class AuthenticationError extends GatesError {
18
11
  constructor(message, code) {
19
12
  super(message, code);
@@ -21,39 +14,27 @@ export class AuthenticationError extends GatesError {
21
14
  Object.setPrototypeOf(this, AuthenticationError.prototype);
22
15
  }
23
16
  }
24
- /**
25
- * Error thrown when a token has expired
26
- */
27
17
  export class TokenExpiredError extends AuthenticationError {
28
- constructor(message = "Token expirado") {
18
+ constructor(message = "Token has expired") {
29
19
  super(message, "TOKEN_EXPIRED");
30
20
  this.name = "TokenExpiredError";
31
21
  Object.setPrototypeOf(this, TokenExpiredError.prototype);
32
22
  }
33
23
  }
34
- /**
35
- * Error thrown when a token is invalid
36
- */
37
24
  export class InvalidTokenError extends AuthenticationError {
38
- constructor(message = "Token inválido") {
25
+ constructor(message = "Invalid token") {
39
26
  super(message, "INVALID_TOKEN");
40
27
  this.name = "InvalidTokenError";
41
28
  Object.setPrototypeOf(this, InvalidTokenError.prototype);
42
29
  }
43
30
  }
44
- /**
45
- * Error thrown when authorization header is missing
46
- */
47
31
  export class MissingAuthorizationError extends AuthenticationError {
48
- constructor(message = "Header de autorização não fornecido") {
32
+ constructor(message = "Authorization header is missing") {
49
33
  super(message, "MISSING_AUTHORIZATION");
50
34
  this.name = "MissingAuthorizationError";
51
35
  Object.setPrototypeOf(this, MissingAuthorizationError.prototype);
52
36
  }
53
37
  }
54
- /**
55
- * Error thrown when user is not a member of required group
56
- */
57
38
  export class UnauthorizedGroupError extends AuthenticationError {
58
39
  requiredGroups;
59
40
  constructor(message, requiredGroups) {
@@ -63,9 +44,6 @@ export class UnauthorizedGroupError extends AuthenticationError {
63
44
  Object.setPrototypeOf(this, UnauthorizedGroupError.prototype);
64
45
  }
65
46
  }
66
- /**
67
- * Base error class for API-related errors
68
- */
69
47
  export class ApiError extends GatesError {
70
48
  statusCode;
71
49
  constructor(message, statusCode, code) {
@@ -75,9 +53,6 @@ export class ApiError extends GatesError {
75
53
  Object.setPrototypeOf(this, ApiError.prototype);
76
54
  }
77
55
  }
78
- /**
79
- * Error thrown when API request fails
80
- */
81
56
  export class ApiRequestError extends ApiError {
82
57
  constructor(message, statusCode) {
83
58
  super(message, statusCode, "API_REQUEST_ERROR");
@@ -85,34 +60,18 @@ export class ApiRequestError extends ApiError {
85
60
  Object.setPrototypeOf(this, ApiRequestError.prototype);
86
61
  }
87
62
  }
88
- /**
89
- * Error thrown when API response is invalid
90
- */
91
- export class InvalidResponseError extends ApiError {
92
- constructor(message = "Formato de resposta da API inválido") {
93
- super(message, undefined, "INVALID_RESPONSE");
94
- this.name = "InvalidResponseError";
95
- Object.setPrototypeOf(this, InvalidResponseError.prototype);
96
- }
97
- }
98
- /**
99
- * Error thrown when a required parameter is missing
100
- */
101
63
  export class MissingParameterError extends GatesError {
102
64
  constructor(parameterName) {
103
- super(`Parâmetro obrigatório ausente: ${parameterName}`, "MISSING_PARAMETER");
65
+ super(`Missing required parameter: ${parameterName}`, "MISSING_PARAMETER");
104
66
  this.name = "MissingParameterError";
105
67
  Object.setPrototypeOf(this, MissingParameterError.prototype);
106
68
  }
107
69
  }
108
- /**
109
- * Error thrown when a parameter has an invalid value
110
- */
111
70
  export class InvalidParameterError extends GatesError {
112
71
  constructor(parameterName, reason) {
113
72
  const message = reason
114
- ? `Parâmetro '${parameterName}' inválido: ${reason}`
115
- : `Parâmetro inválido: ${parameterName}`;
73
+ ? `Invalid parameter '${parameterName}': ${reason}`
74
+ : `Invalid parameter: ${parameterName}`;
116
75
  super(message, "INVALID_PARAMETER");
117
76
  this.name = "InvalidParameterError";
118
77
  Object.setPrototypeOf(this, InvalidParameterError.prototype);
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export type { GatesUser as GatesUser } from "./models/user.js";
2
- export type { UserProfile as Profile, ProfileAttribute, } from "./models/profile.js";
3
- export { GatesUserService as UserService, type UserListResponse, type GetAllUsersOptions, } from "./services/user-service.js";
4
- export { GatesAuthService as AuthService, type VerifyOptions, } from "./services/auth-service.js";
5
- export { GatesError, AuthenticationError, TokenExpiredError, InvalidTokenError, MissingAuthorizationError, UnauthorizedGroupError, ApiError, ApiRequestError, InvalidResponseError, MissingParameterError, InvalidParameterError, } from "./errors/error.js";
1
+ export type { GatesUser, GatesRole } from "./models/user.js";
2
+ export { AuthService, type VerifyOptions } from "./services/auth-service.js";
3
+ export { GatesAdminService, type GatesAdminConfig, type CreateUserParams, type CreateUserResponse, type UpdateUserParams, } from "./services/admin-service.js";
4
+ export { extractToken, authenticate, authorize, handleAuth, type AuthHandlerConfig, } from "./auth/middleware.js";
5
+ export { GatesError, AuthenticationError, TokenExpiredError, InvalidTokenError, MissingAuthorizationError, UnauthorizedGroupError, ApiError, ApiRequestError, MissingParameterError, InvalidParameterError, } from "./errors/error.js";
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,SAAS,IAAI,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC/D,YAAY,EACV,WAAW,IAAI,OAAO,EACtB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,gBAAgB,IAAI,WAAW,EAC/B,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,gBAAgB,IAAI,WAAW,EAC/B,KAAK,aAAa,GACnB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAEL,UAAU,EAGV,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,EACzB,sBAAsB,EAGtB,QAAQ,EACR,eAAe,EACf,oBAAoB,EAGpB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG7D,OAAO,EAAE,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE7E,OAAO,EACL,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,UAAU,EACV,KAAK,iBAAiB,GACvB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,EACzB,sBAAsB,EACtB,QAAQ,EACR,eAAe,EACf,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -1,14 +1,7 @@
1
- // Main exports for Gates SDK
2
1
  // Services
3
- export { GatesUserService as UserService, } from "./services/user-service.js";
4
- export { GatesAuthService as AuthService, } from "./services/auth-service.js";
2
+ export { AuthService } from "./services/auth-service.js";
3
+ export { GatesAdminService, } from "./services/admin-service.js";
4
+ // Middleware
5
+ export { extractToken, authenticate, authorize, handleAuth, } from "./auth/middleware.js";
5
6
  // Errors
6
- export {
7
- // Base errors
8
- GatesError,
9
- // Authentication errors
10
- AuthenticationError, TokenExpiredError, InvalidTokenError, MissingAuthorizationError, UnauthorizedGroupError,
11
- // API errors
12
- ApiError, ApiRequestError, InvalidResponseError,
13
- // Parameter errors
14
- MissingParameterError, InvalidParameterError, } from "./errors/error.js";
7
+ export { GatesError, AuthenticationError, TokenExpiredError, InvalidTokenError, MissingAuthorizationError, UnauthorizedGroupError, ApiError, ApiRequestError, MissingParameterError, InvalidParameterError, } from "./errors/error.js";
@@ -1,12 +1,11 @@
1
- /**
2
- * Tipagem base do payload que sai do Cognito.
3
- * Você pode estender com claims próprias (ex.: permissions, system_access).
4
- */
1
+ export type GatesRole = "INTERNAL_ADMIN" | "INTERNAL_USER" | "CLIENT_ADMIN" | "CLIENT_USER";
5
2
  export type GatesUser = {
6
3
  user_id: string;
7
- email: string;
8
- name: string;
9
- role: string;
4
+ email?: string;
5
+ name?: string;
6
+ role?: string;
7
+ groups: string[];
8
+ token_use: "access" | "id";
10
9
  exp: number;
11
10
  iat: number;
12
11
  };
@@ -1 +1 @@
1
- {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/models/user.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,CAAC"}
1
+ {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/models/user.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GACjB,gBAAgB,GAChB,eAAe,GACf,cAAc,GACd,aAAa,CAAC;AAElB,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { GatesRole } from "../models/user.js";
2
+ export type GatesAdminConfig = {
3
+ baseUrl: string;
4
+ };
5
+ export type CreateUserParams = {
6
+ email: string;
7
+ name: string;
8
+ role: GatesRole;
9
+ client: string;
10
+ };
11
+ export type CreateUserResponse = {
12
+ sub: string;
13
+ };
14
+ export type UpdateUserParams = {
15
+ user_id: string;
16
+ clients_to_add?: string[];
17
+ clients_to_remove?: string[];
18
+ };
19
+ export declare class GatesAdminService {
20
+ private readonly baseUrl;
21
+ constructor(config: GatesAdminConfig);
22
+ createUser(idToken: string, params: CreateUserParams): Promise<CreateUserResponse>;
23
+ updateUser(idToken: string, params: UpdateUserParams): Promise<void>;
24
+ private request;
25
+ }
26
+ //# sourceMappingURL=admin-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-service.d.ts","sourceRoot":"","sources":["../../src/services/admin-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAO9C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B,CAAC;AASF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,gBAAgB;IAO9B,UAAU,CACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,kBAAkB,CAAC;IAgDxB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;YAgB5D,OAAO;CAmCtB"}
@@ -0,0 +1,92 @@
1
+ import { MissingParameterError, InvalidParameterError, ApiRequestError, } from "../errors/error.js";
2
+ const VALID_ROLES = [
3
+ "INTERNAL_ADMIN",
4
+ "INTERNAL_USER",
5
+ "CLIENT_ADMIN",
6
+ "CLIENT_USER",
7
+ ];
8
+ export class GatesAdminService {
9
+ baseUrl;
10
+ constructor(config) {
11
+ if (!config.baseUrl || config.baseUrl.trim().length === 0) {
12
+ throw new MissingParameterError("baseUrl");
13
+ }
14
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
15
+ }
16
+ async createUser(idToken, params) {
17
+ if (!idToken) {
18
+ throw new MissingParameterError("idToken");
19
+ }
20
+ if (!params.email || params.email.trim().length === 0) {
21
+ throw new MissingParameterError("email");
22
+ }
23
+ if (!params.name || params.name.trim().length === 0) {
24
+ throw new MissingParameterError("name");
25
+ }
26
+ if (!params.role) {
27
+ throw new MissingParameterError("role");
28
+ }
29
+ if (!VALID_ROLES.includes(params.role)) {
30
+ throw new InvalidParameterError("role", `must be one of: ${VALID_ROLES.join(", ")}`);
31
+ }
32
+ if (!params.client || params.client.trim().length === 0) {
33
+ throw new MissingParameterError("client");
34
+ }
35
+ const response = await this.request("POST", "/create-user", idToken, {
36
+ email: params.email,
37
+ name: params.name,
38
+ role: params.role,
39
+ });
40
+ const data = (await response.json());
41
+ if (!data.sub) {
42
+ throw new ApiRequestError("Response missing 'sub' field");
43
+ }
44
+ await this.updateUser(idToken, {
45
+ user_id: data.sub,
46
+ clients_to_add: [params.client],
47
+ });
48
+ return data;
49
+ }
50
+ async updateUser(idToken, params) {
51
+ if (!idToken) {
52
+ throw new MissingParameterError("idToken");
53
+ }
54
+ if (!params.user_id || params.user_id.trim().length === 0) {
55
+ throw new MissingParameterError("user_id");
56
+ }
57
+ await this.request("PUT", "/update-user", idToken, {
58
+ user_id: params.user_id,
59
+ clients_to_add: params.clients_to_add,
60
+ clients_to_remove: params.clients_to_remove,
61
+ });
62
+ }
63
+ async request(method, path, idToken, body) {
64
+ let response;
65
+ try {
66
+ response = await fetch(`${this.baseUrl}${path}`, {
67
+ method,
68
+ headers: {
69
+ "Content-Type": "application/json",
70
+ Authorization: `Bearer ${idToken}`,
71
+ },
72
+ body: JSON.stringify(body),
73
+ });
74
+ }
75
+ catch (error) {
76
+ const message = error instanceof Error ? error.message : "Unknown network error";
77
+ throw new ApiRequestError(`Failed to reach Gates API: ${message}`);
78
+ }
79
+ if (!response.ok) {
80
+ let detail;
81
+ try {
82
+ const errorBody = (await response.json());
83
+ detail = errorBody.message ?? response.statusText;
84
+ }
85
+ catch {
86
+ detail = response.statusText;
87
+ }
88
+ throw new ApiRequestError(`Gates API error: ${detail}`, response.status);
89
+ }
90
+ return response;
91
+ }
92
+ }
@@ -2,17 +2,14 @@ import { GatesUser } from "../models/user.js";
2
2
  export type VerifyOptions = {
3
3
  region: string;
4
4
  userPoolId: string;
5
- audience: string;
6
- requiredGroup?: string | string[];
5
+ clientId: string;
7
6
  };
8
- export declare class GatesAuthService {
7
+ export declare class AuthService {
9
8
  private readonly region;
10
9
  private readonly userPoolId;
11
- private readonly audience;
12
- private readonly requiredGroup?;
13
- constructor(region: string, userPoolId: string, audience: string, requiredGroup?: string | string[]);
10
+ private readonly clientId;
11
+ constructor(region: string, userPoolId: string, clientId: string);
14
12
  private get issuer();
15
- isMemberOf(groups?: string[]): boolean;
16
13
  verifyToken(token: string): Promise<GatesUser>;
17
14
  }
18
15
  //# sourceMappingURL=auth-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-service.d.ts","sourceRoot":"","sources":["../../src/services/auth-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAS9C,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACnC,CAAC;AAEF,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAoB;gBAGjD,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAoCnC,OAAO,KAAK,MAAM,GAEjB;IAED,UAAU,CAAC,MAAM,GAAE,MAAM,EAAO,GAAG,OAAO;IAgBpC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;CA0FrD"}
1
+ {"version":3,"file":"auth-service.d.ts","sourceRoot":"","sources":["../../src/services/auth-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAQ9C,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAiChE,OAAO,KAAK,MAAM,GAEjB;IAEK,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;CAqFrD"}
@@ -1,12 +1,11 @@
1
1
  import { jwtVerify, errors as joseErrors } from "jose";
2
2
  import { getJwks } from "../cache/jwks-cache.js";
3
- import { InvalidParameterError, MissingParameterError, TokenExpiredError, InvalidTokenError, UnauthorizedGroupError, } from "../errors/error.js";
4
- export class GatesAuthService {
3
+ import { InvalidParameterError, MissingParameterError, TokenExpiredError, InvalidTokenError, } from "../errors/error.js";
4
+ export class AuthService {
5
5
  region;
6
6
  userPoolId;
7
- audience;
8
- requiredGroup;
9
- constructor(region, userPoolId, audience, requiredGroup) {
7
+ clientId;
8
+ constructor(region, userPoolId, clientId) {
10
9
  if (!region || typeof region !== "string" || region.trim().length === 0) {
11
10
  throw new MissingParameterError("region");
12
11
  }
@@ -15,35 +14,21 @@ export class GatesAuthService {
15
14
  userPoolId.trim().length === 0) {
16
15
  throw new MissingParameterError("userPoolId");
17
16
  }
18
- if (!audience ||
19
- typeof audience !== "string" ||
20
- audience.trim().length === 0) {
21
- throw new MissingParameterError("audience");
17
+ if (!clientId ||
18
+ typeof clientId !== "string" ||
19
+ clientId.trim().length === 0) {
20
+ throw new MissingParameterError("clientId");
22
21
  }
23
- // Validar formato do userPoolId (deve seguir padrão AWS)
24
22
  if (!/^[a-zA-Z0-9_-]+$/.test(userPoolId)) {
25
- throw new InvalidParameterError("userPoolId", "deve seguir o formato AWS (apenas alfanuméricos, hífens e underscores)");
23
+ throw new InvalidParameterError("userPoolId", "must follow AWS format (alphanumeric, hyphens, and underscores only)");
26
24
  }
27
25
  this.region = region;
28
26
  this.userPoolId = userPoolId;
29
- this.audience = audience;
30
- this.requiredGroup = requiredGroup;
27
+ this.clientId = clientId;
31
28
  }
32
29
  get issuer() {
33
30
  return `https://cognito-idp.${this.region}.amazonaws.com/${this.userPoolId}`;
34
31
  }
35
- isMemberOf(groups = []) {
36
- if (!Array.isArray(groups)) {
37
- return false;
38
- }
39
- if (!this.requiredGroup) {
40
- return true;
41
- }
42
- const requiredGroups = Array.isArray(this.requiredGroup)
43
- ? this.requiredGroup
44
- : [this.requiredGroup];
45
- return groups.some((g) => requiredGroups.includes(g));
46
- }
47
32
  async verifyToken(token) {
48
33
  if (!token) {
49
34
  throw new MissingParameterError("token");
@@ -52,47 +37,48 @@ export class GatesAuthService {
52
37
  const jwks = getJwks(this.region, this.userPoolId);
53
38
  const { payload } = await jwtVerify(token, jwks, {
54
39
  issuer: this.issuer,
55
- audience: this.audience,
56
40
  });
57
- if (this.requiredGroup) {
58
- const userGroups = payload["cognito:groups"];
59
- const requiredGroups = Array.isArray(this.requiredGroup)
60
- ? this.requiredGroup
61
- : [this.requiredGroup];
62
- if (!userGroups || !Array.isArray(userGroups)) {
63
- throw new UnauthorizedGroupError("Usuário não pertence a nenhum grupo obrigatório", requiredGroups);
41
+ const tokenUse = payload.token_use;
42
+ if (tokenUse !== "access" && tokenUse !== "id") {
43
+ throw new InvalidTokenError(`Unsupported token_use: expected "access" or "id", got "${tokenUse}"`);
44
+ }
45
+ if (tokenUse === "access") {
46
+ const clientId = payload.client_id;
47
+ if (clientId !== this.clientId) {
48
+ throw new InvalidTokenError("Token client_id does not match the expected clientId");
64
49
  }
65
- // Verifica se o usuário tem pelo menos um dos grupos obrigatórios
66
- const hasRequiredGroup = requiredGroups.some((group) => userGroups.includes(group));
67
- if (!hasRequiredGroup) {
68
- throw new UnauthorizedGroupError(`Usuário deve ser membro de um dos seguintes grupos: ${requiredGroups.join(", ")}`, requiredGroups);
50
+ }
51
+ else {
52
+ const aud = payload.aud;
53
+ const audValue = Array.isArray(aud) ? aud[0] : aud;
54
+ if (audValue !== this.clientId) {
55
+ throw new InvalidTokenError("Token audience does not match the expected clientId");
69
56
  }
70
57
  }
71
- // Mapear o payload do Cognito para o formato do GatesUser
58
+ const groups = payload["cognito:groups"] ?? [];
72
59
  const user = {
73
60
  user_id: payload.sub,
74
61
  email: payload.email,
75
62
  name: payload.name,
76
63
  role: payload["custom:general_role"],
64
+ groups,
65
+ token_use: tokenUse,
77
66
  exp: payload.exp,
78
67
  iat: payload.iat,
79
68
  };
80
69
  return user;
81
70
  }
82
71
  catch (error) {
83
- // Re-throw known errors
84
- if (error instanceof UnauthorizedGroupError ||
72
+ if (error instanceof InvalidTokenError ||
85
73
  error instanceof MissingParameterError) {
86
74
  throw error;
87
75
  }
88
- // Handle jose-specific errors
89
76
  if (error instanceof joseErrors.JWTExpired) {
90
- throw new TokenExpiredError("Token expirado");
77
+ throw new TokenExpiredError();
91
78
  }
92
79
  if (error instanceof joseErrors.JWTInvalid) {
93
- throw new InvalidTokenError("Token inválido ou malformado");
80
+ throw new InvalidTokenError("Invalid or malformed token");
94
81
  }
95
- // Handle other jose errors
96
82
  if (error instanceof Error) {
97
83
  if (error.message.includes("expired")) {
98
84
  throw new TokenExpiredError(error.message);
@@ -101,9 +87,9 @@ export class GatesAuthService {
101
87
  error.message.includes("invalid")) {
102
88
  throw new InvalidTokenError(error.message);
103
89
  }
104
- throw new InvalidTokenError(`Falha na verificação do token: ${error.message}`);
90
+ throw new InvalidTokenError(`Token verification failed: ${error.message}`);
105
91
  }
106
- throw new InvalidTokenError("Falha na verificação do token");
92
+ throw new InvalidTokenError("Token verification failed");
107
93
  }
108
94
  }
109
95
  }
@@ -0,0 +1,22 @@
1
+ export type ClientCredentialsConfig = {
2
+ domain: string;
3
+ clientId: string;
4
+ clientSecret: string;
5
+ scopes?: string[];
6
+ };
7
+ export type ClientToken = {
8
+ access_token: string;
9
+ expires_in: number;
10
+ token_type: string;
11
+ };
12
+ export declare class GatesClientAuth {
13
+ private readonly tokenEndpoint;
14
+ private readonly clientId;
15
+ private readonly clientSecret;
16
+ private readonly scopes;
17
+ private cachedToken;
18
+ constructor(config: ClientCredentialsConfig);
19
+ getAccessToken(): Promise<string>;
20
+ clearCache(): void;
21
+ }
22
+ //# sourceMappingURL=client-auth.d.ts.map