@adobe/aio-commerce-lib-auth 0.1.0 → 0.3.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,39 +1,65 @@
1
- import OAuth1a from "oauth-1.0a";
1
+ import * as valibot0 from "valibot";
2
+ import { InferOutput } from "valibot";
2
3
 
3
- //#region source/lib/ims-auth.d.ts
4
- declare const IMS_AUTH_HEADERS: readonly ["Authorization", "x-api-key"];
5
- declare const IMS_AUTH_PARAMS: readonly ["AIO_COMMERCE_IMS_CLIENT_ID", "AIO_COMMERCE_IMS_CLIENT_SECRETS", "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID", "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL", "AIO_COMMERCE_IMS_IMS_ORG_ID", "AIO_COMMERCE_IMS_SCOPES", "AIO_COMMERCE_IMS_ENV", "AIO_COMMERCE_IMS_CTX"];
6
- type ImsAuthParam = (typeof IMS_AUTH_PARAMS)[number];
7
- type ImsAuthParams = Partial<Record<ImsAuthParam, string>>;
8
- type ImsAuthHeader = (typeof IMS_AUTH_HEADERS)[number];
4
+ //#region source/lib/ims-auth/schema.d.ts
5
+ declare const IMS_AUTH_ENV: {
6
+ readonly PROD: "prod";
7
+ readonly STAGE: "stage";
8
+ };
9
+ declare const ImsAuthEnvSchema: valibot0.EnumSchema<{
10
+ readonly PROD: "prod";
11
+ readonly STAGE: "stage";
12
+ }, undefined>;
13
+ declare const ImsAuthParamsSchema: valibot0.ObjectSchema<{
14
+ readonly clientId: valibot0.SchemaWithPipe<readonly [valibot0.StringSchema<`Expected a string value for the IMS auth parameter ${string}`>, valibot0.NonEmptyAction<string, `Expected a non-empty string value for the IMS auth parameter ${string}`>]>;
15
+ readonly clientSecrets: valibot0.SchemaWithPipe<readonly [valibot0.SchemaWithPipe<readonly [valibot0.ArraySchema<valibot0.StringSchema<undefined>, `Expected a stringified JSON array value for the IMS auth parameter ${string}`>]>, valibot0.MinLengthAction<string[], 1, "Expected at least one client secret for IMS auth">]>;
16
+ readonly technicalAccountId: valibot0.SchemaWithPipe<readonly [valibot0.StringSchema<`Expected a string value for the IMS auth parameter ${string}`>, valibot0.NonEmptyAction<string, `Expected a non-empty string value for the IMS auth parameter ${string}`>]>;
17
+ readonly technicalAccountEmail: valibot0.SchemaWithPipe<readonly [valibot0.StringSchema<"Expected a string value for the IMS auth parameter technicalAccountEmail">, valibot0.EmailAction<string, "Expected a valid email format for technicalAccountEmail">]>;
18
+ readonly imsOrgId: valibot0.SchemaWithPipe<readonly [valibot0.StringSchema<`Expected a string value for the IMS auth parameter ${string}`>, valibot0.NonEmptyAction<string, `Expected a non-empty string value for the IMS auth parameter ${string}`>]>;
19
+ readonly environment: valibot0.SchemaWithPipe<readonly [valibot0.OptionalSchema<valibot0.EnumSchema<{
20
+ readonly PROD: "prod";
21
+ readonly STAGE: "stage";
22
+ }, undefined>, "prod">]>;
23
+ readonly context: valibot0.SchemaWithPipe<readonly [valibot0.OptionalSchema<valibot0.StringSchema<undefined>, "aio-commerce-sdk-creds">]>;
24
+ readonly scopes: valibot0.SchemaWithPipe<readonly [valibot0.SchemaWithPipe<readonly [valibot0.ArraySchema<valibot0.StringSchema<undefined>, `Expected a stringified JSON array value for the IMS auth parameter ${string}`>]>, valibot0.MinLengthAction<string[], 1, "Expected at least one scope for IMS auth">]>;
25
+ }, undefined>;
26
+ type ImsAuthParams = InferOutput<typeof ImsAuthParamsSchema>;
27
+ type ImsAuthEnv = InferOutput<typeof ImsAuthEnvSchema>;
28
+ //#endregion
29
+ //#region source/lib/ims-auth/provider.d.ts
30
+ type ImsAuthHeader = "Authorization" | "x-api-key";
9
31
  type ImsAuthHeaders = Record<ImsAuthHeader, string>;
