@adobe/aio-commerce-lib-auth 0.2.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.
- package/CHANGELOG.md +14 -0
- package/README.md +90 -79
- package/dist/cjs/index.cjs +186 -122
- package/dist/cjs/index.d.cts +34 -57
- package/dist/es/index.d.ts +30 -53
- package/dist/es/index.js +185 -121
- package/package.json +9 -3
- package/.turbo/turbo-build.log +0 -18
- package/source/index.ts +0 -35
- package/source/lib/ims-auth/provider.ts +0 -160
- package/source/lib/ims-auth/schema.ts +0 -87
- package/source/lib/integration-auth/provider.ts +0 -145
- package/source/lib/integration-auth/schema.ts +0 -87
- package/test/ims-auth.test.ts +0 -147
- package/test/integration-auth.test.ts +0 -124
- package/tsconfig.json +0 -15
- package/tsdown.config.ts +0 -7
- package/vitest.config.ts +0 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @adobe/aio-commerce-lib-auth
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#22](https://github.com/adobe/aio-commerce-sdk/pull/22) [`9885eee`](https://github.com/adobe/aio-commerce-sdk/commit/9885eee5849ba7939b2067d3357e677beced3774) Thanks [@iivvaannxx](https://github.com/iivvaannxx)! - Changes include:
|
|
8
|
+
- Removed `try*` methods from public interface
|
|
9
|
+
- Added `assert` methods that throw if required configuration is not provided
|
|
10
|
+
- Cleaned up unused types to reduce bundle size
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [[`9885eee`](https://github.com/adobe/aio-commerce-sdk/commit/9885eee5849ba7939b2067d3357e677beced3774)]:
|
|
15
|
+
- @adobe/aio-commerce-lib-core@0.3.0
|
|
16
|
+
|
|
3
17
|
## 0.2.0
|
|
4
18
|
|
|
5
19
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -11,29 +11,15 @@ This library provides a unified interface for authentication in Adobe Commerce A
|
|
|
11
11
|
|
|
12
12
|
The library supports two main authentication providers:
|
|
13
13
|
|
|
14
|
-
- **IMS Provider**: For authenticating users or services via Adobe Identity Management System (IMS) using OAuth2
|
|
15
|
-
|
|
16
|
-
- AIO_COMMERCE_IMS_CLIENT_ID: string
|
|
17
|
-
- AIO_COMMERCE_IMS_CLIENT_SECRETS: string
|
|
18
|
-
- AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_ID: string
|
|
19
|
-
- AIO_COMMERCE_IMS_TECHNICAL_ACCOUNT_EMAIL: string
|
|
20
|
-
- AIO_COMMERCE_IMS_IMS_ORG_ID: string
|
|
21
|
-
- AIO_COMMERCE_IMS_ENV: string e.g `'prod'` or `'stage'`
|
|
22
|
-
- AIO_COMMERCE_IMS_SCOPES: string e.g `'["value1", "value2"]'`
|
|
23
|
-
- AIO_COMMERCE_IMS_CTX: string
|
|
24
|
-
- **Integrations Provider**: For authenticating with Adobe Commerce integrations using OAuth 1.0a.
|
|
25
|
-
- Required params
|
|
26
|
-
- AIO_COMMERCE_INTEGRATIONS_CONSUMER_KEY: string
|
|
27
|
-
- AIO_COMMERCE_INTEGRATIONS_CONSUMER_SECRET: string
|
|
28
|
-
- AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN: string
|
|
29
|
-
- AIO_COMMERCE_INTEGRATIONS_ACCESS_TOKEN_SECRET: string
|
|
14
|
+
- **IMS Provider**: For authenticating users or services via Adobe Identity Management System (IMS) using OAuth2
|
|
15
|
+
- **Integrations Provider**: For authenticating with Adobe Commerce integrations using OAuth 1.0a
|
|
30
16
|
|
|
31
17
|
These providers abstract the complexity of authentication, making it easy to obtain and use access tokens in your App Builder applications.
|
|
32
18
|
|
|
33
19
|
## Installation
|
|
34
20
|
|
|
35
21
|
```shell
|
|
36
|
-
|
|
22
|
+
pnpm install @adobe/aio-commerce-lib-auth
|
|
37
23
|
```
|
|
38
24
|
|
|
39
25
|
## Usage
|
|
@@ -42,86 +28,111 @@ In your App Builder application, you can use the library to authenticate users o
|
|
|
42
28
|
|
|
43
29
|
### IMS Provider
|
|
44
30
|
|
|
45
|
-
In the runtime action you can generate an access token using the IMS Provider:
|
|
46
|
-
|
|
47
31
|
```typescript
|
|
48
|
-
import {
|
|
49
|
-
|
|
32
|
+
import {
|
|
33
|
+
assertImsAuthParams,
|
|
34
|
+
getImsAuthProvider,
|
|
35
|
+
} from "@adobe/aio-commerce-lib-auth";
|
|
50
36
|
|
|
51
|
-
|
|
52
|
-
const result = tryGetImsAuthProvider(params); // Validate parameters and get the integration auth provider
|
|
53
|
-
|
|
54
|
-
if (isErr(result)) {
|
|
55
|
-
const { error } = result;
|
|
56
|
-
return {
|
|
57
|
-
statusCode: 400,
|
|
58
|
-
body: {
|
|
59
|
-
error: `Unable to get IMS Auth Provider ${error.message}`,
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
}
|
|
37
|
+
import { CommerceSdkValidationError } from "@adobe/aio-commerce-lib-core";
|
|
63
38
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
39
|
+
export const main = async function (params: Record<string, unknown>) {
|
|
40
|
+
try {
|
|
41
|
+
// Validate parameters and get the IMS auth provider
|
|
42
|
+
assertImsAuthParams(params);
|
|
43
|
+
const imsAuthProvider = getImsAuthProvider(params);
|
|
44
|
+
|
|
45
|
+
const token = await imsAuthProvider.getAccessToken();
|
|
46
|
+
const headers = await imsAuthProvider.getHeaders();
|
|
47
|
+
|
|
48
|
+
// Use headers in your API calls
|
|
49
|
+
// business logic e.g requesting orders
|
|
50
|
+
return { statusCode: 200 };
|
|
51
|
+
} catch (error) {
|
|
52
|
+
if (error instanceof CommerceSdkValidationError) {
|
|
53
|
+
return {
|
|
54
|
+
statusCode: 400,
|
|
55
|
+
body: {
|
|
56
|
+
error: `Invalid IMS configuration: ${error.message}`,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
75
61
|
}
|
|
76
|
-
|
|
77
|
-
// business logic e.g requesting orders
|
|
78
|
-
return { statusCode: 200 };
|
|
79
62
|
};
|
|
80
63
|
```
|
|
81
64
|
|
|
82
65
|
### Integrations Provider
|
|
83
66
|
|
|
84
|
-
In the runtime action you can generate an access token using the Integrations Provider:
|
|
85
|
-
|
|
86
67
|
```typescript
|
|
87
|
-
import {
|
|
88
|
-
|
|
68
|
+
import {
|
|
69
|
+
assertIntegrationAuthParams,
|
|
70
|
+
getIntegrationAuthProvider,
|
|
71
|
+
} from "@adobe/aio-commerce-lib-auth";
|
|
72
|
+
|
|
73
|
+
import { CommerceSdkValidationError } from "@adobe/aio-commerce-lib-core";
|
|
89
74
|
|
|
90
75
|
export const main = async function (params: Record<string, unknown>) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
76
|
+
try {
|
|
77
|
+
// Validate parameters and get the integration auth provider
|
|
78
|
+
assertIntegrationAuthParams(params);
|
|
79
|
+
const integrationsAuth = getIntegrationAuthProvider(params);
|
|
80
|
+
|
|
81
|
+
// Get OAuth headers for API requests
|
|
82
|
+
const headers = integrationsAuth.getHeaders(
|
|
83
|
+
"GET",
|
|
84
|
+
"http://localhost/rest/V1/orders",
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
// Use headers in your API calls
|
|
88
|
+
// business logic e.g requesting orders
|
|
89
|
+
return { statusCode: 200 };
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if (error instanceof CommerceSdkValidationError) {
|
|
92
|
+
return {
|
|
93
|
+
statusCode: 400,
|
|
94
|
+
body: {
|
|
95
|
+
error: `Invalid Integration configuration: ${error.message}`,
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
throw error;
|
|
101
100
|
}
|
|
101
|
+
};
|
|
102
|
+
```
|
|
102
103
|
|
|
103
|
-
|
|
104
|
-
const headersResult = integrationsAuth.getHeaders(
|
|
105
|
-
"GET",
|
|
106
|
-
"http://localhost/rest/V1/orders",
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
if (isErr(headersResult)) {
|
|
110
|
-
const { error } = result;
|
|
111
|
-
return {
|
|
112
|
-
statusCode: 400,
|
|
113
|
-
body: {
|
|
114
|
-
error: `Unable to get auth headers for Integration Auth Provider ${error.message}`,
|
|
115
|
-
},
|
|
116
|
-
};
|
|
117
|
-
}
|
|
104
|
+
## Error Handling
|
|
118
105
|
|
|
119
|
-
|
|
106
|
+
The library uses validation to ensure all required parameters are provided and correctly formatted. When validation fails, a `CommerceSdkValidationError` is thrown with detailed information about what went wrong.
|
|
120
107
|
|
|
121
|
-
|
|
122
|
-
};
|
|
108
|
+
```typescript
|
|
109
|
+
import { CommerceSdkValidationError } from "@adobe/aio-commerce-lib-core/error";
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
assertImsAuthParams({
|
|
113
|
+
clientId: "valid-id",
|
|
114
|
+
// Missing required fields
|
|
115
|
+
});
|
|
116
|
+
} catch (error) {
|
|
117
|
+
if (error instanceof CommerceSdkValidationError) {
|
|
118
|
+
console.error(error.display());
|
|
119
|
+
// Output:
|
|
120
|
+
// Invalid ImsAuthProvider configuration
|
|
121
|
+
// ├── Schema validation error at clientSecrets → Expected at least one client secret for IMS auth
|
|
122
|
+
// ├── Schema validation error at technicalAccountId → Expected a non-empty string value for the IMS auth parameter technicalAccountId
|
|
123
|
+
// └── Schema validation error at technicalAccountEmail → Expected a valid email format for technicalAccountEmail
|
|
124
|
+
}
|
|
125
|
+
}
|
|
123
126
|
```
|
|
124
127
|
|
|
128
|
+
## Best Practices
|
|
129
|
+
|
|
130
|
+
1. **Always validate parameters** - Use the `assert*` functions before creating providers
|
|
131
|
+
2. **Handle errors gracefully** - Catch and properly handle validation and authentication errors
|
|
132
|
+
3. **Store credentials securely** - Use environment variables or secure configuration management
|
|
133
|
+
4. **Cache tokens when possible** - The IMS provider handles token lifecycle internally
|
|
134
|
+
5. **Use TypeScript** - Leverage the full type safety provided by the library
|
|
135
|
+
|
|
125
136
|
## Contributing
|
|
126
137
|
|
|
127
138
|
This package is part of the Adobe Commerce SDK monorepo. See the [Contributing Guide](https://github.com/adobe/aio-commerce-sdk/blob/main/.github/CONTRIBUTING.md) and [Development Guide](https://github.com/adobe/aio-commerce-sdk/blob/main/.github/DEVELOPMENT.md) for development setup and guidelines.
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -21,41 +21,58 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
}) : target, mod));
|
|
22
22
|
|
|
23
23
|
//#endregion
|
|
24
|
-
const
|
|
24
|
+
const __adobe_aio_commerce_lib_core_error = __toESM(require("@adobe/aio-commerce-lib-core/error"));
|
|
25
25
|
const __adobe_aio_lib_ims = __toESM(require("@adobe/aio-lib-ims"));
|
|
26
26
|
const valibot = __toESM(require("valibot"));
|
|
27
27
|
const node_crypto = __toESM(require("node:crypto"));
|
|
28
28
|
const oauth_1_0a = __toESM(require("oauth-1.0a"));
|
|
29
29
|
|
|
30
30
|
//#region source/lib/ims-auth/schema.ts
|
|
31
|
+
/**
|
|
32
|
+
* Creates a validation schema for a required IMS auth string parameter.
|
|
33
|
+
* @param name The name of the parameter for error messages.
|
|
34
|
+
* @returns A validation pipeline that ensures the parameter is a non-empty string.
|
|
35
|
+
*/
|
|
31
36
|
const imsAuthParameter = (name) => (0, valibot.pipe)((0, valibot.string)(`Expected a string value for the IMS auth parameter ${name}`), (0, valibot.nonEmpty)(`Expected a non-empty string value for the IMS auth parameter ${name}`));
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Creates a validation schema for an IMS auth string array parameter.
|
|
39
|
+
* @param name The name of the parameter for error messages.
|
|
40
|
+
* @returns A validation pipeline that ensures the parameter is an array of strings.
|
|
41
|
+
*/
|
|
42
|
+
const stringArray = (name) => {
|
|
43
|
+
return (0, valibot.pipe)((0, valibot.array)((0, valibot.string)(), `Expected a stringified JSON array value for the IMS auth parameter ${name}`));
|
|
35
44
|
};
|
|
36
45
|
/** The environments accepted by the IMS auth service. */
|
|
37
46
|
const IMS_AUTH_ENV = {
|
|
38
47
|
PROD: "prod",
|
|
39
48
|
STAGE: "stage"
|
|
40
49
|
};
|
|
50
|
+
/** Validation schema for IMS auth environment values. */
|
|
41
51
|
const ImsAuthEnvSchema = (0, valibot.enum)(IMS_AUTH_ENV);
|
|
42
52
|
/** Defines the schema to validate the necessary parameters for the IMS auth service. */
|
|
43
53
|
const ImsAuthParamsSchema = (0, valibot.object)({
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
54
|
+
clientId: imsAuthParameter("clientId"),
|
|
55
|
+
clientSecrets: (0, valibot.pipe)(stringArray("clientSecrets"), (0, valibot.minLength)(1, "Expected at least one client secret for IMS auth")),
|
|
56
|
+
technicalAccountId: imsAuthParameter("technicalAccountId"),
|
|
57
|
+
technicalAccountEmail: (0, valibot.pipe)((0, valibot.string)("Expected a string value for the IMS auth parameter technicalAccountEmail"), (0, valibot.email)("Expected a valid email format for technicalAccountEmail")),
|
|
58
|
+
imsOrgId: imsAuthParameter("imsOrgId"),
|
|
59
|
+
environment: (0, valibot.pipe)((0, valibot.optional)(ImsAuthEnvSchema, IMS_AUTH_ENV.PROD)),
|
|
60
|
+
context: (0, valibot.pipe)((0, valibot.optional)((0, valibot.string)(), "aio-commerce-sdk-creds")),
|
|
61
|
+
scopes: (0, valibot.pipe)(stringArray("scopes"), (0, valibot.minLength)(1, "Expected at least one scope for IMS auth"))
|
|
52
62
|
});
|
|
53
63
|
|
|
54
64
|
//#endregion
|
|
55
65
|
//#region source/lib/ims-auth/provider.ts
|
|
56
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Converts IMS auth configuration properties to snake_case format.
|
|
68
|
+
* @param config The IMS auth configuration with camelCase properties.
|
|
69
|
+
* @returns The configuration with snake_case properties.
|
|
70
|
+
*/
|
|
71
|
+
function toImsAuthConfig(config) {
|
|
57
72
|
return {
|
|
58
|
-
|
|
73
|
+
scopes: config.scopes,
|
|
74
|
+
env: config?.environment ?? "prod",
|
|
75
|
+
context: config.context,
|
|
59
76
|
client_id: config.clientId,
|
|
60
77
|
client_secrets: config.clientSecrets,
|
|
61
78
|
technical_account_id: config.technicalAccountId,
|
|
@@ -63,90 +80,112 @@ function snakeCaseImsAuthConfig(config) {
|
|
|
63
80
|
ims_org_id: config.imsOrgId
|
|
64
81
|
};
|
|
65
82
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
83
|
+
/**
|
|
84
|
+
* Asserts the provided configuration for an Adobe IMS authentication provider. {@link ImsAuthParams}
|
|
85
|
+
* {@link ImsAuthProvider}
|
|
86
|
+
* @param config {Record<PropertyKey, unknown>} The configuration to validate.
|
|
87
|
+
* @throws {CommerceSdkValidationError} If the configuration is invalid.
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* const config = {
|
|
91
|
+
* clientId: "your-client-id",
|
|
92
|
+
* clientSecrets: ["your-client-secret"],
|
|
93
|
+
* technicalAccountId: "your-technical-account-id",
|
|
94
|
+
* technicalAccountEmail: "your-account@example.com",
|
|
95
|
+
* imsOrgId: "your-ims-org-id@AdobeOrg",
|
|
96
|
+
* scopes: ["AdobeID", "openid"],
|
|
97
|
+
* environment: "prod", // or "stage"
|
|
98
|
+
* context: "my-app-context"
|
|
99
|
+
* };
|
|
100
|
+
*
|
|
101
|
+
* // This will validate the config and throw if invalid
|
|
102
|
+
* assertImsAuthParams(config);
|
|
103
|
+
*```
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* // Example of a failing assert:
|
|
107
|
+
* try {
|
|
108
|
+
* assertImsAuthParams({
|
|
109
|
+
* clientId: "valid-client-id",
|
|
110
|
+
* // Missing required fields like clientSecrets, technicalAccountId, etc.
|
|
111
|
+
* });
|
|
112
|
+
* } catch (error) {
|
|
113
|
+
* console.error(error.message); // "Invalid ImsAuthProvider configuration"
|
|
114
|
+
* console.error(error.issues); // Array of validation issues
|
|
115
|
+
* }
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
function assertImsAuthParams(config) {
|
|
119
|
+
const result = (0, valibot.safeParse)(ImsAuthParamsSchema, config);
|
|
120
|
+
if (!result.success) throw new __adobe_aio_commerce_lib_core_error.CommerceSdkValidationError("Invalid ImsAuthProvider configuration", { issues: result.issues });
|
|
99
121
|
}
|
|
100
122
|
/**
|
|
101
123
|
* Creates an {@link ImsAuthProvider} based on the provided configuration.
|
|
102
|
-
* @param config
|
|
124
|
+
* @param config An {@link ImsAuthParams} parameter that contains the configuration for the IMS auth provider.
|
|
103
125
|
* @returns An {@link ImsAuthProvider} instance that can be used to get access token and auth headers.
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* const config = {
|
|
129
|
+
* clientId: "your-client-id",
|
|
130
|
+
* clientSecrets: ["your-client-secret"],
|
|
131
|
+
* technicalAccountId: "your-technical-account-id",
|
|
132
|
+
* technicalAccountEmail: "your-account@example.com",
|
|
133
|
+
* imsOrgId: "your-ims-org-id@AdobeOrg",
|
|
134
|
+
* scopes: ["AdobeID", "openid"],
|
|
135
|
+
* environment: "prod",
|
|
136
|
+
* context: "my-app-context"
|
|
137
|
+
* };
|
|
138
|
+
*
|
|
139
|
+
* const authProvider = getImsAuthProvider(config);
|
|
140
|
+
*
|
|
141
|
+
* // Get access token
|
|
142
|
+
* const token = await authProvider.getAccessToken();
|
|
143
|
+
* console.log(token); // "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."
|
|
144
|
+
*
|
|
145
|
+
* // Get headers for API requests
|
|
146
|
+
* const headers = await authProvider.getHeaders();
|
|
147
|
+
* console.log(headers);
|
|
148
|
+
* // {
|
|
149
|
+
* // Authorization: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
|
|
150
|
+
* // "x-api-key": "your-client-id"
|
|
151
|
+
* // }
|
|
152
|
+
*
|
|
153
|
+
* // Use headers in API calls
|
|
154
|
+
* const response = await fetch('https://api.adobe.io/some-endpoint', {
|
|
155
|
+
* headers: await authProvider.getHeaders()
|
|
156
|
+
* });
|
|
157
|
+
* ```
|
|
104
158
|
*/
|
|
105
|
-
function getImsAuthProvider(
|
|
159
|
+
function getImsAuthProvider(authParams) {
|
|
106
160
|
const getAccessToken = async () => {
|
|
107
|
-
const
|
|
108
|
-
await __adobe_aio_lib_ims.context.set(
|
|
109
|
-
return
|
|
161
|
+
const imsAuthConfig = toImsAuthConfig(authParams);
|
|
162
|
+
await __adobe_aio_lib_ims.context.set(authParams.context, imsAuthConfig);
|
|
163
|
+
return (0, __adobe_aio_lib_ims.getToken)(authParams.context, {});
|
|
110
164
|
};
|
|
111
165
|
const getHeaders = async () => {
|
|
112
|
-
const
|
|
113
|
-
return
|
|
166
|
+
const accessToken = await getAccessToken();
|
|
167
|
+
return {
|
|
114
168
|
Authorization: `Bearer ${accessToken}`,
|
|
115
|
-
"x-api-key":
|
|
116
|
-
}
|
|
169
|
+
"x-api-key": authParams.clientId
|
|
170
|
+
};
|
|
117
171
|
};
|
|
118
172
|
return {
|
|
119
173
|
getAccessToken,
|
|
120
174
|
getHeaders
|
|
121
175
|
};
|
|
122
176
|
}
|
|
123
|
-
/**
|
|
124
|
-
* Tries to create an {@link ImsAuthProvider} based on the provided parameters.
|
|
125
|
-
* @param params The parameters required to create the IMS Auth Provider.
|
|
126
|
-
* @returns An {@link ImsAuthProvider} instance that can be used to get access token and auth headers.
|
|
127
|
-
*/
|
|
128
|
-
function tryGetImsAuthProvider(params) {
|
|
129
|
-
const validation = (0, valibot.safeParse)(ImsAuthParamsSchema, params);
|
|
130
|
-
if (!validation.success) return (0, __adobe_aio_commerce_lib_core_result.err)(makeImsAuthValidationError("Failed to validate the provided IMS parameters", validation.issues));
|
|
131
|
-
return (0, __adobe_aio_commerce_lib_core_result.ok)(getImsAuthProvider(fromParams$1(validation.output)));
|
|
132
|
-
}
|
|
133
177
|
|
|
134
178
|
//#endregion
|
|
135
179
|
//#region source/lib/integration-auth/schema.ts
|
|
136
180
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
181
|
+
* Creates a validation schema for a required Commerce Integration string parameter.
|
|
182
|
+
* @param name The name of the parameter for error messages.
|
|
183
|
+
* @returns A validation pipeline that ensures the parameter is a non-empty string.
|
|
139
184
|
*/
|
|
140
|
-
const AllowedHttpMethod = [
|
|
141
|
-
"GET",
|
|
142
|
-
"POST",
|
|
143
|
-
"PUT",
|
|
144
|
-
"PATCH",
|
|
145
|
-
"DELETE"
|
|
146
|
-
];
|
|
147
|
-
const HttpMethodSchema = (0, valibot.picklist)(AllowedHttpMethod);
|
|
148
185
|
const integrationAuthParameter = (name) => (0, valibot.pipe)((0, valibot.string)(`Expected a string value for the Commerce Integration parameter ${name}`), (0, valibot.nonEmpty)(`Expected a non-empty string value for the Commerce Integration parameter ${name}`));
|
|
186
|
+
/** Validation schema for the Adobe Commerce endpoint base URL. */
|
|
149
187
|
const BaseUrlSchema = (0, valibot.pipe)((0, valibot.string)("Expected a string for the Adobe Commerce endpoint"), (0, valibot.nonEmpty)("Expected a non-empty string for the Adobe Commerce endpoint"), (0, valibot.url)("Expected a valid url for the Adobe Commerce endpoint"));
|
|
188
|
+
/** Validation schema that accepts either a URL string or URL instance and normalizes to string. */
|
|
150
189
|
const UrlSchema = (0, valibot.pipe)((0, valibot.union)([BaseUrlSchema, (0, valibot.instance)(URL)]), (0, valibot.transform)((url) => {
|
|
151
190
|
if (url instanceof URL) return url.toString();
|
|
152
191
|
return url;
|
|
@@ -156,73 +195,98 @@ const UrlSchema = (0, valibot.pipe)((0, valibot.union)([BaseUrlSchema, (0, valib
|
|
|
156
195
|
* This is used to validate the parameters passed to the Commerce Integration provider.
|
|
157
196
|
*/
|
|
158
197
|
const IntegrationAuthParamsSchema = (0, valibot.nonOptional)((0, valibot.object)({
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
198
|
+
consumerKey: integrationAuthParameter("consumerKey"),
|
|
199
|
+
consumerSecret: integrationAuthParameter("consumerSecret"),
|
|
200
|
+
accessToken: integrationAuthParameter("accessToken"),
|
|
201
|
+
accessTokenSecret: integrationAuthParameter("accessTokenSecret")
|
|
163
202
|
}));
|
|
164
203
|
|
|
165
204
|
//#endregion
|
|
166
205
|
//#region source/lib/integration-auth/provider.ts
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
206
|
+
/**
|
|
207
|
+
* Asserts the provided configuration for an Adobe Commerce integration authentication provider. {@link IntegrationAuthParams}
|
|
208
|
+
* {@link IntegrationAuthProvider}
|
|
209
|
+
* @param config {Record<PropertyKey, unknown>} The configuration to validate.
|
|
210
|
+
* @throws {CommerceSdkValidationError} If the configuration is invalid.
|
|
211
|
+
* @example
|
|
212
|
+
* ```typescript
|
|
213
|
+
* const config = {
|
|
214
|
+
* consumerKey: "your-consumer-key",
|
|
215
|
+
* consumerSecret: "your-consumer-secret",
|
|
216
|
+
* accessToken: "your-access-token",
|
|
217
|
+
* accessTokenSecret: "your-access-token-secret"
|
|
218
|
+
* };
|
|
219
|
+
*
|
|
220
|
+
* // This will validate the config and throw if invalid
|
|
221
|
+
* assertIntegrationAuthParams(config);
|
|
222
|
+
* ```
|
|
223
|
+
* @example
|
|
224
|
+
* ```typescript
|
|
225
|
+
* // Example of a failing assert:
|
|
226
|
+
* try {
|
|
227
|
+
* assertIntegrationAuthParams({
|
|
228
|
+
* consumerKey: "valid-consumer-key",
|
|
229
|
+
* // Missing required fields like consumerSecret, accessToken, accessTokenSecret
|
|
230
|
+
* });
|
|
231
|
+
* } catch (error) {
|
|
232
|
+
* console.error(error.message); // "Invalid IntegrationAuthProvider configuration"
|
|
233
|
+
* console.error(error.issues); // Array of validation issues
|
|
234
|
+
* }
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
function assertIntegrationAuthParams(config) {
|
|
238
|
+
const result = (0, valibot.safeParse)(IntegrationAuthParamsSchema, config);
|
|
239
|
+
if (!result.success) throw new __adobe_aio_commerce_lib_core_error.CommerceSdkValidationError("Invalid IntegrationAuthProvider configuration", { issues: result.issues });
|
|
181
240
|
}
|
|
182
241
|
/**
|
|
183
242
|
* Creates an {@link IntegrationAuthProvider} based on the provided configuration.
|
|
184
|
-
* @param config The configuration for the integration.
|
|
243
|
+
* @param config {IntegrationAuthParams} The configuration for the integration.
|
|
185
244
|
* @returns An {@link IntegrationAuthProvider} instance that can be used to get auth headers.
|
|
245
|
+
* @example
|
|
246
|
+
* ```typescript
|
|
247
|
+
* const config = {
|
|
248
|
+
* consumerKey: "your-consumer-key",
|
|
249
|
+
* consumerSecret: "your-consumer-secret",
|
|
250
|
+
* accessToken: "your-access-token",
|
|
251
|
+
* accessTokenSecret: "your-access-token-secret"
|
|
252
|
+
* };
|
|
253
|
+
*
|
|
254
|
+
* const authProvider = getIntegrationAuthProvider(config);
|
|
255
|
+
*
|
|
256
|
+
* // Get OAuth headers for a REST API call
|
|
257
|
+
* const headers = authProvider.getHeaders("GET", "https://your-store.com/rest/V1/products");
|
|
258
|
+
* console.log(headers); // { Authorization: "OAuth oauth_consumer_key=..., oauth_signature=..." }
|
|
259
|
+
*
|
|
260
|
+
* // Can also be used with URL objects
|
|
261
|
+
* const url = new URL("https://your-store.com/rest/V1/customers");
|
|
262
|
+
* const postHeaders = authProvider.getHeaders("POST", url);
|
|
263
|
+
* ```
|
|
186
264
|
*/
|
|
187
|
-
function getIntegrationAuthProvider(
|
|
265
|
+
function getIntegrationAuthProvider(authParams) {
|
|
188
266
|
const oauth = new oauth_1_0a.default({
|
|
189
267
|
consumer: {
|
|
190
|
-
key:
|
|
191
|
-
secret:
|
|
268
|
+
key: authParams.consumerKey,
|
|
269
|
+
secret: authParams.consumerSecret
|
|
192
270
|
},
|
|
193
271
|
signature_method: "HMAC-SHA256",
|
|
194
272
|
hash_function: (baseString, key) => node_crypto.default.createHmac("sha256", key).update(baseString).digest("base64")
|
|
195
273
|
});
|
|
196
274
|
const oauthToken = {
|
|
197
|
-
key:
|
|
198
|
-
secret:
|
|
275
|
+
key: authParams.accessToken,
|
|
276
|
+
secret: authParams.accessTokenSecret
|
|
199
277
|
};
|
|
200
|
-
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const headers = oauth.toHeader(oauth.authorize({
|
|
205
|
-
url: finalUrl,
|
|
278
|
+
return { getHeaders: (method, url) => {
|
|
279
|
+
const urlString = url instanceof URL ? url.toString() : url;
|
|
280
|
+
return oauth.toHeader(oauth.authorize({
|
|
281
|
+
url: urlString,
|
|
206
282
|
method
|
|
207
283
|
}, oauthToken));
|
|
208
|
-
|
|
209
|
-
};
|
|
210
|
-
return { getHeaders };
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Tries to create an {@link IntegrationAuthProvider} based on the provided parameters.
|
|
214
|
-
* @param params The parameters required for integration authentication.
|
|
215
|
-
* @returns An {@link IntegrationAuthProvider} instance that can be used to get auth headers.
|
|
216
|
-
*/
|
|
217
|
-
function tryGetIntegrationAuthProvider(params) {
|
|
218
|
-
const validation = (0, valibot.safeParse)(IntegrationAuthParamsSchema, params);
|
|
219
|
-
if (!validation.success) return (0, __adobe_aio_commerce_lib_core_result.err)(makeIntegrationAuthValidationError("Failed to validate the provided integration parameters", validation.issues));
|
|
220
|
-
return (0, __adobe_aio_commerce_lib_core_result.ok)(getIntegrationAuthProvider(fromParams(validation.output)));
|
|
284
|
+
} };
|
|
221
285
|
}
|
|
222
286
|
|
|
223
287
|
//#endregion
|
|
224
288
|
exports.IMS_AUTH_ENV = IMS_AUTH_ENV;
|
|
289
|
+
exports.assertImsAuthParams = assertImsAuthParams;
|
|
290
|
+
exports.assertIntegrationAuthParams = assertIntegrationAuthParams;
|
|
225
291
|
exports.getImsAuthProvider = getImsAuthProvider;
|
|
226
|
-
exports.getIntegrationAuthProvider = getIntegrationAuthProvider;
|
|
227
|
-
exports.tryGetImsAuthProvider = tryGetImsAuthProvider;
|
|
228
|
-
exports.tryGetIntegrationAuthProvider = tryGetIntegrationAuthProvider;
|
|
292
|
+
exports.getIntegrationAuthProvider = getIntegrationAuthProvider;
|