@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,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 crypto from "node:crypto";
14
- import OAuth1a from "oauth-1.0a";
15
-
16
- import { allNonEmpty } from "./params";
17
-
18
- const HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"] as const;
19
- const INTEGRATION_AUTH_HEADERS = ["Authorization"] as const;
20
- const INTEGRATION_AUTH_PARAMS = [
21
- "AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY",
22
- "AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET",
23
- "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN",
24
- "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET",
25
- ] as const;
26
-
27
- /** Defines a union of allowed integration authentication parameters. */
28
- export type IntegrationAuthParam = (typeof INTEGRATION_AUTH_PARAMS)[number];
29
-
30
- /** Defines a key-value map of integration authentication parameters. */
31
- export type IntegrationAuthParams = Partial<
32
- Record<IntegrationAuthParam, string>
33
- >;
34
-
35
- /** Defines a union of allowed integration authentication headers. */
36
- export type IntegrationAuthHeader = (typeof INTEGRATION_AUTH_HEADERS)[number];
37
-
38
- /** Defines a key-value map of integration authentication headers. */
39
- export type IntegrationAuthHeaders = Record<IntegrationAuthHeader, string>;
40
-
41
- type HttpMethod = (typeof HTTP_METHODS)[number];
42
-
43
- /** Defines an authentication provider for integration authentication. */
44
- export interface IntegrationAuthProvider {
45
- getHeaders: (method: HttpMethod, url: string) => IntegrationAuthHeaders;
46
- }
47
-
48
- /**
49
- * If the required integration parameters are present, this function returns an {@link IntegrationAuthProvider}.
50
- * @param params includes integration parameters
51
- */
52
- export function getIntegrationAuthProvider(params: IntegrationAuthParams) {
53
- const config = resolveIntegrationConfig(params);
54
-
55
- if (config) {
56
- const oauth = new OAuth1a({
57
- consumer: {
58
- key: config.consumerKey,
59
- secret: config.consumerSecret,
60
- },
61
- signature_method: "HMAC-SHA256",
62
- hash_function: (baseString, key) =>
63
- crypto.createHmac("sha256", key).update(baseString).digest("base64"),
64
- });
65
-
66
- const oauthToken = {
67
- key: config.accessToken,
68
- secret: config.accessTokenSecret,
69
- };
70
-
71
- return {
72
- getHeaders(method: HttpMethod, url: string) {
73
- return oauth.toHeader(oauth.authorize({ url, method }, oauthToken));
74
- },
75
- } satisfies IntegrationAuthProvider;
76
- }
77
- }
78
-
79
- function resolveIntegrationConfig(params: IntegrationAuthParams) {
80
- if (
81
- allNonEmpty(params, [
82
- "AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY",
83
- "AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET",
84
- "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN",
85
- "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET",
86
- ])
87
- ) {
88
- return {
89
- consumerKey: params.AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY,
90
- consumerSecret: params.AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET,
91
- accessToken: params.AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN,
92
- accessTokenSecret: params.AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET,
93
- };
94
- }
95
- }
@@ -1,34 +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
- /**
14
- * Checks if the given value is non-empty.
15
- *
16
- * @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.
17
- * @param value of the parameter.
18
- */
19
- export function nonEmpty(name: string, value: string | undefined) {
20
- const v = value?.trim();
21
- return v !== undefined && v !== `$${name}`;
22
- }
23
-
24
- /**
25
- * Checks if all required parameters are non-empty.
26
- * @param params action input parameters.
27
- * @param required list of required parameter names.
28
- */
29
- export function allNonEmpty<const T extends string>(
30
- params: Record<string, string | undefined>,
31
- required: T[],
32
- ): params is Required<Record<T, string> & Record<string, string>> {
33
- return required.every((name) => nonEmpty(name, params[name]));
34
- }
@@ -1,69 +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 { getToken } from "@adobe/aio-lib-ims";
14
- import { describe, expect, test, vi } from "vitest";
15
-
16
- import { getImsAuthProvider, type ImsAuthParams } from "~/lib/ims-auth";
17
-
18
- vi.mock("@adobe/aio-lib-ims", async () => ({
19
- context: (await vi.importActual("@adobe/aio-lib-ims")).context,
20
- getToken: vi.fn(),
21
- }));
22
-
23
- describe("getImsAuthProvider", () => {
24
- const params: ImsAuthParams = {
25
- AIO_COMMERCE_IMS_CLIENT_ID: "test-client-id",
26
- AIO_COMMERCE_IMS_CLIENT_SECRETS: JSON.stringify(["supersecret"]),
27
- AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID: "test-technical-account-id",
28
- AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL: "test-email@example.com",
29
- AIO_COMMERCE_IMS_IMS_ORG_ID: "test-org-id",
30
- AIO_COMMERCE_IMS_SCOPES: JSON.stringify(["scope1", "scope2"]),
31
- };
32
-
33
- test("should export token when all required params are provided", async () => {
34
- const authToken = "supersecrettoken";
35
- vi.mocked(getToken).mockResolvedValue(authToken);
36
-
37
- const imsProvider = await getImsAuthProvider(params);
38
- expect(imsProvider).toBeDefined();
39
-
40
- const retrievedToken = await imsProvider?.getAccessToken();
41
- expect(retrievedToken).toEqual(authToken);
42
-
43
- const headers = await imsProvider?.getHeaders();
44
- expect(headers).toHaveProperty("Authorization", `Bearer ${authToken}`);
45
- expect(headers).toHaveProperty(
46
- "x-api-key",
47
- params.AIO_COMMERCE_IMS_CLIENT_ID,
48
- );
49
- });
50
-
51
- for (const param of [
52
- "AIO_COMMERCE_IMS_CLIENT_ID",
53
- "AIO_COMMERCE_IMS_CLIENT_SECRETS",
54
- "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID",
55
- "AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL",
56
- "AIO_COMMERCE_IMS_IMS_ORG_ID",
57
- "AIO_COMMERCE_IMS_SCOPES",
58
- ]) {
59
- test(`should return undefined when ${param} is missing`, async () => {
60
- const incompleteParams = {
61
- ...params,
62
- [param]: undefined,
63
- };
64
-
65
- const imsProvider = await getImsAuthProvider(incompleteParams);
66
- expect(imsProvider).toBeUndefined();
67
- });
68
- }
69
- });
@@ -1,61 +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 { describe, expect, test } from "vitest";
14
- import {
15
- getIntegrationAuthProvider,
16
- type IntegrationAuthParams,
17
- } from "~/lib/integration-auth";
18
-
19
- /** Regex to match the OAuth 1.0a header format. */
20
- const OAUTH1_REGEX =
21
- /^OAuth oauth_consumer_key="[^"]+", oauth_nonce="[^"]+", oauth_signature="[^"]+", oauth_signature_method="HMAC-SHA256", oauth_timestamp="[^"]+", oauth_token="[^"]+", oauth_version="1\.0"$/;
22
-
23
- describe("getIntegrationAuthProvider", () => {
24
- const params: IntegrationAuthParams = {
25
- AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY: "test-consumer-key",
26
- AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET: "test-consumer-secret",
27
- AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN: "test-access-token",
28
- AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET: "test-access-token-secret",
29
- };
30
-
31
- test("should export getIntegrationAccessToken", () => {
32
- const integrationProvider = getIntegrationAuthProvider(params);
33
- expect(integrationProvider).toBeDefined();
34
-
35
- const headers = integrationProvider?.getHeaders(
36
- "GET",
37
- "http://localhost/test",
38
- );
39
- expect(headers).toHaveProperty(
40
- "Authorization",
41
- expect.stringMatching(OAUTH1_REGEX),
42
- );
43
- });
44
-
45
- for (const param of [
46
- "AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY",
47
- "AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET",
48
- "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN",
49
- "AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET",
50
- ]) {
51
- test(`should return undefined when ${param} is missing`, () => {
52
- const incompleteParams = {
53
- ...params,
54
- [param]: undefined,
55
- };
56
-
57
- const integrationProvider = getIntegrationAuthProvider(incompleteParams);
58
- expect(integrationProvider).toBeUndefined();
59
- });
60
- }
61
- });
package/tsconfig.json DELETED
@@ -1,15 +0,0 @@
1
- {
2
- "extends": "@aio-commerce-sdk/config-typescript/tsconfig.base.json",
3
- "compilerOptions": {
4
- "baseUrl": ".",
5
- "rootDir": ".",
6
- "outDir": "./dist",
7
-
8
- "paths": {
9
- "~/*": ["./source/*"],
10
- "~~/*": ["./*"]
11
- }
12
- },
13
-
14
- "include": ["tsdown.config.ts", "source/**/*", "test/**/*"]
15
- }
package/tsdown.config.ts DELETED
@@ -1,7 +0,0 @@
1
- import { baseConfig } from "@aio-commerce-sdk/config-tsdown/tsdown.config.base";
2
- import { defineConfig } from "tsdown";
3
-
4
- export default defineConfig({
5
- ...baseConfig,
6
- entry: ["./source/index.ts"],
7
- });
package/vitest.config.ts DELETED
@@ -1,16 +0,0 @@
1
- import { resolve } from "node:path";
2
- import { defineConfig } from "vitest/config";
3
-
4
- export default defineConfig({
5
- resolve: {
6
- alias: {
7
- "~": resolve(__dirname, "./source"),
8
- "~~": resolve(__dirname, "./"),
9
- },
10
- },
11
-
12
- test: {
13
- globals: true,
14
- environment: "node",
15
- },
16
- });