@zetra/citrineos-util 1.8.3-fork.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.
Files changed (142) hide show
  1. package/dist/authorization/ApiAuthPlugin.d.ts +52 -0
  2. package/dist/authorization/ApiAuthPlugin.js +122 -0
  3. package/dist/authorization/ApiAuthPlugin.js.map +1 -0
  4. package/dist/authorization/OidcTokenProvider.d.ts +15 -0
  5. package/dist/authorization/OidcTokenProvider.js +47 -0
  6. package/dist/authorization/OidcTokenProvider.js.map +1 -0
  7. package/dist/authorization/index.d.ts +4 -0
  8. package/dist/authorization/index.js +8 -0
  9. package/dist/authorization/index.js.map +1 -0
  10. package/dist/authorization/provider/LocalByPassAuthProvider.d.ts +34 -0
  11. package/dist/authorization/provider/LocalByPassAuthProvider.js +62 -0
  12. package/dist/authorization/provider/LocalByPassAuthProvider.js.map +1 -0
  13. package/dist/authorization/provider/OIDCAuthProvider.d.ts +62 -0
  14. package/dist/authorization/provider/OIDCAuthProvider.js +173 -0
  15. package/dist/authorization/provider/OIDCAuthProvider.js.map +1 -0
  16. package/dist/authorization/rbac/RbacRulesLoader.d.ts +32 -0
  17. package/dist/authorization/rbac/RbacRulesLoader.js +105 -0
  18. package/dist/authorization/rbac/RbacRulesLoader.js.map +1 -0
  19. package/dist/authorization/rbac/UrlMatcher.d.ts +14 -0
  20. package/dist/authorization/rbac/UrlMatcher.js +44 -0
  21. package/dist/authorization/rbac/UrlMatcher.js.map +1 -0
  22. package/dist/authorizer/RealTimeAuthorizer.d.ts +28 -0
  23. package/dist/authorizer/RealTimeAuthorizer.js +152 -0
  24. package/dist/authorizer/RealTimeAuthorizer.js.map +1 -0
  25. package/dist/authorizer/index.d.ts +1 -0
  26. package/dist/authorizer/index.js +5 -0
  27. package/dist/authorizer/index.js.map +1 -0
  28. package/dist/cache/memory.d.ts +19 -0
  29. package/dist/cache/memory.js +147 -0
  30. package/dist/cache/memory.js.map +1 -0
  31. package/dist/cache/redis.d.ts +16 -0
  32. package/dist/cache/redis.js +120 -0
  33. package/dist/cache/redis.js.map +1 -0
  34. package/dist/certificate/CertificateAuthority.d.ts +38 -0
  35. package/dist/certificate/CertificateAuthority.js +233 -0
  36. package/dist/certificate/CertificateAuthority.js.map +1 -0
  37. package/dist/certificate/CertificateUtil.d.ts +60 -0
  38. package/dist/certificate/CertificateUtil.js +317 -0
  39. package/dist/certificate/CertificateUtil.js.map +1 -0
  40. package/dist/certificate/client/acme.d.ts +37 -0
  41. package/dist/certificate/client/acme.js +138 -0
  42. package/dist/certificate/client/acme.js.map +1 -0
  43. package/dist/certificate/client/hubject.d.ts +41 -0
  44. package/dist/certificate/client/hubject.js +221 -0
  45. package/dist/certificate/client/hubject.js.map +1 -0
  46. package/dist/certificate/client/interface.d.ts +12 -0
  47. package/dist/certificate/client/interface.js +5 -0
  48. package/dist/certificate/client/interface.js.map +1 -0
  49. package/dist/certificate/index.d.ts +2 -0
  50. package/dist/certificate/index.js +6 -0
  51. package/dist/certificate/index.js.map +1 -0
  52. package/dist/files/ftpServer.d.ts +4 -0
  53. package/dist/files/ftpServer.js +9 -0
  54. package/dist/files/ftpServer.js.map +1 -0
  55. package/dist/files/gcpCloudStorage.d.ts +39 -0
  56. package/dist/files/gcpCloudStorage.js +130 -0
  57. package/dist/files/gcpCloudStorage.js.map +1 -0
  58. package/dist/files/localStorage.d.ts +14 -0
  59. package/dist/files/localStorage.js +57 -0
  60. package/dist/files/localStorage.js.map +1 -0
  61. package/dist/files/s3Storage.d.ts +17 -0
  62. package/dist/files/s3Storage.js +118 -0
  63. package/dist/files/s3Storage.js.map +1 -0
  64. package/dist/index.d.ts +21 -0
  65. package/dist/index.js +25 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/networkconnection/WebsocketNetworkConnection.d.ts +135 -0
  68. package/dist/networkconnection/WebsocketNetworkConnection.js +474 -0
  69. package/dist/networkconnection/WebsocketNetworkConnection.js.map +1 -0
  70. package/dist/networkconnection/authenticator/Authenticator.d.ts +20 -0
  71. package/dist/networkconnection/authenticator/Authenticator.js +39 -0
  72. package/dist/networkconnection/authenticator/Authenticator.js.map +1 -0
  73. package/dist/networkconnection/authenticator/AuthenticatorFilter.d.ts +11 -0
  74. package/dist/networkconnection/authenticator/AuthenticatorFilter.js +30 -0
  75. package/dist/networkconnection/authenticator/AuthenticatorFilter.js.map +1 -0
  76. package/dist/networkconnection/authenticator/BasicAuthenticationFilter.d.ts +17 -0
  77. package/dist/networkconnection/authenticator/BasicAuthenticationFilter.js +51 -0
  78. package/dist/networkconnection/authenticator/BasicAuthenticationFilter.js.map +1 -0
  79. package/dist/networkconnection/authenticator/ConnectedStationFilter.d.ts +14 -0
  80. package/dist/networkconnection/authenticator/ConnectedStationFilter.js +25 -0
  81. package/dist/networkconnection/authenticator/ConnectedStationFilter.js.map +1 -0
  82. package/dist/networkconnection/authenticator/NetworkProfileFilter.d.ts +16 -0
  83. package/dist/networkconnection/authenticator/NetworkProfileFilter.js +84 -0
  84. package/dist/networkconnection/authenticator/NetworkProfileFilter.js.map +1 -0
  85. package/dist/networkconnection/authenticator/UnknownStationFilter.d.ts +16 -0
  86. package/dist/networkconnection/authenticator/UnknownStationFilter.js +25 -0
  87. package/dist/networkconnection/authenticator/UnknownStationFilter.js.map +1 -0
  88. package/dist/networkconnection/authenticator/errors/AuthenticationError.d.ts +6 -0
  89. package/dist/networkconnection/authenticator/errors/AuthenticationError.js +25 -0
  90. package/dist/networkconnection/authenticator/errors/AuthenticationError.js.map +1 -0
  91. package/dist/networkconnection/authenticator/errors/IUpgradeError.d.ts +9 -0
  92. package/dist/networkconnection/authenticator/errors/IUpgradeError.js +5 -0
  93. package/dist/networkconnection/authenticator/errors/IUpgradeError.js.map +1 -0
  94. package/dist/networkconnection/authenticator/errors/UnknownError.d.ts +6 -0
  95. package/dist/networkconnection/authenticator/errors/UnknownError.js +24 -0
  96. package/dist/networkconnection/authenticator/errors/UnknownError.js.map +1 -0
  97. package/dist/networkconnection/index.d.ts +5 -0
  98. package/dist/networkconnection/index.js +9 -0
  99. package/dist/networkconnection/index.js.map +1 -0
  100. package/dist/queue/index.d.ts +4 -0
  101. package/dist/queue/index.js +8 -0
  102. package/dist/queue/index.js.map +1 -0
  103. package/dist/queue/kafka/receiver.d.ts +35 -0
  104. package/dist/queue/kafka/receiver.js +179 -0
  105. package/dist/queue/kafka/receiver.js.map +1 -0
  106. package/dist/queue/kafka/sender.d.ts +53 -0
  107. package/dist/queue/kafka/sender.js +189 -0
  108. package/dist/queue/kafka/sender.js.map +1 -0
  109. package/dist/queue/rabbit-mq/receiver.d.ts +89 -0
  110. package/dist/queue/rabbit-mq/receiver.js +472 -0
  111. package/dist/queue/rabbit-mq/receiver.js.map +1 -0
  112. package/dist/queue/rabbit-mq/sender.d.ts +90 -0
  113. package/dist/queue/rabbit-mq/sender.js +251 -0
  114. package/dist/queue/rabbit-mq/sender.js.map +1 -0
  115. package/dist/security/SignedMeterValuesUtil.d.ts +44 -0
  116. package/dist/security/SignedMeterValuesUtil.js +135 -0
  117. package/dist/security/SignedMeterValuesUtil.js.map +1 -0
  118. package/dist/security/authentication.d.ts +2 -0
  119. package/dist/security/authentication.js +26 -0
  120. package/dist/security/authentication.js.map +1 -0
  121. package/dist/util/RequestOperations.d.ts +14 -0
  122. package/dist/util/RequestOperations.js +25 -0
  123. package/dist/util/RequestOperations.js.map +1 -0
  124. package/dist/util/StringOperations.d.ts +1 -0
  125. package/dist/util/StringOperations.js +8 -0
  126. package/dist/util/StringOperations.js.map +1 -0
  127. package/dist/util/emaidCheckDigitCalculator.d.ts +15 -0
  128. package/dist/util/emaidCheckDigitCalculator.js +179 -0
  129. package/dist/util/emaidCheckDigitCalculator.js.map +1 -0
  130. package/dist/util/idGenerator.d.ts +7 -0
  131. package/dist/util/idGenerator.js +10 -0
  132. package/dist/util/idGenerator.js.map +1 -0
  133. package/dist/util/parser.d.ts +31 -0
  134. package/dist/util/parser.js +60 -0
  135. package/dist/util/parser.js.map +1 -0
  136. package/dist/util/swagger.d.ts +5 -0
  137. package/dist/util/swagger.js +154 -0
  138. package/dist/util/swagger.js.map +1 -0
  139. package/dist/util/validator.d.ts +110 -0
  140. package/dist/util/validator.js +534 -0
  141. package/dist/util/validator.js.map +1 -0
  142. package/package.json +46 -0