10
- type ImsAccessToken = string;
11
32
  interface ImsAuthProvider {
33
+ getAccessToken: () => Promise<string>;
12
34
  getHeaders: () => Promise<ImsAuthHeaders>;
13
- getAccessToken: () => Promise<ImsAccessToken>;
14
35
  }
15
- declare function getImsAuthProvider(params: ImsAuthParams): Promise<{
36
+ declare function assertImsAuthParams(config: Record<PropertyKey, unknown>): asserts config is ImsAuthParams;
37
+ declare function getImsAuthProvider(authParams: ImsAuthParams): {
16
38
  getAccessToken: () => Promise<string>;
17
39
  getHeaders: () => Promise<{
18
40
  Authorization: string;
19
41
  "x-api-key": string;
20
42
  }>;
21
- } | undefined>;
43
+ };
44
+ //#endregion
45
+ //#region source/lib/integration-auth/schema.d.ts
46
+ type HttpMethodInput = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
47
+ declare const IntegrationAuthParamsSchema: valibot0.NonOptionalSchema<valibot0.ObjectSchema<{
48
+ readonly consumerKey: valibot0.SchemaWithPipe<readonly [valibot0.StringSchema<`Expected a string value for the Commerce Integration parameter ${string}`>, valibot0.NonEmptyAction<string, `Expected a non-empty string value for the Commerce Integration parameter ${string}`>]>;
49
+ readonly consumerSecret: valibot0.SchemaWithPipe<readonly [valibot0.StringSchema<`Expected a string value for the Commerce Integration parameter ${string}`>, valibot0.NonEmptyAction<string, `Expected a non-empty string value for the Commerce Integration parameter ${string}`>]>;
50
+ readonly accessToken: valibot0.SchemaWithPipe<readonly [valibot0.StringSchema<`Expected a string value for the Commerce Integration parameter ${string}`>, valibot0.NonEmptyAction<string, `Expected a non-empty string value for the Commerce Integration parameter ${string}`>]>;
51
+ readonly accessTokenSecret: valibot0.SchemaWithPipe<readonly [valibot0.StringSchema<`Expected a string value for the Commerce Integration parameter ${string}`>, valibot0.NonEmptyAction<string, `Expected a non-empty string value for the Commerce Integration parameter ${string}`>]>;
52
+ }, undefined>, undefined>;
53
+ type IntegrationAuthParams = InferOutput<typeof IntegrationAuthParamsSchema>;
22
54
  //#endregion
23
- //#region source/lib/integration-auth.d.ts
24
- declare const HTTP_METHODS: readonly ["GET", "POST", "PUT", "PATCH", "DELETE"];
25
- declare const INTEGRATION_AUTH_HEADERS: readonly ["Authorization"];
26
- declare const INTEGRATION_AUTH_PARAMS: readonly ["AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY", "AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET", "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN", "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET"];
27
- type IntegrationAuthParam = (typeof INTEGRATION_AUTH_PARAMS)[number];
28
- type IntegrationAuthParams = Partial<Record<IntegrationAuthParam, string>>;
29
- type IntegrationAuthHeader = (typeof INTEGRATION_AUTH_HEADERS)[number];
55
+ //#region source/lib/integration-auth/provider.d.ts
56
+ type IntegrationAuthHeader = "Authorization";
30
57
  type IntegrationAuthHeaders = Record<IntegrationAuthHeader, string>;
31
- type HttpMethod = (typeof HTTP_METHODS)[number];
58
+ type AdobeCommerceUrl = string | URL;
32
59
  interface IntegrationAuthProvider {
33
- getHeaders: (method: HttpMethod, url: string) => IntegrationAuthHeaders;
60
+ getHeaders: (method: HttpMethodInput, url: AdobeCommerceUrl) => IntegrationAuthHeaders;
34
61
  }
35
- declare function getIntegrationAuthProvider(params: IntegrationAuthParams): {
36
- getHeaders(method: HttpMethod, url: string): OAuth1a.Header;
37
- } | undefined;
62
+ declare function assertIntegrationAuthParams(config: Record<PropertyKey, unknown>): asserts config is IntegrationAuthParams;
63
+ declare function getIntegrationAuthProvider(authParams: IntegrationAuthParams): IntegrationAuthProvider;
38
64
  //#endregion
39
- export { ImsAuthHeader, ImsAuthHeaders, ImsAuthParam, ImsAuthParams, ImsAuthProvider, IntegrationAuthHeader, IntegrationAuthHeaders, IntegrationAuthParam, IntegrationAuthParams, IntegrationAuthProvider, getImsAuthProvider, getIntegrationAuthProvider };
65
+ export { IMS_AUTH_ENV, ImsAuthEnv, ImsAuthParams, ImsAuthProvider, IntegrationAuthParams, IntegrationAuthProvider, assertImsAuthParams, assertIntegrationAuthParams, getImsAuthProvider, getIntegrationAuthProvider };
package/dist/es/index.js CHANGED
@@ -1,111 +1,265 @@
1
+ import { CommerceSdkValidationError } from "@adobe/aio-commerce-lib-core/error";
1
2
  import { context, getToken } from "@adobe/aio-lib-ims";
3
+ import { array, email, enum as enum$1, instance, minLength, nonEmpty, nonOptional, object, optional, pipe, safeParse, string, transform, union, url } from "valibot";
2
4
  import crypto from "node:crypto";
3
5
  import OAuth1a from "oauth-1.0a";
4
6
 
5
- //#region source/lib/params.ts
7
+ //#region source/lib/ims-auth/schema.ts
6
8
  /**
7
- * Checks if the given value is non-empty.
8
- *
9
- * @param name of the parameter. Required because of `aio app dev` compatibility: inputs mapped to undefined env vars come as $<input_name> in dev mode, but as '' in prod mode.
10
- * @param value of the parameter.
9
+ * Creates a validation schema for a required IMS auth string parameter.
10
+ * @param name The name of the parameter for error messages.
11
+ * @returns A validation pipeline that ensures the parameter is a non-empty string.
11
12
  */
12
- function nonEmpty(name, value) {
13
- const v = value?.trim();
14
- return v !== void 0 && v !== `$${name}`;
15
- }
13
+ const imsAuthParameter = (name) => pipe(string(`Expected a string value for the IMS auth parameter ${name}`), nonEmpty(`Expected a non-empty string value for the IMS auth parameter ${name}`));
16
14
  /**
17
- * Checks if all required parameters are non-empty.
18
- * @param params action input parameters.
19
- * @param required list of required parameter names.
15
+ * Creates a validation schema for an IMS auth string array parameter.
16
+ * @param name The name of the parameter for error messages.
17
+ * @returns A validation pipeline that ensures the parameter is an array of strings.
20
18
  */
21
- function allNonEmpty(params, required) {
22
- return required.every((name) => nonEmpty(name, params[name]));
23
- }
19
+ const stringArray = (name) => {
20
+ return pipe(array(string(), `Expected a stringified JSON array value for the IMS auth parameter ${name}`));
21
+ };
22
+ /** The environments accepted by the IMS auth service. */
23
+ const IMS_AUTH_ENV = {
24
+ PROD: "prod",
25
+ STAGE: "stage"
26
+ };
27
+ /** Validation schema for IMS auth environment values. */
28
+ const ImsAuthEnvSchema = enum$1(IMS_AUTH_ENV);
29
+ /** Defines the schema to validate the necessary parameters for the IMS auth service. */
30
+ const ImsAuthParamsSchema = object({
31
+ clientId: imsAuthParameter("clientId"),
32
+ clientSecrets: pipe(stringArray("clientSecrets"), minLength(1, "Expected at least one client secret for IMS auth")),
33
+ technicalAccountId: imsAuthParameter("technicalAccountId"),
34
+ technicalAccountEmail: pipe(string("Expected a string value for the IMS auth parameter technicalAccountEmail"), email("Expected a valid email format for technicalAccountEmail")),
35
+ imsOrgId: imsAuthParameter("imsOrgId"),
36
+ environment: pipe(optional(ImsAuthEnvSchema, IMS_AUTH_ENV.PROD)),
37
+ context: pipe(optional(string(), "aio-commerce-sdk-creds")),
38
+ scopes: pipe(stringArray("scopes"), minLength(1, "Expected at least one scope for IMS auth"))
39
+ });
24
40
 