@@ -0,0 +1,52 @@
1
+ import type { FastifyPluginAsync, FastifyReply } from 'fastify';
2
+ import type { ILogObj } from 'tslog';
3
+ import { Logger } from 'tslog';
4
+ import type { IApiAuthProvider, UserInfo } from '@citrineos/base';
5
+ /**
6
+ * Options for the authentication plugin
7
+ */
8
+ export interface AuthPluginOptions {
9
+ /**
10
+ * Routes that don't require authentication
11
+ */
12
+ excludedRoutes?: string[];
13
+ /**
14
+ * Enable verbose debug logging
15
+ */
16
+ debug?: boolean;
17
+ }
18
+ /**
19
+ * Extend the FastifyRequest interface to include user information
20
+ */
21
+ declare module 'fastify' {
22
+ interface FastifyRequest {
23
+ /**
24
+ * Authenticated user information
25
+ */
26
+ user?: UserInfo;
27
+ }
28
+ }
29
+ /**
30
+ * Extend FastifyInstance to include our auth functions and provider
31
+ */
32
+ declare module 'fastify' {
33
+ interface FastifyInstance {
34
+ /**
35
+ * The authentication provider instance
36
+ */
37
+ authProvider: IApiAuthProvider;
38
+ /**
39
+ * Authenticates a request by validating the token in Authorization header
40
+ */
41
+ authenticate: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
42
+ /**
43
+ * Authorizes a request for a specific resource
44
+ */
45
+ authorize: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
46
+ }
47
+ }
48
+ export declare const apiAuthPluginFp: FastifyPluginAsync<{
49
+ provider: IApiAuthProvider;
50
+ options?: AuthPluginOptions;
51
+ logger?: Logger<ILogObj>;
52
+ }>;
@@ -0,0 +1,122 @@
1
+ // SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { Logger } from 'tslog';
5
+ import fp from 'fastify-plugin';
6
+ import { HttpStatus } from '@citrineos/base';
7
+ /**
8
+ * Authentication plugin for Fastify
9
+ * This plugin adds authentication and authorization capabilities to Fastify
10
+ * using the provided auth provider
11
+ *
12
+ * @param fastify Fastify instance
13
+ * @param provider Auth provider instance
14
+ * @param options Plugin options
15
+ */
16
+ const apiAuthPlugin = async (fastify, { provider, options = {}, logger }) => {
17
+ //TODO add logger instance ?
18
+ const _logger = logger
19
+ ? logger.getSubLogger({ name: 'AuthPlugin' })
20
+ : new Logger({ name: 'AuthPlugin' });
21
+ // Register the auth provider
22
+ fastify.decorate('authProvider', provider);
23
+ // Helper to check if a route is excluded from authentication
24
+ function isExcludedRoute(url) {
25
+ // Always exclude health check
26
+ if (url === '/health') {
27
+ return true;
28
+ }
29
+ const isExcluded = !!options.excludedRoutes?.some((route) => url === route || url.startsWith(`${route}/`));
30
+ if (isExcluded && options.debug) {
31
+ _logger.debug(`Skipping authentication for excluded route: ${url}`);
32
+ }
33
+ return isExcluded;
34
+ }
35
+ // Authentication decorator - validates token from Authorization header
36
+ fastify.decorate('authenticate', async function (request, reply) {
37
+ try {
38
+ // Extract token
39
+ const token = await provider.extractToken(request);
40
+ if (!token) {
41
+ reply.code(HttpStatus.UNAUTHORIZED).send({
42
+ error: 'Unauthorized',
43
+ message: 'Missing or invalid authorization header',
44
+ });
45
+ return;
46
+ }
47
+ // Authenticate token
48
+ const authResult = await provider.authenticateToken(token);
49
+ if (!authResult.isAuthenticated || !authResult.user) {
50
+ reply.code(HttpStatus.UNAUTHORIZED).send({
51
+ error: 'Unauthorized',
52
+ message: authResult.error || 'Invalid token',
53
+ });
54
+ return;
55
+ }
56
+ // Store user info in request
57
+ request.user = authResult.user;
58
+ if (options.debug) {
59
+ _logger.debug(`Authenticated user: ${authResult.user.id} (${authResult.user.name})`);
60
+ _logger.debug(`Roles: ${authResult.user.roles.join(', ')}`);
61
+ }
62
+ }
63
+ catch (error) {
64
+ _logger.error('Authentication error:', error);
65
+ reply.code(HttpStatus.UNAUTHORIZED).send({
66
+ error: 'Unauthorized',
67
+ message: 'Authentication failed',
68
+ });
69
+ }
70
+ });
71
+ // Authorization decorator - authorizes user for the requested resource
72
+ fastify.decorate('authorize', async function (request, reply) {
73
+ try {
74
+ // Check if user is authenticated
75
+ if (!request.user) {
76
+ reply.code(HttpStatus.UNAUTHORIZED).send({
77
+ error: 'Unauthorized',
78
+ message: 'Authentication required',
79
+ });
80
+ return;
81
+ }
82
+ // Authorize user for this request
83
+ const authzResult = await provider.authorizeUser(request.user, request);
84
+ if (!authzResult.isAuthorized) {
85
+ reply.code(HttpStatus.FORBIDDEN).send({
86
+ error: 'Forbidden',
87
+ message: authzResult.error || 'Insufficient permissions',
88
+ });
89
+ return;
90
+ }
91
+ if (options.debug) {
92
+ _logger.debug(`Authorized user ${request.user.id} for ${request.method} ${request.url}`);
93
+ }
94
+ }
95
+ catch (error) {
96
+ _logger.error('Authorization error:', error);
97
+ reply.code(HttpStatus.FORBIDDEN).send({
98
+ error: 'Forbidden',
99
+ message: 'Authorization failed',
100
+ });
101
+ }
102
+ });
103
+ // Add global authentication hook for all routes
104
+ fastify.addHook('onRequest', async (request, reply) => {
105
+ // Skip authentication for excluded routes
106
+ if (isExcludedRoute(request.url)) {
107
+ if (options.debug) {
108
+ _logger.trace(`Skipping authentication for excluded route: ${request.url}`);
109
+ }
110
+ return;
111
+ }
112
+ // Authenticate and authorize the request
113
+ await fastify.authenticate(request, reply);
114
+ await fastify.authorize(request, reply);
115
+ });
116
+ _logger.info('Authentication plugin registered');
117
+ };
118
+ export const apiAuthPluginFp = fp(apiAuthPlugin, {
119
+ name: 'apiAuth',
120
+ fastify: '5.x',
121
+ });
122
+ //# sourceMappingURL=ApiAuthPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiAuthPlugin.js","sourceRoot":"","sources":["../../src/authorization/ApiAuthPlugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { ILogObj } from 'tslog';
2
+ import { Logger } from 'tslog';
3
+ export interface OidcTokenProviderConfig {
4
+ tokenUrl: string;
5
+ clientId: string;
6
+ clientSecret: string;
7
+ audience: string;
8
+ }
9
+ export declare class OidcTokenProvider {
10
+ private config;
11
+ private oidcToken?;
12
+ private readonly _logger;
13
+ constructor(config: OidcTokenProviderConfig, logger?: Logger<ILogObj>);
14
+ getToken(): Promise<string>;
15
+ }
@@ -0,0 +1,47 @@
1
+ // SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { Logger } from 'tslog';
5
+ export class OidcTokenProvider {
6
+ config;
7
+ oidcToken;
8
+ _logger;
9
+ constructor(config, logger) {
10
+ this.config = config;
11
+ this._logger = logger
12
+ ? logger.getSubLogger({ name: this.constructor.name })
13
+ : new Logger({ name: this.constructor.name });
14
+ }
15
+ async getToken() {
16
+ if (this.oidcToken && this.oidcToken.expiresAt > Date.now()) {
17
+ this._logger.debug('Returning cached OIDC token');
18
+ return this.oidcToken.accessToken;
19
+ }
20
+ this._logger.debug('Fetching new OIDC token');
21
+ const response = await fetch(this.config.tokenUrl, {
22
+ method: 'POST',
23
+ headers: {
24
+ 'Content-Type': 'application/x-www-form-urlencoded',
25
+ },
26
+ body: new URLSearchParams({
27
+ grant_type: 'client_credentials',
28
+ client_id: this.config.clientId,
29
+ client_secret: this.config.clientSecret,
30
+ audience: this.config.audience,
31
+ }),
32
+ });
33
+ if (!response.ok) {
34
+ const errorText = await response.text();
35
+ this._logger.error('Failed to fetch OIDC token:', errorText);
36
+ throw new Error(`Failed to fetch OIDC token: ${response.statusText}`);
37
+ }
38
+ const tokenData = await response.json();
39
+ this.oidcToken = {
40
+ accessToken: tokenData.access_token,
41
+ // Set expiry to 1 minute before actual expiration to be safe
42
+ expiresAt: Date.now() + (tokenData.expires_in - 60) * 1000,
43
+ };
44
+ return this.oidcToken.accessToken;
45
+ }
46
+ }
47
+ //# sourceMappingURL=OidcTokenProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OidcTokenProvider.js","sourceRoot":"","sources":["../../src/authorization/OidcTokenProvider.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,sCAAsC;AAGtC,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAc/B,MAAM,OAAO,iBAAiB;IAKlB;IAJF,SAAS,CAAa;IACb,OAAO,CAAkB;IAE1C,YACU,MAA+B,EACvC,MAAwB;QADhB,WAAM,GAAN,MAAM,CAAyB;QAGvC,IAAI,CAAC,OAAO,GAAG,MAAM;YACnB,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YACtD,CAAC,CAAC,IAAI,MAAM,CAAU,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IAEM,KAAK,CAAC,QAAQ;QACnB,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC5D,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YAClD,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;QACpC,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;YACjD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,mCAAmC;aACpD;YACD,IAAI,EAAE,IAAI,eAAe,CAAC;gBACxB,UAAU,EAAE,oBAAoB;gBAChC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;gBAC/B,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY;gBACvC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;aAC/B,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,SAAS,CAAC,CAAC;YAC7D,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACxC,IAAI,CAAC,SAAS,GAAG;YACf,WAAW,EAAE,SAAS,CAAC,YAAY;YACnC,6DAA6D;YAC7D,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,UAAU,GAAG,EAAE,CAAC,GAAG,IAAI;SAC3D,CAAC;QAEF,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;IACpC,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ export * from './ApiAuthPlugin.js';
2
+ export { LocalBypassAuthProvider } from './provider/LocalByPassAuthProvider.js';
3
+ export { OIDCAuthProvider } from './provider/OIDCAuthProvider.js';
4
+ export { OidcTokenProvider } from './OidcTokenProvider.js';
@@ -0,0 +1,8 @@
1
+ // SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ export * from './ApiAuthPlugin.js';
5
+ export { LocalBypassAuthProvider } from './provider/LocalByPassAuthProvider.js';
6
+ export { OIDCAuthProvider } from './provider/OIDCAuthProvider.js';
7
+ export { OidcTokenProvider } from './OidcTokenProvider.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/authorization/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,sCAAsC;AACtC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { FastifyRequest } from 'fastify';
2
+ import type { ILogObj } from 'tslog';
3
+ import { Logger } from 'tslog';
4
+ import type { IApiAuthProvider, UserInfo } from '@citrineos/base';
5
+ import { ApiAuthenticationResult, ApiAuthorizationResult } from '@citrineos/base';
6
+ /**
7
+ * A local bypass authentication provider that doesn't perform actual authentication
8
+ * Only for development and testing environments
9
+ */
10
+ export declare class LocalBypassAuthProvider implements IApiAuthProvider {
11
+ private readonly _logger;
12
+ /**
13
+ * Creates a new local bypass authentication provider
14
+ *
15
+ * @param logger Optional logger instance
16
+ */
17
+ constructor(logger?: Logger<ILogObj>);
18
+ extractToken(_request: FastifyRequest): Promise<string>;
19
+ /**
20
+ * Always returns a successful authentication with admin user
21
+ *
22
+ * @param token Ignored, can be any string
23
+ * @returns Authentication result with admin user info
24
+ */
25
+ authenticateToken(_token: string): Promise<ApiAuthenticationResult>;
26
+ /**
27
+ * Always returns a successful authorization
28
+ *
29
+ * @param user Ignored, can be any user
30
+ * @param request Ignored, can be any request
31
+ * @returns Always successful authorization
32
+ */
33
+ authorizeUser(user: UserInfo, request: FastifyRequest): Promise<ApiAuthorizationResult>;
34
+ }
@@ -0,0 +1,62 @@
1
+ // SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { Logger } from 'tslog';
5
+ import { ApiAuthenticationResult, ApiAuthorizationResult } from '@citrineos/base';
6
+ /**
7
+ * A local bypass authentication provider that doesn't perform actual authentication
8
+ * Only for development and testing environments
9
+ */
10
+ export class LocalBypassAuthProvider {
11
+ _logger;
12
+ /**
13
+ * Creates a new local bypass authentication provider
14
+ *
15
+ * @param logger Optional logger instance
16
+ */
17
+ constructor(logger) {
18
+ this._logger = logger
19
+ ? logger.getSubLogger({ name: this.constructor.name })
20
+ : new Logger({ name: this.constructor.name });
21
+ this._logger.warn('⚠️ WARNING: Using LocalBypassAuthProvider - This should only be used in development environments');
22
+ }
23
+ async extractToken(_request) {
24
+ // Always return a dummy token for local bypass
25
+ this._logger.debug('LocalBypassAuthProvider.authenticateToken: Returning dummy token');
26
+ return 'local-bypass-token';
27
+ }
28
+ /**
29
+ * Always returns a successful authentication with admin user
30
+ *
31
+ * @param token Ignored, can be any string
32
+ * @returns Authentication result with admin user info
33
+ */
34
+ async authenticateToken(_token) {
35
+ this._logger.debug('LocalBypassAuthProvider.authenticateToken: Bypassing authentication, using dummy user');
36
+ // Create a default admin user
37
+ const user = {
38
+ id: 'local-admin',
39
+ name: 'Local Admin',
40
+ email: 'admin@local',
41
+ roles: ['admin', 'user'],
42
+ groups: ['administrators'],
43
+ tenantId: '1',
44
+ metadata: {
45
+ isLocalBypass: true,
46
+ },
47
+ };
48
+ return ApiAuthenticationResult.success(user);
49
+ }
50
+ /**
51
+ * Always returns a successful authorization
52
+ *
53
+ * @param user Ignored, can be any user
54
+ * @param request Ignored, can be any request
55
+ * @returns Always successful authorization
56
+ */
57
+ async authorizeUser(user, request) {
58
+ this._logger.debug(`LocalBypassAuthProvider.authorizeUser: Bypassing authorization for ${request.method} ${request.url}`);
59
+ return ApiAuthorizationResult.success();
60
+ }
61
+ }
62
+ //# sourceMappingURL=LocalByPassAuthProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalByPassAuthProvider.js","sourceRoot":"","sources":["../../../src/authorization/provider/LocalByPassAuthProvider.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,sCAAsC;AAItC,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAElF;;;GAGG;AACH,MAAM,OAAO,uBAAuB;IACjB,OAAO,CAAkB;IAE1C;;;;OAIG;IACH,YAAY,MAAwB;QAClC,IAAI,CAAC,OAAO,GAAG,MAAM;YACnB,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YACtD,CAAC,CAAC,IAAI,MAAM,CAAU,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QAEzD,IAAI,CAAC,OAAO,CAAC,IAAI,CACf,kGAAkG,CACnG,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,QAAwB;QACzC,+CAA+C;QAC/C,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QACvF,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,iBAAiB,CAAC,MAAc;QACpC,IAAI,CAAC,OAAO,CAAC,KAAK,CAChB,uFAAuF,CACxF,CAAC;QAEF,8BAA8B;QAC9B,MAAM,IAAI,GAAa;YACrB,EAAE,EAAE,aAAa;YACjB,IAAI,EAAE,aAAa;YACnB,KAAK,EAAE,aAAa;YACpB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;YACxB,MAAM,EAAE,CAAC,gBAAgB,CAAC;YAC1B,QAAQ,EAAE,GAAG;YACb,QAAQ,EAAE;gBACR,aAAa,EAAE,IAAI;aACpB;SACF,CAAC;QAEF,OAAO,uBAAuB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,aAAa,CAAC,IAAc,EAAE,OAAuB;QACzD,IAAI,CAAC,OAAO,CAAC,KAAK,CAChB,sEAAsE,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,CACtG,CAAC;QAEF,OAAO,sBAAsB,CAAC,OAAO,EAAE,CAAC;IAC1C,CAAC;CACF"}
@@ -0,0 +1,62 @@
1
+ import type { FastifyRequest } from 'fastify';
2
+ import type { ILogObj } from 'tslog';
3
+ import { Logger } from 'tslog';
4
+ import type { IApiAuthProvider, UserInfo } from '@citrineos/base';
5
+ import { ApiAuthenticationResult, ApiAuthorizationResult } from '@citrineos/base';
6
+ export interface OIDCConfig {
7
+ jwksUri: string;
8
+ issuer: string;
9
+ audience?: string;
10
+ cacheTime?: number;
11
+ rateLimit?: boolean;
12
+ }
13
+ /**
14
+ * OIDC authentication provider implementation
15
+ */
16
+ export declare class OIDCAuthProvider implements IApiAuthProvider {
17
+ private readonly _config;
18
+ private readonly _logger;
19
+ private readonly _jkwsClient;
20
+ private readonly _rulesLoader;
21
+ private readonly _defaultTenantId;
22
+ /**
23
+ * Creates a new Keycloak authentication provider
24
+ *
25
+ * @param config OIDC configuration
26
+ * @param logger Optional logger instance
27
+ */
28
+ constructor(config: OIDCConfig, logger?: Logger<ILogObj>);
29
+ extractToken(request: FastifyRequest): Promise<string | null>;
30
+ /**
31
+ * Authenticates a JWT token from and OIDC provider
32
+ *
33
+ * @param token JWT token to authenticate
34
+ * @returns Authentication result with user info if successful
35
+ */
36
+ authenticateToken(token: string): Promise<ApiAuthenticationResult>;
37
+ /**
38
+ * Authorizes a user for a specific request
39
+ * This implementation checks if the user has the required permissions
40
+ * for the requested URL and method
41
+ *
42
+ * @param user User information
43
+ * @param request Fastify request
44
+ * @returns Authorization result
45
+ */
46
+ authorizeUser(user: UserInfo, request: FastifyRequest): Promise<ApiAuthorizationResult>;
47
+ /**
48
+ * Fetches the public key from OIDC provider
49
+ * @param {string} kid Key ID from the JWT header
50
+ * @returns {Promise<string>} Public key as a string
51
+ * @private
52
+ */
53
+ private fetchPublicKey;
54
+ /**
55
+ * Check if a user has any of the required roles for a specific tenant
56
+ *
57
+ * @param user User with roles
58
+ * @param requiredRoles Array of role names (without tenant prefix)
59
+ * @returns True if user has any of the required roles
60
+ */
61
+ private userHasRequiredRole;
62
+ }
@@ -0,0 +1,173 @@
1
+ // SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { Logger } from 'tslog';
5
+ import jwt from 'jsonwebtoken';
6
+ import jwksClient from 'jwks-rsa';
7
+ import JwksRsa from 'jwks-rsa';
8
+ import { ApiAuthenticationResult, ApiAuthorizationResult } from '@citrineos/base';
9
+ import { createPublicKey } from 'crypto';
10
+ import { RbacRulesLoader } from '../rbac/RbacRulesLoader.js';
11
+ /**
12
+ * OIDC authentication provider implementation
13
+ */
14
+ export class OIDCAuthProvider {
15
+ _config;
16
+ _logger;
17
+ _jkwsClient;
18
+ _rulesLoader;
19
+ _defaultTenantId = '1'; //TODO get default from config
20
+ /**
21
+ * Creates a new Keycloak authentication provider
22
+ *
23
+ * @param config OIDC configuration
24
+ * @param logger Optional logger instance
25
+ */
26
+ constructor(config, logger) {
27
+ this._config = {
28
+ cacheTime: 60 * 60 * 1000, // Default 1 hour cache
29
+ rateLimit: true,
30
+ ...config,
31
+ };
32
+ this._logger = logger
33
+ ? logger.getSubLogger({ name: this.constructor.name })
34
+ : new Logger({ name: this.constructor.name });
35
+ this._logger.info('OIDC auth provider config', this._config);
36
+ // Create the JWKS client
37
+ this._jkwsClient = jwksClient({
38
+ jwksUri: this._config.jwksUri,
39
+ cache: true,
40
+ cacheMaxAge: this._config.cacheTime,
41
+ rateLimit: this._config.rateLimit,
42
+ jwksRequestsPerMinute: 5, // Limit requests to JWKS endpoint
43
+ });
44
+ this._rulesLoader = new RbacRulesLoader('rbac-rules.json', this._logger);
45
+ this._logger.info(`OIDC auth provider setup with jwksUri: ${this._config.jwksUri}`);
46
+ }
47
+ async extractToken(request) {
48
+ // Extract the Authorization header
49
+ const authHeader = request.headers.authorization;
50
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
51
+ this._logger.warn('No Bearer token found in request headers');
52
+ return null;
53
+ }
54
+ // Return the token without the "Bearer " prefix
55
+ const token = authHeader.slice(7).trim();
56
+ this._logger.debug('Extracted token from request:', token);
57
+ return token;
58
+ }
59
+ /**
60
+ * Authenticates a JWT token from and OIDC provider
61
+ *
62
+ * @param token JWT token to authenticate
63
+ * @returns Authentication result with user info if successful
64
+ */
65
+ async authenticateToken(token) {
66
+ try {
67
+ const decoded = jwt.decode(token, { complete: true });
68
+ if (!decoded || typeof decoded !== 'object' || !decoded.header || !decoded.header.kid) {
69
+ throw new Error('Invalid token format');
70
+ }
71
+ const publicKey = await this.fetchPublicKey(decoded.header.kid);
72
+ // Verify the token with the public key
73
+ const payload = jwt.verify(token, createPublicKey(publicKey));
74
+ // Extract user info from the decoded token
75
+ const user = {
76
+ id: payload.sub,
77
+ name: payload.preferred_username || payload.name || payload.sub,
78
+ email: payload.email || '',
79
+ roles: payload.resource_access.citrineos?.roles,
80
+ tenantId: payload.tenant_id || this._defaultTenantId,
81
+ metadata: {
82
+ firstName: payload.given_name,
83
+ lastName: payload.family_name,
84
+ fullName: payload.name,
85
+ emailVerified: payload.email_verified,
86
+ locale: payload.locale || 'en-US',
87
+ },
88
+ };
89
+ return ApiAuthenticationResult.success(user);
90
+ }
91
+ catch (error) {
92
+ this._logger.error('Token authentication failed:', error);
93
+ return ApiAuthenticationResult.failure(error instanceof Error ? error.message : 'Invalid token');
94
+ }
95
+ }
96
+ /**
97
+ * Authorizes a user for a specific request
98
+ * This implementation checks if the user has the required permissions
99
+ * for the requested URL and method
100
+ *
101
+ * @param user User information
102
+ * @param request Fastify request
103
+ * @returns Authorization result
104
+ */
105
+ async authorizeUser(user, request) {
106
+ try {
107
+ // Get the requested resource and method
108
+ const url = request.url;
109
+ const method = request.method;
110
+ const tenantId = request.query.tenantId || this._defaultTenantId;
111
+ const requiredRoles = this._rulesLoader.getRequiredRoles(tenantId, url, method);
112
+ //If no role is found for the requested resource and tenant, decline access
113
+ if (!requiredRoles || requiredRoles.length === 0) {
114
+ return ApiAuthorizationResult.failure(`Tenant does not have access to this resource ${url}`);
115
+ }
116
+ if (this.userHasRequiredRole(user, requiredRoles)) {
117
+ return ApiAuthorizationResult.success();
118
+ }
119
+ return ApiAuthorizationResult.failure(`Missing required roles. Need one of: ${requiredRoles.join(', ')} for tenant ${tenantId}`);
120
+ }
121
+ catch (error) {
122
+ this._logger.error('Authorization error:', error);
123
+ return ApiAuthorizationResult.failure(`Authorization error: ${error instanceof Error ? error.message : String(error)}`);
124
+ }
125
+ }
126
+ /**
127
+ * Fetches the public key from OIDC provider
128
+ * @param {string} kid Key ID from the JWT header
129
+ * @returns {Promise<string>} Public key as a string
130
+ * @private
131
+ */
132
+ async fetchPublicKey(kid) {
133
+ try {
134
+ return new Promise((resolve, reject) => {
135
+ this._jkwsClient.getSigningKey(kid, (err, key) => {
136
+ if (err) {
137
+ this._logger.error(`Error fetching signing key for kid: ${kid}`, err);
138
+ return reject(err);
139
+ }
140
+ if (!key) {
141
+ const error = new Error(`No signing key found for kid: ${kid}`);
142
+ this._logger.error(error.message);
143
+ return reject(error);
144
+ }
145
+ try {
146
+ // Get the public key
147
+ const signingKey = key.getPublicKey();
148
+ resolve(signingKey);
149
+ }
150
+ catch (keyError) {
151
+ this._logger.error('Error extracting public key:', keyError);
152
+ reject(keyError);
153
+ }
154
+ });
155
+ });
156
+ }
157
+ catch (error) {
158
+ this._logger.error('Failed to fetch public key:', error);
159
+ throw error;
160
+ }
161
+ }
162
+ /**
163
+ * Check if a user has any of the required roles for a specific tenant
164
+ *
165
+ * @param user User with roles
166
+ * @param requiredRoles Array of role names (without tenant prefix)
167
+ * @returns True if user has any of the required roles
168
+ */
169
+ userHasRequiredRole(user, requiredRoles) {
170
+ return user.roles.some((userRole) => requiredRoles.includes(userRole));
171
+ }
172
+ }
173
+ //# sourceMappingURL=OIDCAuthProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OIDCAuthProvider.js","sourceRoot":"","sources":["../../../src/authorization/provider/OIDCAuthProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { ILogObj } from 'tslog';
2
+ import { Logger } from 'tslog';
3
+ /**
4
+ * Class to load and validate RBAC rules
5
+ */
6
+ export declare class RbacRulesLoader {
7
+ private _rules;
8
+ private readonly _logger;
9
+ /**
10
+ * Creates a new RBAC rules loader
11
+ *
12
+ * @param rulesFilePath Path to the JSON rules file
13
+ * @param logger Logger instance
14
+ */
15
+ constructor(rulesFilePath: string, logger: Logger<ILogObj>);
16
+ /**
17
+ * Load and validate rules from a JSON file
18
+ *
19
+ * @param filePath Path to the JSON rules file
20
+ */
21
+ private loadRules;
22
+ /**
23
+ * Get the required roles for a specific tenant, URL, and HTTP method
24
+ *
25
+ * @param tenantId Tenant identifier
26
+ * @param url URL path
27
+ * @param method HTTP method
28
+ * @returns Array of required roles or null if no matching rule
29
+ */
30
+ getRequiredRoles(tenantId: string, url: string, method: string): string[] | null;
31
+ private normalizeUrl;
32
+ }