25
41
  //#endregion
26
- //#region source/lib/ims-auth.ts
42
+ //#region source/lib/ims-auth/provider.ts
43
+ /**
44
+ * Converts IMS auth configuration properties to snake_case format.
45
+ * @param config The IMS auth configuration with camelCase properties.
46
+ * @returns The configuration with snake_case properties.
47
+ */
48
+ function toImsAuthConfig(config) {
49
+ return {
50
+ scopes: config.scopes,
51
+ env: config?.environment ?? "prod",
52
+ context: config.context,
53
+ client_id: config.clientId,
54
+ client_secrets: config.clientSecrets,
55
+ technical_account_id: config.technicalAccountId,
56
+ technical_account_email: config.technicalAccountEmail,
57
+ ims_org_id: config.imsOrgId
58
+ };
59
+ }
60
+ /**
61
+ * Asserts the provided configuration for an Adobe IMS authentication provider. {@link ImsAuthParams}
62
+ * {@link ImsAuthProvider}
63
+ * @param config {Record<PropertyKey, unknown>} The configuration to validate.
64
+ * @throws {CommerceSdkValidationError} If the configuration is invalid.
65
+ * @example
66
+ * ```typescript
67
+ * const config = {
68
+ * clientId: "your-client-id",
69
+ * clientSecrets: ["your-client-secret"],
70
+ * technicalAccountId: "your-technical-account-id",
71
+ * technicalAccountEmail: "your-account@example.com",
72
+ * imsOrgId: "your-ims-org-id@AdobeOrg",
73
+ * scopes: ["AdobeID", "openid"],
74
+ * environment: "prod", // or "stage"
75
+ * context: "my-app-context"
76
+ * };
77
+ *
78
+ * // This will validate the config and throw if invalid
79
+ * assertImsAuthParams(config);
80
+ *```
81
+ * @example
82
+ * ```typescript
83
+ * // Example of a failing assert:
84
+ * try {
85
+ * assertImsAuthParams({
86
+ * clientId: "valid-client-id",
87
+ * // Missing required fields like clientSecrets, technicalAccountId, etc.
88
+ * });
89
+ * } catch (error) {
90
+ * console.error(error.message); // "Invalid ImsAuthProvider configuration"
91
+ * console.error(error.issues); // Array of validation issues
92
+ * }
93
+ * ```
94
+ */
95
+ function assertImsAuthParams(config) {
96
+ const result = safeParse(ImsAuthParamsSchema, config);
97
+ if (!result.success) throw new CommerceSdkValidationError("Invalid ImsAuthProvider configuration", { issues: result.issues });
98
+ }
27
99
  /**
28
- * If the required IMS parameters are present, this function returns an {@link ImsAuthProvider}.
29
- * @param params includes IMS parameters
100
+ * Creates an {@link ImsAuthProvider} based on the provided configuration.
101
+ * @param config An {@link ImsAuthParams} parameter that contains the configuration for the IMS auth provider.
102
+ * @returns An {@link ImsAuthProvider} instance that can be used to get access token and auth headers.
103
+ * @example
104
+ * ```typescript
105
+ * const config = {
106
+ * clientId: "your-client-id",
107
+ * clientSecrets: ["your-client-secret"],
108
+ * technicalAccountId: "your-technical-account-id",
109
+ * technicalAccountEmail: "your-account@example.com",
110
+ * imsOrgId: "your-ims-org-id@AdobeOrg",
111
+ * scopes: ["AdobeID", "openid"],
112
+ * environment: "prod",
113
+ * context: "my-app-context"
114
+ * };
115
+ *
116
+ * const authProvider = getImsAuthProvider(config);
117
+ *
118
+ * // Get access token
119
+ * const token = await authProvider.getAccessToken();
120
+ * console.log(token); // "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."
121
+ *
122
+ * // Get headers for API requests
123
+ * const headers = await authProvider.getHeaders();
124
+ * console.log(headers);
125
+ * // {
126
+ * // Authorization: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
127
+ * // "x-api-key": "your-client-id"
128
+ * // }
129
+ *
130
+ * // Use headers in API calls
131
+ * const response = await fetch('https://api.adobe.io/some-endpoint', {
132
+ * headers: await authProvider.getHeaders()
133
+ * });
134
+ * ```
30
135
  */
31
- async function getImsAuthProvider(params) {
32
- const config = resolveImsConfig(params);
33
- if (config) {
34
- const contextName = params.AIO_COMMERCE_IMS_CTX ?? "aio-commerce-sdk-creds";
35
- await context.set(contextName, config);
136
+ function getImsAuthProvider(authParams) {
137
+ const getAccessToken = async () => {
138
+ const imsAuthConfig = toImsAuthConfig(authParams);
139
+ await context.set(authParams.context, imsAuthConfig);
140
+ return getToken(authParams.context, {});
141
+ };
142
+ const getHeaders = async () => {
143
+ const accessToken = await getAccessToken();
36
144
  return {
37
- getAccessToken: async () => getToken(contextName, {}),
38
- getHeaders: async () => {
39
- const accessToken = await getToken(contextName, {});
40
- return {
41
- Authorization: `Bearer ${accessToken}`,
42
- "x-api-key": config.client_id
43
- };
44
- }
145
+ Authorization: `Bearer ${accessToken}`,
146
+ "x-api-key": authParams.clientId
45
147
  };
46
- }
47
- }
48
- function resolveImsConfig(params) {
49
- if (allNonEmpty(params, [
50
- "AIO_COMMERCE_IMS_CLIENT_ID",
51
- "AIO_COMMERCE_IMS_CLIENT_SECRETS",
52
- "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID",
53
- "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL",
54
- "AIO_COMMERCE_IMS_IMS_ORG_ID",
55
- "AIO_COMMERCE_IMS_SCOPES"
56
- ])) return {
57
- client_id: params.AIO_COMMERCE_IMS_CLIENT_ID,
58
- client_secrets: JSON.parse(params.AIO_COMMERCE_IMS_CLIENT_SECRETS ?? "[]"),
59
- technical_account_id: params.AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID,
60
- technical_account_email: params.AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL,
61
- ims_org_id: params.AIO_COMMERCE_IMS_IMS_ORG_ID,
62
- scopes: JSON.parse(params.AIO_COMMERCE_IMS_SCOPES ?? "[]"),
63
- environment: params.AIO_COMMERCE_IMS_ENV ?? "prod"
148
+ };
149
+ return {
150
+ getAccessToken,
151
+ getHeaders
64
152
  };
65
153
  }
66
154
 
67
155
  //#endregion
68
- //#region source/lib/integration-auth.ts
156
+ //#region source/lib/integration-auth/schema.ts
69
157
  /**
70
- * If the required integration parameters are present, this function returns an {@link IntegrationAuthProvider}.
71
- * @param params includes integration parameters
158
+ * Creates a validation schema for a required Commerce Integration string parameter.
159
+ * @param name The name of the parameter for error messages.
160
+ * @returns A validation pipeline that ensures the parameter is a non-empty string.
72
161
  */
73
- function getIntegrationAuthProvider(params) {
74
- const config = resolveIntegrationConfig(params);
75
- if (config) {
76
- const oauth = new OAuth1a({
77
- consumer: {
78
- key: config.consumerKey,
79
- secret: config.consumerSecret
80
- },
81
- signature_method: "HMAC-SHA256",
82
- hash_function: (baseString, key) => crypto.createHmac("sha256", key).update(baseString).digest("base64")
83
- });
84
- const oauthToken = {
85
- key: config.accessToken,
86
- secret: config.accessTokenSecret
87
- };
88
- return { getHeaders(method, url) {
89
- return oauth.toHeader(oauth.authorize({
90
- url,
91
- method
92
- }, oauthToken));
93
- } };
94
- }
162
+ const integrationAuthParameter = (name) => pipe(string(`Expected a string value for the Commerce Integration parameter ${name}`), nonEmpty(`Expected a non-empty string value for the Commerce Integration parameter ${name}`));
163
+ /** Validation schema for the Adobe Commerce endpoint base URL. */
164
+ const BaseUrlSchema = pipe(string("Expected a string for the Adobe Commerce endpoint"), nonEmpty("Expected a non-empty string for the Adobe Commerce endpoint"), url("Expected a valid url for the Adobe Commerce endpoint"));
165
+ /** Validation schema that accepts either a URL string or URL instance and normalizes to string. */
166
+ const UrlSchema = pipe(union([BaseUrlSchema, instance(URL)]), transform((url$1) => {
167
+ if (url$1 instanceof URL) return url$1.toString();
168
+ return url$1;
169
+ }));
170
+ /**
171
+ * The schema for the Commerce Integration parameters.
172
+ * This is used to validate the parameters passed to the Commerce Integration provider.
173
+ */
174
+ const IntegrationAuthParamsSchema = nonOptional(object({
175
+ consumerKey: integrationAuthParameter("consumerKey"),
176
+ consumerSecret: integrationAuthParameter("consumerSecret"),
177
+ accessToken: integrationAuthParameter("accessToken"),
178
+ accessTokenSecret: integrationAuthParameter("accessTokenSecret")
179
+ }));
180
+
181
+ //#endregion
182
+ //#region source/lib/integration-auth/provider.ts
183
+ /**
184
+ * Asserts the provided configuration for an Adobe Commerce integration authentication provider. {@link IntegrationAuthParams}
185
+ * {@link IntegrationAuthProvider}
186
+ * @param config {Record<PropertyKey, unknown>} The configuration to validate.
187
+ * @throws {CommerceSdkValidationError} If the configuration is invalid.
188
+ * @example
189
+ * ```typescript
190
+ * const config = {
191
+ * consumerKey: "your-consumer-key",
192
+ * consumerSecret: "your-consumer-secret",
193
+ * accessToken: "your-access-token",
194
+ * accessTokenSecret: "your-access-token-secret"
195
+ * };
196
+ *
197
+ * // This will validate the config and throw if invalid
198
+ * assertIntegrationAuthParams(config);
199
+ * ```
200
+ * @example
201
+ * ```typescript
202
+ * // Example of a failing assert:
203
+ * try {
204
+ * assertIntegrationAuthParams({
205
+ * consumerKey: "valid-consumer-key",
206
+ * // Missing required fields like consumerSecret, accessToken, accessTokenSecret
207
+ * });
208
+ * } catch (error) {
209
+ * console.error(error.message); // "Invalid IntegrationAuthProvider configuration"
210
+ * console.error(error.issues); // Array of validation issues
211
+ * }
212
+ * ```
213
+ */
214
+ function assertIntegrationAuthParams(config) {
215
+ const result = safeParse(IntegrationAuthParamsSchema, config);
216
+ if (!result.success) throw new CommerceSdkValidationError("Invalid IntegrationAuthProvider configuration", { issues: result.issues });
95
217
  }
96
- function resolveIntegrationConfig(params) {
97
- if (allNonEmpty(params, [
98
- "AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY",
99
- "AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET",
100
- "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN",
101
- "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET"
102
- ])) return {
103
- consumerKey: params.AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY,
104
- consumerSecret: params.AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET,
105
- accessToken: params.AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN,
106
- accessTokenSecret: params.AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET
218
+ /**
219
+ * Creates an {@link IntegrationAuthProvider} based on the provided configuration.
220
+ * @param config {IntegrationAuthParams} The configuration for the integration.
221
+ * @returns An {@link IntegrationAuthProvider} instance that can be used to get auth headers.
222
+ * @example
223
+ * ```typescript
224
+ * const config = {
225
+ * consumerKey: "your-consumer-key",
226
+ * consumerSecret: "your-consumer-secret",
227
+ * accessToken: "your-access-token",
228
+ * accessTokenSecret: "your-access-token-secret"
229
+ * };
230
+ *
231
+ * const authProvider = getIntegrationAuthProvider(config);
232
+ *
233
+ * // Get OAuth headers for a REST API call
234
+ * const headers = authProvider.getHeaders("GET", "https://your-store.com/rest/V1/products");
235
+ * console.log(headers); // { Authorization: "OAuth oauth_consumer_key=..., oauth_signature=..." }
236
+ *
237
+ * // Can also be used with URL objects
238
+ * const url = new URL("https://your-store.com/rest/V1/customers");
239
+ * const postHeaders = authProvider.getHeaders("POST", url);
240
+ * ```
241
+ */
242
+ function getIntegrationAuthProvider(authParams) {
243
+ const oauth = new OAuth1a({
244
+ consumer: {
245
+ key: authParams.consumerKey,
246
+ secret: authParams.consumerSecret
247
+ },
248
+ signature_method: "HMAC-SHA256",
249
+ hash_function: (baseString, key) => crypto.createHmac("sha256", key).update(baseString).digest("base64")
250
+ });
251
+ const oauthToken = {
252
+ key: authParams.accessToken,
253
+ secret: authParams.accessTokenSecret
107
254
  };
255
+ return { getHeaders: (method, url$1) => {
256
+ const urlString = url$1 instanceof URL ? url$1.toString() : url$1;
257
+ return oauth.toHeader(oauth.authorize({
258
+ url: urlString,
259
+ method
260
+ }, oauthToken));
261
+ } };
108
262
  }
109
263
 
110
264
  //#endregion
111
- export { getImsAuthProvider, getIntegrationAuthProvider };
265
+ export { IMS_AUTH_ENV, assertImsAuthParams, assertIntegrationAuthParams, getImsAuthProvider, getIntegrationAuthProvider };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@adobe/aio-commerce-lib-auth",
3
3
  "type": "module",
4
- "version": "0.1.0",
4
+ "version": "0.3.0",
5
5
  "private": false,
6
6
  "author": "Adobe Inc.",
7
7
  "engines": {
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "main": "./dist/cjs/index.cjs",
28
28
  "module": "./dist/es/index.js",
29
- "types": "./dist/es/index.d.ts",
29
+ "types": "./dist/cjs/index.d.cts",
30
30
  "exports": {
31
31
  ".": {
32
32
  "import": {
@@ -40,9 +40,18 @@
40
40
  },
41
41
  "./package.json": "./package.json"
42
42
  },
43
+ "files": [
44
+ "dist",
45
+ "package.json",
46
+ "CHANGELOG.md",
47
+ "README.md"
48
+ ],
43
49
  "dependencies": {
44
50
  "@adobe/aio-lib-ims": "^8.1.0",
45
- "oauth-1.0a": "^2.2.6"
51
+ "ansis": "^4.1.0",
52
+ "oauth-1.0a": "^2.2.6",
53
+ "valibot": "^1.1.0",
54
+ "@adobe/aio-commerce-lib-core": "0.3.0"
46
55
  },
47
56
  "devDependencies": {
48
57
  "vitest": "^3.2.4",
@@ -1,18 +0,0 @@
1
-
2
- > @adobe/aio-commerce-lib-auth@0.1.0 build /home/runner/work/aio-commerce-sdk/aio-commerce-sdk/packages/aio-commerce-lib-auth
3
- > tsdown
4
-
5
- ℹ tsdown v0.12.9 powered by rolldown v1.0.0-beta.21
6
- ℹ Using tsdown config: /home/runner/work/aio-commerce-sdk/aio-commerce-sdk/packages/aio-commerce-lib-auth/tsdown.config.ts
7
- ℹ entry: source/index.ts
8
- ℹ target: node22.0.0
9
- ℹ tsconfig: tsconfig.json
10
- ℹ Build start
11
- ℹ [CJS] dist/cjs/index.cjs 4.81 kB │ gzip: 1.71 kB
12
- ℹ [CJS] 1 files, total: 4.81 kB
13
- ℹ [CJS] dist/index.d.cts 2.33 kB │ gzip: 0.69 kB
14
- ℹ [CJS] 1 files, total: 2.33 kB
15
- ℹ [ESM] dist/es/index.js 3.63 kB │ gzip: 1.27 kB
16
- ℹ [ESM] dist/es/index.d.ts 2.33 kB │ gzip: 0.69 kB
17
- ℹ [ESM] 2 files, total: 5.97 kB
18
- ✔ Build complete in 1768ms
package/source/index.ts DELETED
@@ -1,14 +0,0 @@
1
- /*
2
- * Copyright 2025 Adobe. All rights reserved.
3
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
- * you may not use this file except in compliance with the License. You may obtain a copy
5
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
- *
7
- * Unless required by applicable law or agreed to in writing, software distributed under
8
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
- * OF ANY KIND, either express or implied. See the License for the specific language
10
- * governing permissions and limitations under the License.
11
- */
12
-
13
- export * from "./lib/ims-auth";
14
- export * from "./lib/integration-auth";
@@ -1,95 +0,0 @@
1
- /*
2
- * Copyright 2025 Adobe. All rights reserved.
3
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
- * you may not use this file except in compliance with the License. You may obtain a copy
5
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
- *
7
- * Unless required by applicable law or agreed to in writing, software distributed under
8
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
- * OF ANY KIND, either express or implied. See the License for the specific language
10
- * governing permissions and limitations under the License.
11
- */
12
-
13
- import { context, getToken } from "@adobe/aio-lib-ims";
14
- import { allNonEmpty } from "./params";
15
-
16
- const IMS_AUTH_HEADERS = ["Authorization", "x-api-key"] as const;
17
- const IMS_AUTH_PARAMS = [
18
- "AIO_COMMERCE_IMS_CLIENT_ID",
19
- "AIO_COMMERCE_IMS_CLIENT_SECRETS",
20
- "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID",
21
- "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL",
22
- "AIO_COMMERCE_IMS_IMS_ORG_ID",
23
- "AIO_COMMERCE_IMS_SCOPES",
24
- "AIO_COMMERCE_IMS_ENV",
25
- "AIO_COMMERCE_IMS_CTX",
26
- ] as const;
27
-
28
- /** Defines a union of allowed IMS authentication parameters. */
29
- export type ImsAuthParam = (typeof IMS_AUTH_PARAMS)[number];
30
-
31
- /** Defines a key-value map of IMS authentication parameters. */
32
- export type ImsAuthParams = Partial<Record<ImsAuthParam, string>>;
33
-
34
- /** Defines a union of allowed IMS authentication headers. */
35
- export type ImsAuthHeader = (typeof IMS_AUTH_HEADERS)[number];
36
-
37
- /** Defines a key-value map of IMS authentication headers. */
38
- export type ImsAuthHeaders = Record<ImsAuthHeader, string>;
39
-
40
- type ImsAccessToken = string;
41
-
42
- /** Defines an authentication provider for Adobe IMS. */
43
- export interface ImsAuthProvider {
44
- getHeaders: () => Promise<ImsAuthHeaders>;
45
- getAccessToken: () => Promise<ImsAccessToken>;
46
- }
47
-
48
- /**
49
- * If the required IMS parameters are present, this function returns an {@link ImsAuthProvider}.
50
- * @param params includes IMS parameters
51
- */
52
- export async function getImsAuthProvider(params: ImsAuthParams) {
53
- const config = resolveImsConfig(params);
54
-
55
- if (config) {
56
- const contextName = params.AIO_COMMERCE_IMS_CTX ?? "aio-commerce-sdk-creds";
57
- await context.set(contextName, config);
58
-
59
- return {
60
- getAccessToken: async () => getToken(contextName, {}),
61
- getHeaders: async () => {
62
- const accessToken = await getToken(contextName, {});
63
- return {
64
- Authorization: `Bearer ${accessToken}`,
65
- "x-api-key": config.client_id,
66
- };
67
- },
68
- } satisfies ImsAuthProvider;
69
- }
70
- }
71
-
72
- function resolveImsConfig(params: ImsAuthParams) {
73
- if (
74
- allNonEmpty(params, [
75
- "AIO_COMMERCE_IMS_CLIENT_ID",
76
- "AIO_COMMERCE_IMS_CLIENT_SECRETS",
77
- "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID",
78
- "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL",
79
- "AIO_COMMERCE_IMS_IMS_ORG_ID",
80
- "AIO_COMMERCE_IMS_SCOPES",
81
- ])
82
- ) {
83
- return {
84
- client_id: params.AIO_COMMERCE_IMS_CLIENT_ID,
85
- client_secrets: JSON.parse(
86
- params.AIO_COMMERCE_IMS_CLIENT_SECRETS ?? "[]",
87
- ) as string[],
88
- technical_account_id: params.AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID,
89
- technical_account_email: params.AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL,
90
- ims_org_id: params.AIO_COMMERCE_IMS_IMS_ORG_ID,
91
- scopes: JSON.parse(params.AIO_COMMERCE_IMS_SCOPES ?? "[]") as string[],
92
- environment: params.AIO_COMMERCE_IMS_ENV ?? "prod",
93
- };
94
- }
95
- }