@corti/sdk 0.5.0 → 0.6.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/README.md +14 -2
- package/dist/cjs/Client.d.ts +1 -1
- package/dist/cjs/Client.js +2 -2
- package/dist/cjs/api/resources/auth/client/Client.d.ts +2 -2
- package/dist/cjs/api/resources/auth/client/Client.js +2 -2
- package/dist/cjs/api/resources/auth/client/requests/AuthGetTokenRequest.d.ts +4 -3
- package/dist/cjs/core/auth/OAuthTokenProvider.d.ts +1 -1
- package/dist/cjs/custom/CortiAuth.d.ts +48 -5
- package/dist/cjs/custom/CortiAuth.js +55 -20
- package/dist/cjs/custom/CortiSDKError.d.ts +12 -0
- package/dist/cjs/custom/CortiSDKError.js +19 -0
- package/dist/cjs/custom/utils/localStorage.d.ts +4 -0
- package/dist/cjs/custom/utils/localStorage.js +38 -0
- package/dist/cjs/custom/utils/pkce.d.ts +2 -0
- package/dist/cjs/custom/utils/pkce.js +32 -0
- package/dist/cjs/custom/utils/tokenRequest.d.ts +11 -0
- package/dist/cjs/custom/utils/tokenRequest.js +76 -0
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/index.js +6 -1
- package/dist/cjs/serialization/resources/auth/client/requests/AuthGetTokenRequest.d.ts +1 -1
- package/dist/cjs/serialization/resources/auth/client/requests/AuthGetTokenRequest.js +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/Client.d.mts +1 -1
- package/dist/esm/Client.mjs +2 -2
- package/dist/esm/api/resources/auth/client/Client.d.mts +2 -2
- package/dist/esm/api/resources/auth/client/Client.mjs +2 -2
- package/dist/esm/api/resources/auth/client/requests/AuthGetTokenRequest.d.mts +4 -3
- package/dist/esm/core/auth/OAuthTokenProvider.d.mts +1 -1
- package/dist/esm/custom/CortiAuth.d.mts +48 -5
- package/dist/esm/custom/CortiAuth.mjs +55 -20
- package/dist/esm/custom/CortiSDKError.d.mts +12 -0
- package/dist/esm/custom/CortiSDKError.mjs +15 -0
- package/dist/esm/custom/utils/localStorage.d.mts +4 -0
- package/dist/esm/custom/utils/localStorage.mjs +32 -0
- package/dist/esm/custom/utils/pkce.d.mts +2 -0
- package/dist/esm/custom/utils/pkce.mjs +27 -0
- package/dist/esm/custom/utils/tokenRequest.d.mts +11 -0
- package/dist/esm/custom/utils/tokenRequest.mjs +39 -0
- package/dist/esm/index.d.mts +4 -0
- package/dist/esm/index.mjs +4 -0
- package/dist/esm/serialization/resources/auth/client/requests/AuthGetTokenRequest.d.mts +1 -1
- package/dist/esm/serialization/resources/auth/client/requests/AuthGetTokenRequest.mjs +1 -1
- package/dist/esm/version.d.mts +1 -1
- package/dist/esm/version.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -60,7 +60,10 @@ const client = new CortiClient({
|
|
|
60
60
|
},
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
-
// For user authentication, you can
|
|
63
|
+
// For user authentication, you can use:
|
|
64
|
+
// - Authorization Code Flow
|
|
65
|
+
// - Authorization Code Flow with PKCE
|
|
66
|
+
// - Resource Owner Password Credentials (ROPC) flow
|
|
64
67
|
// See the Authentication Guide for detailed instructions
|
|
65
68
|
|
|
66
69
|
await client.interactions.create({
|
|
@@ -92,11 +95,12 @@ Depending on the type of error, the SDK will throw one of the following:
|
|
|
92
95
|
- **CortiError**: Thrown when the API returns a non-success status code (4xx or 5xx response). This is the base error for API-related issues.
|
|
93
96
|
- **ParseError**: Thrown when parsing input data fails schema validation. This typically occurs when the data you provide does not match the expected schema.
|
|
94
97
|
- **JsonError**: Thrown when serializing data to JSON fails schema validation. This typically occurs when converting parsed data to JSON for transmission or storage fails validation.
|
|
98
|
+
- **CortiSDKError**: Base class for SDK-specific runtime issues (e.g., internal helpers, environment detection). Provides an optional `code` and `cause` for debugging.
|
|
95
99
|
|
|
96
100
|
Example usage:
|
|
97
101
|
|
|
98
102
|
```typescript
|
|
99
|
-
import { CortiError, ParseError, JsonError } from "@corti/sdk";
|
|
103
|
+
import { CortiError, ParseError, JsonError, CortiSDKError } from "@corti/sdk";
|
|
100
104
|
|
|
101
105
|
try {
|
|
102
106
|
await client.interactions.create(...);
|
|
@@ -116,6 +120,14 @@ try {
|
|
|
116
120
|
// Handle schema validation errors during serialization
|
|
117
121
|
console.error("JSON validation error details:", err.errors);
|
|
118
122
|
}
|
|
123
|
+
if (err instanceof CortiSDKError) {
|
|
124
|
+
// Handle other SDK-level errors that expose extra context
|
|
125
|
+
console.error("SDK error code:", err.code);
|
|
126
|
+
console.error("SDK error cause:", err.cause);
|
|
127
|
+
if (err.code === "local_storage_error") {
|
|
128
|
+
console.error("LocalStorage operation failed:", err.message);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
119
131
|
}
|
|
120
132
|
```
|
|
121
133
|
|
package/dist/cjs/Client.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export declare namespace CortiClient {
|
|
|
19
19
|
/** Specify a custom URL to connect the client to. */
|
|
20
20
|
baseUrl?: core.Supplier<string>;
|
|
21
21
|
clientId: core.Supplier<string>;
|
|
22
|
-
clientSecret: core.Supplier<string>;
|
|
22
|
+
clientSecret: core.Supplier<string | undefined>;
|
|
23
23
|
/** Override the Tenant-Name header */
|
|
24
24
|
tenantName: core.Supplier<string>;
|
|
25
25
|
/** Additional headers to include in requests. */
|
package/dist/cjs/Client.js
CHANGED
|
@@ -64,8 +64,8 @@ class CortiClient {
|
|
|
64
64
|
"Tenant-Name": _options === null || _options === void 0 ? void 0 : _options.tenantName,
|
|
65
65
|
"X-Fern-Language": "JavaScript",
|
|
66
66
|
"X-Fern-SDK-Name": "@corti/sdk",
|
|
67
|
-
"X-Fern-SDK-Version": "0.
|
|
68
|
-
"User-Agent": "@corti/sdk/0.
|
|
67
|
+
"X-Fern-SDK-Version": "0.6.0",
|
|
68
|
+
"User-Agent": "@corti/sdk/0.6.0",
|
|
69
69
|
"X-Fern-Runtime": core.RUNTIME.type,
|
|
70
70
|
"X-Fern-Runtime-Version": core.RUNTIME.version,
|
|
71
71
|
}, _options === null || _options === void 0 ? void 0 : _options.headers) });
|
|
@@ -39,8 +39,8 @@ export declare class Auth {
|
|
|
39
39
|
*
|
|
40
40
|
* @example
|
|
41
41
|
* await client.auth.getToken({
|
|
42
|
-
* clientId: "
|
|
43
|
-
* clientSecret: "
|
|
42
|
+
* clientId: "client_id_123",
|
|
43
|
+
* clientSecret: "my_secret_value"
|
|
44
44
|
* })
|
|
45
45
|
*/
|
|
46
46
|
getToken(request: Corti.AuthGetTokenRequest, requestOptions?: Auth.RequestOptions): core.HttpResponsePromise<Corti.GetTokenResponse>;
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* @example
|
|
6
6
|
* {
|
|
7
|
-
* clientId: "
|
|
8
|
-
* clientSecret: "
|
|
7
|
+
* clientId: "client_id_123",
|
|
8
|
+
* clientSecret: "my_secret_value"
|
|
9
9
|
* }
|
|
10
10
|
*/
|
|
11
11
|
export interface AuthGetTokenRequest {
|
|
12
12
|
clientId: string;
|
|
13
|
-
|
|
13
|
+
/** Optional secret for confidential clients and Authorization code flow */
|
|
14
|
+
clientSecret?: string;
|
|
14
15
|
}
|
|
@@ -16,7 +16,7 @@ export declare class OAuthTokenProvider {
|
|
|
16
16
|
private _expiresAt;
|
|
17
17
|
constructor({ clientId, clientSecret, authClient, }: {
|
|
18
18
|
clientId: core.Supplier<string>;
|
|
19
|
-
clientSecret: core.Supplier<string>;
|
|
19
|
+
clientSecret: core.Supplier<string | undefined>;
|
|
20
20
|
authClient: Auth;
|
|
21
21
|
});
|
|
22
22
|
getToken(): Promise<string>;
|
|
@@ -15,20 +15,47 @@ import { Auth as FernAuth } from "../api/resources/auth/client/Client.js";
|
|
|
15
15
|
import * as core from "../core/index.js";
|
|
16
16
|
import * as Corti from "../api/index.js";
|
|
17
17
|
import * as environments from "../environments.js";
|
|
18
|
+
/**
|
|
19
|
+
* Patch: added codeChallenge to the AuthorizationCodeClient interface to support PKCE flow
|
|
20
|
+
*/
|
|
18
21
|
interface AuthorizationCodeClient {
|
|
19
22
|
clientId: string;
|
|
20
23
|
redirectUri: string;
|
|
24
|
+
codeChallenge?: string;
|
|
21
25
|
}
|
|
22
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Patch: renamed AuthorizationCodeClient to AuthorizationCode as it can be used for both(server and client) flows
|
|
28
|
+
*/
|
|
29
|
+
interface AuthorizationCode {
|
|
23
30
|
clientId: string;
|
|
24
31
|
clientSecret: string;
|
|
25
32
|
redirectUri: string;
|
|
26
33
|
code: string;
|
|
27
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Patch: added type for AuthorizationPkce request
|
|
37
|
+
*/
|
|
38
|
+
interface AuthorizationPkce {
|
|
39
|
+
clientId: string;
|
|
40
|
+
redirectUri: string;
|
|
41
|
+
code: string;
|
|
42
|
+
codeVerifier?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Patch: added type for AuthorizationRopc request
|
|
46
|
+
*/
|
|
47
|
+
interface AuthorizationRopcServer {
|
|
48
|
+
clientId: string;
|
|
49
|
+
username: string;
|
|
50
|
+
password: string;
|
|
51
|
+
}
|
|
28
52
|
interface AuthorizationRefreshServer {
|
|
29
53
|
clientId: string;
|
|
30
54
|
clientSecret: string;
|
|
31
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Patch: added optional refreshToken for ROPC and PKCE flow
|
|
57
|
+
*/
|
|
58
|
+
refreshToken?: string;
|
|
32
59
|
}
|
|
33
60
|
interface Options {
|
|
34
61
|
skipRedirect?: boolean;
|
|
@@ -41,18 +68,34 @@ export declare class Auth extends FernAuth {
|
|
|
41
68
|
* Patch: use custom AuthOptions type to support string-based environment
|
|
42
69
|
*/
|
|
43
70
|
constructor(_options: AuthOptions);
|
|
71
|
+
/**
|
|
72
|
+
* Patch: Generate PKCE authorization URL with automatic code verifier generation
|
|
73
|
+
*/
|
|
74
|
+
authorizePkceUrl({ clientId, redirectUri, }: AuthorizationCodeClient, options?: Options): Promise<string>;
|
|
75
|
+
/**
|
|
76
|
+
* Patch: Get the stored PKCE code verifier
|
|
77
|
+
*/
|
|
78
|
+
getCodeVerifier(): string | null;
|
|
44
79
|
/**
|
|
45
80
|
* Patch: called custom implementation this.__getToken_custom instead of this.__getToken
|
|
46
81
|
*/
|
|
47
82
|
getToken(request: Corti.AuthGetTokenRequest, requestOptions?: FernAuth.RequestOptions): core.HttpResponsePromise<Corti.GetTokenResponse>;
|
|
48
83
|
/**
|
|
49
|
-
* Patch: added method to get Authorization URL for Authorization code flow
|
|
84
|
+
* Patch: added method to get Authorization URL for Authorization code flow and PKCE flow
|
|
50
85
|
*/
|
|
51
|
-
authorizeURL({ clientId, redirectUri, }: AuthorizationCodeClient, options?: Options): Promise<string>;
|
|
86
|
+
authorizeURL({ clientId, redirectUri, codeChallenge, }: AuthorizationCodeClient, options?: Options): Promise<string>;
|
|
52
87
|
/**
|
|
53
88
|
* Patch: calls __getToken_custom with additional fields to support Authorization code flow
|
|
54
89
|
*/
|
|
55
|
-
getCodeFlowToken(request:
|
|
90
|
+
getCodeFlowToken(request: AuthorizationCode, requestOptions?: FernAuth.RequestOptions): core.HttpResponsePromise<Corti.GetTokenResponse>;
|
|
91
|
+
/**
|
|
92
|
+
* Patch: PKCE-specific method
|
|
93
|
+
*/
|
|
94
|
+
getPkceFlowToken(request: AuthorizationPkce, requestOptions?: FernAuth.RequestOptions): core.HttpResponsePromise<Corti.GetTokenResponse>;
|
|
95
|
+
/**
|
|
96
|
+
* Patch: ROPC-specific method
|
|
97
|
+
*/
|
|
98
|
+
getRopcFlowToken(request: AuthorizationRopcServer, requestOptions?: FernAuth.RequestOptions): core.HttpResponsePromise<Corti.GetTokenResponse>;
|
|
56
99
|
/**
|
|
57
100
|
* Patch: copy of this.__getToken with patches
|
|
58
101
|
*/
|
|
@@ -62,6 +62,11 @@ const headers_js_1 = require("../core/headers.js");
|
|
|
62
62
|
const serializers = __importStar(require("../serialization/index.js"));
|
|
63
63
|
const errors = __importStar(require("../errors/index.js"));
|
|
64
64
|
const getEnvironmentFromString_js_1 = require("./utils/getEnvironmentFromString.js");
|
|
65
|
+
const ParseError_js_1 = require("../core/schemas/builders/schema-utils/ParseError.js");
|
|
66
|
+
const localStorage_js_1 = require("./utils/localStorage.js");
|
|
67
|
+
const pkce_js_1 = require("./utils/pkce.js");
|
|
68
|
+
const tokenRequest_js_1 = require("./utils/tokenRequest.js");
|
|
69
|
+
const CODE_VERIFIER_KEY = "corti_js_sdk_code_verifier";
|
|
65
70
|
class Auth extends Client_js_1.Auth {
|
|
66
71
|
/**
|
|
67
72
|
* Patch: use custom AuthOptions type to support string-based environment
|
|
@@ -69,6 +74,27 @@ class Auth extends Client_js_1.Auth {
|
|
|
69
74
|
constructor(_options) {
|
|
70
75
|
super(Object.assign(Object.assign({}, _options), { environment: (0, getEnvironmentFromString_js_1.getEnvironment)(_options.environment) }));
|
|
71
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Patch: Generate PKCE authorization URL with automatic code verifier generation
|
|
79
|
+
*/
|
|
80
|
+
authorizePkceUrl(_a, options_1) {
|
|
81
|
+
return __awaiter(this, arguments, void 0, function* ({ clientId, redirectUri, }, options) {
|
|
82
|
+
const codeVerifier = (0, pkce_js_1.generateCodeVerifier)();
|
|
83
|
+
(0, localStorage_js_1.setLocalStorageItem)(CODE_VERIFIER_KEY, codeVerifier);
|
|
84
|
+
const codeChallenge = yield (0, pkce_js_1.generateCodeChallenge)(codeVerifier);
|
|
85
|
+
return this.authorizeURL({
|
|
86
|
+
clientId,
|
|
87
|
+
redirectUri,
|
|
88
|
+
codeChallenge,
|
|
89
|
+
}, options);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Patch: Get the stored PKCE code verifier
|
|
94
|
+
*/
|
|
95
|
+
getCodeVerifier() {
|
|
96
|
+
return (0, localStorage_js_1.getLocalStorageItem)(CODE_VERIFIER_KEY);
|
|
97
|
+
}
|
|
72
98
|
/**
|
|
73
99
|
* Patch: called custom implementation this.__getToken_custom instead of this.__getToken
|
|
74
100
|
*/
|
|
@@ -76,10 +102,10 @@ class Auth extends Client_js_1.Auth {
|
|
|
76
102
|
return core.HttpResponsePromise.fromPromise(this.__getToken_custom(request, requestOptions));
|
|
77
103
|
}
|
|
78
104
|
/**
|
|
79
|
-
* Patch: added method to get Authorization URL for Authorization code flow
|
|
105
|
+
* Patch: added method to get Authorization URL for Authorization code flow and PKCE flow
|
|
80
106
|
*/
|
|
81
107
|
authorizeURL(_a, options_1) {
|
|
82
|
-
return __awaiter(this, arguments, void 0, function* ({ clientId, redirectUri, }, options) {
|
|
108
|
+
return __awaiter(this, arguments, void 0, function* ({ clientId, redirectUri, codeChallenge, }, options) {
|
|
83
109
|
var _b;
|
|
84
110
|
const authUrl = new URL(core.url.join((_b = (yield core.Supplier.get(this._options.baseUrl))) !== null && _b !== void 0 ? _b : (yield core.Supplier.get(this._options.environment)).login, yield core.Supplier.get(this._options.tenantName), "protocol/openid-connect/auth"));
|
|
85
111
|
authUrl.searchParams.set('response_type', 'code');
|
|
@@ -90,6 +116,10 @@ class Auth extends Client_js_1.Auth {
|
|
|
90
116
|
if (redirectUri !== undefined) {
|
|
91
117
|
authUrl.searchParams.set('redirect_uri', redirectUri);
|
|
92
118
|
}
|
|
119
|
+
if (codeChallenge !== undefined) {
|
|
120
|
+
authUrl.searchParams.set('code_challenge', codeChallenge);
|
|
121
|
+
authUrl.searchParams.set('code_challenge_method', 'S256');
|
|
122
|
+
}
|
|
93
123
|
const authUrlString = authUrl.toString();
|
|
94
124
|
if (typeof window !== "undefined" && !(options === null || options === void 0 ? void 0 : options.skipRedirect)) {
|
|
95
125
|
window.location.href = authUrlString;
|
|
@@ -104,12 +134,33 @@ class Auth extends Client_js_1.Auth {
|
|
|
104
134
|
getCodeFlowToken(request, requestOptions) {
|
|
105
135
|
return core.HttpResponsePromise.fromPromise(this.__getToken_custom(Object.assign(Object.assign({}, request), { grantType: "authorization_code" }), requestOptions));
|
|
106
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Patch: PKCE-specific method
|
|
139
|
+
*/
|
|
140
|
+
getPkceFlowToken(request, requestOptions) {
|
|
141
|
+
const codeVerifier = request.codeVerifier || this.getCodeVerifier();
|
|
142
|
+
if (!codeVerifier) {
|
|
143
|
+
throw new ParseError_js_1.ParseError([
|
|
144
|
+
{
|
|
145
|
+
path: ['codeVerifier'],
|
|
146
|
+
message: 'Code verifier was not provided and not found in localStorage.',
|
|
147
|
+
},
|
|
148
|
+
]);
|
|
149
|
+
}
|
|
150
|
+
return core.HttpResponsePromise.fromPromise(this.__getToken_custom(Object.assign(Object.assign({}, request), { codeVerifier: codeVerifier, grantType: "authorization_code" }), requestOptions));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Patch: ROPC-specific method
|
|
154
|
+
*/
|
|
155
|
+
getRopcFlowToken(request, requestOptions) {
|
|
156
|
+
return core.HttpResponsePromise.fromPromise(this.__getToken_custom(Object.assign(Object.assign({}, request), { grantType: "password" }), requestOptions));
|
|
157
|
+
}
|
|
107
158
|
/**
|
|
108
159
|
* Patch: copy of this.__getToken with patches
|
|
109
160
|
*/
|
|
110
161
|
__getToken_custom(
|
|
111
162
|
/**
|
|
112
|
-
* Patch: added additional fields to request to support Authorization
|
|
163
|
+
* Patch: added additional fields to request to support Authorization PKCE and ROPC flow
|
|
113
164
|
*/
|
|
114
165
|
request, requestOptions) {
|
|
115
166
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -132,23 +183,7 @@ class Auth extends Client_js_1.Auth {
|
|
|
132
183
|
/**
|
|
133
184
|
* Patch: removed `requestType: "json"`, made body a URLSearchParams object
|
|
134
185
|
*/
|
|
135
|
-
body:
|
|
136
|
-
unrecognizedObjectKeys: "strip",
|
|
137
|
-
omitUndefined: true,
|
|
138
|
-
})), { scope: "openid",
|
|
139
|
-
/**
|
|
140
|
-
* Patch: `grant_type` uses values from request or defaults to "client_credentials"
|
|
141
|
-
*/
|
|
142
|
-
grant_type: request.grantType || "client_credentials" }), (request.grantType === "authorization_code"
|
|
143
|
-
? {
|
|
144
|
-
code: request.code,
|
|
145
|
-
redirect_uri: request.redirectUri
|
|
146
|
-
}
|
|
147
|
-
: {})), (request.grantType === "refresh_token"
|
|
148
|
-
? {
|
|
149
|
-
refresh_token: request.refreshToken,
|
|
150
|
-
}
|
|
151
|
-
: {}))),
|
|
186
|
+
body: (0, tokenRequest_js_1.buildTokenRequestBody)(request),
|
|
152
187
|
timeoutMs: (requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.timeoutInSeconds) != null ? requestOptions.timeoutInSeconds * 1000 : 60000,
|
|
153
188
|
maxRetries: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries,
|
|
154
189
|
abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface CortiSDKErrorOptions {
|
|
2
|
+
code: CortiSDKErrorCodes;
|
|
3
|
+
cause?: unknown;
|
|
4
|
+
}
|
|
5
|
+
export declare enum CortiSDKErrorCodes {
|
|
6
|
+
LOCAL_STORAGE_ERROR = "local_storage_error"
|
|
7
|
+
}
|
|
8
|
+
export declare class CortiSDKError extends Error {
|
|
9
|
+
readonly code: CortiSDKErrorCodes;
|
|
10
|
+
readonly cause?: unknown;
|
|
11
|
+
constructor(message?: string, options?: CortiSDKErrorOptions);
|
|
12
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CortiSDKError = exports.CortiSDKErrorCodes = void 0;
|
|
4
|
+
var CortiSDKErrorCodes;
|
|
5
|
+
(function (CortiSDKErrorCodes) {
|
|
6
|
+
CortiSDKErrorCodes["LOCAL_STORAGE_ERROR"] = "local_storage_error";
|
|
7
|
+
})(CortiSDKErrorCodes || (exports.CortiSDKErrorCodes = CortiSDKErrorCodes = {}));
|
|
8
|
+
class CortiSDKError extends Error {
|
|
9
|
+
constructor(message = "An unexpected error occurred in the Corti SDK.", options = { code: CortiSDKErrorCodes.LOCAL_STORAGE_ERROR }) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "CortiSDKError";
|
|
12
|
+
this.code = options.code;
|
|
13
|
+
if ("cause" in options) {
|
|
14
|
+
this.cause = options.cause;
|
|
15
|
+
}
|
|
16
|
+
Object.setPrototypeOf(this, CortiSDKError.prototype);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.CortiSDKError = CortiSDKError;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const LOCAL_STORAGE_ERROR_CODE: "local_storage_error";
|
|
2
|
+
export declare const requireLocalStorage: () => Storage;
|
|
3
|
+
export declare const setLocalStorageItem: (key: string, value: string) => void;
|
|
4
|
+
export declare const getLocalStorageItem: (key: string) => string | null;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getLocalStorageItem = exports.setLocalStorageItem = exports.requireLocalStorage = exports.LOCAL_STORAGE_ERROR_CODE = void 0;
|
|
4
|
+
const CortiSDKError_js_1 = require("../CortiSDKError.js");
|
|
5
|
+
exports.LOCAL_STORAGE_ERROR_CODE = "local_storage_error";
|
|
6
|
+
const requireLocalStorage = () => {
|
|
7
|
+
if (typeof window === "undefined" || !window.localStorage) {
|
|
8
|
+
throw new CortiSDKError_js_1.CortiSDKError("LocalStorage operation failed: storage is not available in this environment.", { code: CortiSDKError_js_1.CortiSDKErrorCodes.LOCAL_STORAGE_ERROR });
|
|
9
|
+
}
|
|
10
|
+
return window.localStorage;
|
|
11
|
+
};
|
|
12
|
+
exports.requireLocalStorage = requireLocalStorage;
|
|
13
|
+
const setLocalStorageItem = (key, value) => {
|
|
14
|
+
const storage = (0, exports.requireLocalStorage)();
|
|
15
|
+
try {
|
|
16
|
+
storage.setItem(key, value);
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
throw new CortiSDKError_js_1.CortiSDKError("LocalStorage set operation failed.", {
|
|
20
|
+
code: CortiSDKError_js_1.CortiSDKErrorCodes.LOCAL_STORAGE_ERROR,
|
|
21
|
+
cause: error,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
exports.setLocalStorageItem = setLocalStorageItem;
|
|
26
|
+
const getLocalStorageItem = (key) => {
|
|
27
|
+
const storage = (0, exports.requireLocalStorage)();
|
|
28
|
+
try {
|
|
29
|
+
return storage.getItem(key);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
throw new CortiSDKError_js_1.CortiSDKError("LocalStorage get operation failed.", {
|
|
33
|
+
code: CortiSDKError_js_1.CortiSDKErrorCodes.LOCAL_STORAGE_ERROR,
|
|
34
|
+
cause: error,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
exports.getLocalStorageItem = getLocalStorageItem;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.generateCodeChallenge = exports.generateCodeVerifier = void 0;
|
|
13
|
+
const base64URLEncode = (buffer) => {
|
|
14
|
+
const base64 = btoa(String.fromCharCode(...buffer));
|
|
15
|
+
return base64
|
|
16
|
+
.replace(/\+/g, '-')
|
|
17
|
+
.replace(/\//g, '_')
|
|
18
|
+
.replace(/=/g, '');
|
|
19
|
+
};
|
|
20
|
+
const generateCodeVerifier = () => {
|
|
21
|
+
const array = new Uint8Array(32);
|
|
22
|
+
crypto.getRandomValues(array);
|
|
23
|
+
return base64URLEncode(array);
|
|
24
|
+
};
|
|
25
|
+
exports.generateCodeVerifier = generateCodeVerifier;
|
|
26
|
+
const generateCodeChallenge = (verifier) => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
const encoder = new TextEncoder();
|
|
28
|
+
const data = encoder.encode(verifier);
|
|
29
|
+
const hash = yield crypto.subtle.digest('SHA-256', data);
|
|
30
|
+
return base64URLEncode(new Uint8Array(hash));
|
|
31
|
+
});
|
|
32
|
+
exports.generateCodeChallenge = generateCodeChallenge;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as Corti from "../../api/index.js";
|
|
2
|
+
export type TokenRequest = Corti.AuthGetTokenRequest & Partial<{
|
|
3
|
+
grantType: "client_credentials" | "authorization_code" | "refresh_token" | "password";
|
|
4
|
+
code: string;
|
|
5
|
+
redirectUri: string;
|
|
6
|
+
refreshToken: string;
|
|
7
|
+
codeVerifier: string;
|
|
8
|
+
username: string;
|
|
9
|
+
password: string;
|
|
10
|
+
}>;
|
|
11
|
+
export declare const buildTokenRequestBody: (request: TokenRequest) => URLSearchParams;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.buildTokenRequestBody = void 0;
|
|
37
|
+
const serializers = __importStar(require("../../serialization/index.js"));
|
|
38
|
+
const buildTokenRequestBody = (request) => {
|
|
39
|
+
const serializedRequest = serializers.AuthGetTokenRequest.jsonOrThrow(request, {
|
|
40
|
+
unrecognizedObjectKeys: "strip",
|
|
41
|
+
omitUndefined: true,
|
|
42
|
+
});
|
|
43
|
+
const tokenRequestBody = {
|
|
44
|
+
scope: "openid",
|
|
45
|
+
grant_type: request.grantType || "client_credentials",
|
|
46
|
+
};
|
|
47
|
+
Object.entries(serializedRequest).forEach(([key, value]) => {
|
|
48
|
+
if (value != null) {
|
|
49
|
+
tokenRequestBody[key] = String(value);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
if (request.grantType === "authorization_code") {
|
|
53
|
+
if (request.code != null) {
|
|
54
|
+
tokenRequestBody.code = request.code;
|
|
55
|
+
}
|
|
56
|
+
if (request.redirectUri != null) {
|
|
57
|
+
tokenRequestBody.redirect_uri = request.redirectUri;
|
|
58
|
+
}
|
|
59
|
+
if (request.codeVerifier != null) {
|
|
60
|
+
tokenRequestBody.code_verifier = request.codeVerifier;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (request.grantType === "refresh_token" && request.refreshToken != null) {
|
|
64
|
+
tokenRequestBody.refresh_token = request.refreshToken;
|
|
65
|
+
}
|
|
66
|
+
if (request.grantType === "password") {
|
|
67
|
+
if (request.username != null) {
|
|
68
|
+
tokenRequestBody.username = request.username;
|
|
69
|
+
}
|
|
70
|
+
if (request.password != null) {
|
|
71
|
+
tokenRequestBody.password = request.password;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return new URLSearchParams(tokenRequestBody);
|
|
75
|
+
};
|
|
76
|
+
exports.buildTokenRequestBody = buildTokenRequestBody;
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -15,3 +15,7 @@ export { Auth as CortiAuth } from "./custom/CortiAuth.js";
|
|
|
15
15
|
*/
|
|
16
16
|
export { JsonError } from "./core/schemas/builders/schema-utils/JsonError.js";
|
|
17
17
|
export { ParseError } from "./core/schemas/builders/schema-utils/ParseError.js";
|
|
18
|
+
/**
|
|
19
|
+
* Patch: added new export to provide SDK-level error handling.
|
|
20
|
+
*/
|
|
21
|
+
export { CortiSDKError } from "./custom/CortiSDKError.js";
|
package/dist/cjs/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.ParseError = exports.JsonError = exports.CortiAuth = exports.CortiEnvironment = exports.CortiClient = exports.serialization = exports.CortiTimeoutError = exports.CortiError = exports.Corti = void 0;
|
|
36
|
+
exports.CortiSDKError = exports.ParseError = exports.JsonError = exports.CortiAuth = exports.CortiEnvironment = exports.CortiClient = exports.serialization = exports.CortiTimeoutError = exports.CortiError = exports.Corti = void 0;
|
|
37
37
|
exports.Corti = __importStar(require("./api/index.js"));
|
|
38
38
|
var index_js_1 = require("./errors/index.js");
|
|
39
39
|
Object.defineProperty(exports, "CortiError", { enumerable: true, get: function () { return index_js_1.CortiError; } });
|
|
@@ -58,3 +58,8 @@ var JsonError_js_1 = require("./core/schemas/builders/schema-utils/JsonError.js"
|
|
|
58
58
|
Object.defineProperty(exports, "JsonError", { enumerable: true, get: function () { return JsonError_js_1.JsonError; } });
|
|
59
59
|
var ParseError_js_1 = require("./core/schemas/builders/schema-utils/ParseError.js");
|
|
60
60
|
Object.defineProperty(exports, "ParseError", { enumerable: true, get: function () { return ParseError_js_1.ParseError; } });
|
|
61
|
+
/**
|
|
62
|
+
* Patch: added new export to provide SDK-level error handling.
|
|
63
|
+
*/
|
|
64
|
+
var CortiSDKError_js_1 = require("./custom/CortiSDKError.js");
|
|
65
|
+
Object.defineProperty(exports, "CortiSDKError", { enumerable: true, get: function () { return CortiSDKError_js_1.CortiSDKError; } });
|
|
@@ -40,5 +40,5 @@ exports.AuthGetTokenRequest = void 0;
|
|
|
40
40
|
const core = __importStar(require("../../../../../core/index.js"));
|
|
41
41
|
exports.AuthGetTokenRequest = core.serialization.object({
|
|
42
42
|
clientId: core.serialization.property("client_id", core.serialization.string()),
|
|
43
|
-
clientSecret: core.serialization.property("client_secret", core.serialization.string()),
|
|
43
|
+
clientSecret: core.serialization.property("client_secret", core.serialization.string().optional()),
|
|
44
44
|
});
|
package/dist/cjs/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "0.
|
|
1
|
+
export declare const SDK_VERSION = "0.6.0";
|
package/dist/cjs/version.js
CHANGED
package/dist/esm/Client.d.mts
CHANGED
|
@@ -19,7 +19,7 @@ export declare namespace CortiClient {
|
|
|
19
19
|
/** Specify a custom URL to connect the client to. */
|
|
20
20
|
baseUrl?: core.Supplier<string>;
|
|
21
21
|
clientId: core.Supplier<string>;
|
|
22
|
-
clientSecret: core.Supplier<string>;
|
|
22
|
+
clientSecret: core.Supplier<string | undefined>;
|
|
23
23
|
/** Override the Tenant-Name header */
|
|
24
24
|
tenantName: core.Supplier<string>;
|
|
25
25
|
/** Additional headers to include in requests. */
|
package/dist/esm/Client.mjs
CHANGED
|
@@ -28,8 +28,8 @@ export class CortiClient {
|
|
|
28
28
|
"Tenant-Name": _options === null || _options === void 0 ? void 0 : _options.tenantName,
|
|
29
29
|
"X-Fern-Language": "JavaScript",
|
|
30
30
|
"X-Fern-SDK-Name": "@corti/sdk",
|
|
31
|
-
"X-Fern-SDK-Version": "0.
|
|
32
|
-
"User-Agent": "@corti/sdk/0.
|
|
31
|
+
"X-Fern-SDK-Version": "0.6.0",
|
|
32
|
+
"User-Agent": "@corti/sdk/0.6.0",
|
|
33
33
|
"X-Fern-Runtime": core.RUNTIME.type,
|
|
34
34
|
"X-Fern-Runtime-Version": core.RUNTIME.version,
|
|
35
35
|
}, _options === null || _options === void 0 ? void 0 : _options.headers) });
|
|
@@ -39,8 +39,8 @@ export declare class Auth {
|
|
|
39
39
|
*
|
|
40
40
|
* @example
|
|
41
41
|
* await client.auth.getToken({
|
|
42
|
-
* clientId: "
|
|
43
|
-
* clientSecret: "
|
|
42
|
+
* clientId: "client_id_123",
|
|
43
|
+
* clientSecret: "my_secret_value"
|
|
44
44
|
* })
|
|
45
45
|
*/
|
|
46
46
|
getToken(request: Corti.AuthGetTokenRequest, requestOptions?: Auth.RequestOptions): core.HttpResponsePromise<Corti.GetTokenResponse>;
|
|
@@ -26,8 +26,8 @@ export class Auth {
|
|
|
26
26
|
*
|
|
27
27
|
* @example
|
|
28
28
|
* await client.auth.getToken({
|
|
29
|
-
* clientId: "
|
|
30
|
-
* clientSecret: "
|
|
29
|
+
* clientId: "client_id_123",
|
|
30
|
+
* clientSecret: "my_secret_value"
|
|
31
31
|
* })
|
|
32
32
|
*/
|
|
33
33
|
getToken(request, requestOptions) {
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* @example
|
|
6
6
|
* {
|
|
7
|
-
* clientId: "
|
|
8
|
-
* clientSecret: "
|
|
7
|
+
* clientId: "client_id_123",
|
|
8
|
+
* clientSecret: "my_secret_value"
|
|
9
9
|
* }
|
|
10
10
|
*/
|
|
11
11
|
export interface AuthGetTokenRequest {
|
|
12
12
|
clientId: string;
|
|
13
|
-
|
|
13
|
+
/** Optional secret for confidential clients and Authorization code flow */
|
|
14
|
+
clientSecret?: string;
|
|
14
15
|
}
|
|
@@ -16,7 +16,7 @@ export declare class OAuthTokenProvider {
|
|
|
16
16
|
private _expiresAt;
|
|
17
17
|
constructor({ clientId, clientSecret, authClient, }: {
|
|
18
18
|
clientId: core.Supplier<string>;
|
|
19
|
-
clientSecret: core.Supplier<string>;
|
|
19
|
+
clientSecret: core.Supplier<string | undefined>;
|
|
20
20
|
authClient: Auth;
|
|
21
21
|
});
|
|
22
22
|
getToken(): Promise<string>;
|
|
@@ -15,20 +15,47 @@ import { Auth as FernAuth } from "../api/resources/auth/client/Client.mjs";
|
|
|
15
15
|
import * as core from "../core/index.mjs";
|
|
16
16
|
import * as Corti from "../api/index.mjs";
|
|
17
17
|
import * as environments from "../environments.mjs";
|
|
18
|
+
/**
|
|
19
|
+
* Patch: added codeChallenge to the AuthorizationCodeClient interface to support PKCE flow
|
|
20
|
+
*/
|
|
18
21
|
interface AuthorizationCodeClient {
|
|
19
22
|
clientId: string;
|
|
20
23
|
redirectUri: string;
|
|
24
|
+
codeChallenge?: string;
|
|
21
25
|
}
|
|
22
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Patch: renamed AuthorizationCodeClient to AuthorizationCode as it can be used for both(server and client) flows
|
|
28
|
+
*/
|
|
29
|
+
interface AuthorizationCode {
|
|
23
30
|
clientId: string;
|
|
24
31
|
clientSecret: string;
|
|
25
32
|
redirectUri: string;
|
|
26
33
|
code: string;
|
|
27
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Patch: added type for AuthorizationPkce request
|
|
37
|
+
*/
|
|
38
|
+
interface AuthorizationPkce {
|
|
39
|
+
clientId: string;
|
|
40
|
+
redirectUri: string;
|
|
41
|
+
code: string;
|
|
42
|
+
codeVerifier?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Patch: added type for AuthorizationRopc request
|
|
46
|
+
*/
|
|
47
|
+
interface AuthorizationRopcServer {
|
|
48
|
+
clientId: string;
|
|
49
|
+
username: string;
|
|
50
|
+
password: string;
|
|
51
|
+
}
|
|
28
52
|
interface AuthorizationRefreshServer {
|
|
29
53
|
clientId: string;
|
|
30
54
|
clientSecret: string;
|
|
31
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Patch: added optional refreshToken for ROPC and PKCE flow
|
|
57
|
+
*/
|
|
58
|
+
refreshToken?: string;
|
|
32
59
|
}
|
|
33
60
|
interface Options {
|
|
34
61
|
skipRedirect?: boolean;
|
|
@@ -41,18 +68,34 @@ export declare class Auth extends FernAuth {
|
|
|
41
68
|
* Patch: use custom AuthOptions type to support string-based environment
|
|
42
69
|
*/
|
|
43
70
|
constructor(_options: AuthOptions);
|
|
71
|
+
/**
|
|
72
|
+
* Patch: Generate PKCE authorization URL with automatic code verifier generation
|
|
73
|
+
*/
|
|
74
|
+
authorizePkceUrl({ clientId, redirectUri, }: AuthorizationCodeClient, options?: Options): Promise<string>;
|
|
75
|
+
/**
|
|
76
|
+
* Patch: Get the stored PKCE code verifier
|
|
77
|
+
*/
|
|
78
|
+
getCodeVerifier(): string | null;
|
|
44
79
|
/**
|
|
45
80
|
* Patch: called custom implementation this.__getToken_custom instead of this.__getToken
|
|
46
81
|
*/
|
|
47
82
|
getToken(request: Corti.AuthGetTokenRequest, requestOptions?: FernAuth.RequestOptions): core.HttpResponsePromise<Corti.GetTokenResponse>;
|
|
48
83
|
/**
|
|
49
|
-
* Patch: added method to get Authorization URL for Authorization code flow
|
|
84
|
+
* Patch: added method to get Authorization URL for Authorization code flow and PKCE flow
|
|
50
85
|
*/
|
|
51
|
-
authorizeURL({ clientId, redirectUri, }: AuthorizationCodeClient, options?: Options): Promise<string>;
|
|
86
|
+
authorizeURL({ clientId, redirectUri, codeChallenge, }: AuthorizationCodeClient, options?: Options): Promise<string>;
|
|
52
87
|
/**
|
|
53
88
|
* Patch: calls __getToken_custom with additional fields to support Authorization code flow
|
|
54
89
|
*/
|
|
55
|
-
getCodeFlowToken(request:
|
|
90
|
+
getCodeFlowToken(request: AuthorizationCode, requestOptions?: FernAuth.RequestOptions): core.HttpResponsePromise<Corti.GetTokenResponse>;
|
|
91
|
+
/**
|
|
92
|
+
* Patch: PKCE-specific method
|
|
93
|
+
*/
|
|
94
|
+
getPkceFlowToken(request: AuthorizationPkce, requestOptions?: FernAuth.RequestOptions): core.HttpResponsePromise<Corti.GetTokenResponse>;
|
|
95
|
+
/**
|
|
96
|
+
* Patch: ROPC-specific method
|
|
97
|
+
*/
|
|
98
|
+
getRopcFlowToken(request: AuthorizationRopcServer, requestOptions?: FernAuth.RequestOptions): core.HttpResponsePromise<Corti.GetTokenResponse>;
|
|
56
99
|
/**
|
|
57
100
|
* Patch: copy of this.__getToken with patches
|
|
58
101
|
*/
|
|
@@ -26,6 +26,11 @@ import { mergeHeaders, mergeOnlyDefinedHeaders } from "../core/headers.mjs";
|
|
|
26
26
|
import * as serializers from "../serialization/index.mjs";
|
|
27
27
|
import * as errors from "../errors/index.mjs";
|
|
28
28
|
import { getEnvironment } from "./utils/getEnvironmentFromString.mjs";
|
|
29
|
+
import { ParseError } from "../core/schemas/builders/schema-utils/ParseError.mjs";
|
|
30
|
+
import { getLocalStorageItem, setLocalStorageItem } from "./utils/localStorage.mjs";
|
|
31
|
+
import { generateCodeChallenge, generateCodeVerifier } from "./utils/pkce.mjs";
|
|
32
|
+
import { buildTokenRequestBody } from "./utils/tokenRequest.mjs";
|
|
33
|
+
const CODE_VERIFIER_KEY = "corti_js_sdk_code_verifier";
|
|
29
34
|
export class Auth extends FernAuth {
|
|
30
35
|
/**
|
|
31
36
|
* Patch: use custom AuthOptions type to support string-based environment
|
|
@@ -33,6 +38,27 @@ export class Auth extends FernAuth {
|
|
|
33
38
|
constructor(_options) {
|
|
34
39
|
super(Object.assign(Object.assign({}, _options), { environment: getEnvironment(_options.environment) }));
|
|
35
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Patch: Generate PKCE authorization URL with automatic code verifier generation
|
|
43
|
+
*/
|
|
44
|
+
authorizePkceUrl(_a, options_1) {
|
|
45
|
+
return __awaiter(this, arguments, void 0, function* ({ clientId, redirectUri, }, options) {
|
|
46
|
+
const codeVerifier = generateCodeVerifier();
|
|
47
|
+
setLocalStorageItem(CODE_VERIFIER_KEY, codeVerifier);
|
|
48
|
+
const codeChallenge = yield generateCodeChallenge(codeVerifier);
|
|
49
|
+
return this.authorizeURL({
|
|
50
|
+
clientId,
|
|
51
|
+
redirectUri,
|
|
52
|
+
codeChallenge,
|
|
53
|
+
}, options);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Patch: Get the stored PKCE code verifier
|
|
58
|
+
*/
|
|
59
|
+
getCodeVerifier() {
|
|
60
|
+
return getLocalStorageItem(CODE_VERIFIER_KEY);
|
|
61
|
+
}
|
|
36
62
|
/**
|
|
37
63
|
* Patch: called custom implementation this.__getToken_custom instead of this.__getToken
|
|
38
64
|
*/
|
|
@@ -40,10 +66,10 @@ export class Auth extends FernAuth {
|
|
|
40
66
|
return core.HttpResponsePromise.fromPromise(this.__getToken_custom(request, requestOptions));
|
|
41
67
|
}
|
|
42
68
|
/**
|
|
43
|
-
* Patch: added method to get Authorization URL for Authorization code flow
|
|
69
|
+
* Patch: added method to get Authorization URL for Authorization code flow and PKCE flow
|
|
44
70
|
*/
|
|
45
71
|
authorizeURL(_a, options_1) {
|
|
46
|
-
return __awaiter(this, arguments, void 0, function* ({ clientId, redirectUri, }, options) {
|
|
72
|
+
return __awaiter(this, arguments, void 0, function* ({ clientId, redirectUri, codeChallenge, }, options) {
|
|
47
73
|
var _b;
|
|
48
74
|
const authUrl = new URL(core.url.join((_b = (yield core.Supplier.get(this._options.baseUrl))) !== null && _b !== void 0 ? _b : (yield core.Supplier.get(this._options.environment)).login, yield core.Supplier.get(this._options.tenantName), "protocol/openid-connect/auth"));
|
|
49
75
|
authUrl.searchParams.set('response_type', 'code');
|
|
@@ -54,6 +80,10 @@ export class Auth extends FernAuth {
|
|
|
54
80
|
if (redirectUri !== undefined) {
|
|
55
81
|
authUrl.searchParams.set('redirect_uri', redirectUri);
|
|
56
82
|
}
|
|
83
|
+
if (codeChallenge !== undefined) {
|
|
84
|
+
authUrl.searchParams.set('code_challenge', codeChallenge);
|
|
85
|
+
authUrl.searchParams.set('code_challenge_method', 'S256');
|
|
86
|
+
}
|
|
57
87
|
const authUrlString = authUrl.toString();
|
|
58
88
|
if (typeof window !== "undefined" && !(options === null || options === void 0 ? void 0 : options.skipRedirect)) {
|
|
59
89
|
window.location.href = authUrlString;
|
|
@@ -68,12 +98,33 @@ export class Auth extends FernAuth {
|
|
|
68
98
|
getCodeFlowToken(request, requestOptions) {
|
|
69
99
|
return core.HttpResponsePromise.fromPromise(this.__getToken_custom(Object.assign(Object.assign({}, request), { grantType: "authorization_code" }), requestOptions));
|
|
70
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Patch: PKCE-specific method
|
|
103
|
+
*/
|
|
104
|
+
getPkceFlowToken(request, requestOptions) {
|
|
105
|
+
const codeVerifier = request.codeVerifier || this.getCodeVerifier();
|
|
106
|
+
if (!codeVerifier) {
|
|
107
|
+
throw new ParseError([
|
|
108
|
+
{
|
|
109
|
+
path: ['codeVerifier'],
|
|
110
|
+
message: 'Code verifier was not provided and not found in localStorage.',
|
|
111
|
+
},
|
|
112
|
+
]);
|
|
113
|
+
}
|
|
114
|
+
return core.HttpResponsePromise.fromPromise(this.__getToken_custom(Object.assign(Object.assign({}, request), { codeVerifier: codeVerifier, grantType: "authorization_code" }), requestOptions));
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Patch: ROPC-specific method
|
|
118
|
+
*/
|
|
119
|
+
getRopcFlowToken(request, requestOptions) {
|
|
120
|
+
return core.HttpResponsePromise.fromPromise(this.__getToken_custom(Object.assign(Object.assign({}, request), { grantType: "password" }), requestOptions));
|
|
121
|
+
}
|
|
71
122
|
/**
|
|
72
123
|
* Patch: copy of this.__getToken with patches
|
|
73
124
|
*/
|
|
74
125
|
__getToken_custom(
|
|
75
126
|
/**
|
|
76
|
-
* Patch: added additional fields to request to support Authorization
|
|
127
|
+
* Patch: added additional fields to request to support Authorization PKCE and ROPC flow
|
|
77
128
|
*/
|
|
78
129
|
request, requestOptions) {
|
|
79
130
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -96,23 +147,7 @@ export class Auth extends FernAuth {
|
|
|
96
147
|
/**
|
|
97
148
|
* Patch: removed `requestType: "json"`, made body a URLSearchParams object
|
|
98
149
|
*/
|
|
99
|
-
body:
|
|
100
|
-
unrecognizedObjectKeys: "strip",
|
|
101
|
-
omitUndefined: true,
|
|
102
|
-
})), { scope: "openid",
|
|
103
|
-
/**
|
|
104
|
-
* Patch: `grant_type` uses values from request or defaults to "client_credentials"
|
|
105
|
-
*/
|
|
106
|
-
grant_type: request.grantType || "client_credentials" }), (request.grantType === "authorization_code"
|
|
107
|
-
? {
|
|
108
|
-
code: request.code,
|
|
109
|
-
redirect_uri: request.redirectUri
|
|
110
|
-
}
|
|
111
|
-
: {})), (request.grantType === "refresh_token"
|
|
112
|
-
? {
|
|
113
|
-
refresh_token: request.refreshToken,
|
|
114
|
-
}
|
|
115
|
-
: {}))),
|
|
150
|
+
body: buildTokenRequestBody(request),
|
|
116
151
|
timeoutMs: (requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.timeoutInSeconds) != null ? requestOptions.timeoutInSeconds * 1000 : 60000,
|
|
117
152
|
maxRetries: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.maxRetries,
|
|
118
153
|
abortSignal: requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.abortSignal,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface CortiSDKErrorOptions {
|
|
2
|
+
code: CortiSDKErrorCodes;
|
|
3
|
+
cause?: unknown;
|
|
4
|
+
}
|
|
5
|
+
export declare enum CortiSDKErrorCodes {
|
|
6
|
+
LOCAL_STORAGE_ERROR = "local_storage_error"
|
|
7
|
+
}
|
|
8
|
+
export declare class CortiSDKError extends Error {
|
|
9
|
+
readonly code: CortiSDKErrorCodes;
|
|
10
|
+
readonly cause?: unknown;
|
|
11
|
+
constructor(message?: string, options?: CortiSDKErrorOptions);
|
|
12
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export var CortiSDKErrorCodes;
|
|
2
|
+
(function (CortiSDKErrorCodes) {
|
|
3
|
+
CortiSDKErrorCodes["LOCAL_STORAGE_ERROR"] = "local_storage_error";
|
|
4
|
+
})(CortiSDKErrorCodes || (CortiSDKErrorCodes = {}));
|
|
5
|
+
export class CortiSDKError extends Error {
|
|
6
|
+
constructor(message = "An unexpected error occurred in the Corti SDK.", options = { code: CortiSDKErrorCodes.LOCAL_STORAGE_ERROR }) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "CortiSDKError";
|
|
9
|
+
this.code = options.code;
|
|
10
|
+
if ("cause" in options) {
|
|
11
|
+
this.cause = options.cause;
|
|
12
|
+
}
|
|
13
|
+
Object.setPrototypeOf(this, CortiSDKError.prototype);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const LOCAL_STORAGE_ERROR_CODE: "local_storage_error";
|
|
2
|
+
export declare const requireLocalStorage: () => Storage;
|
|
3
|
+
export declare const setLocalStorageItem: (key: string, value: string) => void;
|
|
4
|
+
export declare const getLocalStorageItem: (key: string) => string | null;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { CortiSDKError, CortiSDKErrorCodes } from "../CortiSDKError.mjs";
|
|
2
|
+
export const LOCAL_STORAGE_ERROR_CODE = "local_storage_error";
|
|
3
|
+
export const requireLocalStorage = () => {
|
|
4
|
+
if (typeof window === "undefined" || !window.localStorage) {
|
|
5
|
+
throw new CortiSDKError("LocalStorage operation failed: storage is not available in this environment.", { code: CortiSDKErrorCodes.LOCAL_STORAGE_ERROR });
|
|
6
|
+
}
|
|
7
|
+
return window.localStorage;
|
|
8
|
+
};
|
|
9
|
+
export const setLocalStorageItem = (key, value) => {
|
|
10
|
+
const storage = requireLocalStorage();
|
|
11
|
+
try {
|
|
12
|
+
storage.setItem(key, value);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw new CortiSDKError("LocalStorage set operation failed.", {
|
|
16
|
+
code: CortiSDKErrorCodes.LOCAL_STORAGE_ERROR,
|
|
17
|
+
cause: error,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
export const getLocalStorageItem = (key) => {
|
|
22
|
+
const storage = requireLocalStorage();
|
|
23
|
+
try {
|
|
24
|
+
return storage.getItem(key);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
throw new CortiSDKError("LocalStorage get operation failed.", {
|
|
28
|
+
code: CortiSDKErrorCodes.LOCAL_STORAGE_ERROR,
|
|
29
|
+
cause: error,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
const base64URLEncode = (buffer) => {
|
|
11
|
+
const base64 = btoa(String.fromCharCode(...buffer));
|
|
12
|
+
return base64
|
|
13
|
+
.replace(/\+/g, '-')
|
|
14
|
+
.replace(/\//g, '_')
|
|
15
|
+
.replace(/=/g, '');
|
|
16
|
+
};
|
|
17
|
+
export const generateCodeVerifier = () => {
|
|
18
|
+
const array = new Uint8Array(32);
|
|
19
|
+
crypto.getRandomValues(array);
|
|
20
|
+
return base64URLEncode(array);
|
|
21
|
+
};
|
|
22
|
+
export const generateCodeChallenge = (verifier) => __awaiter(void 0, void 0, void 0, function* () {
|
|
23
|
+
const encoder = new TextEncoder();
|
|
24
|
+
const data = encoder.encode(verifier);
|
|
25
|
+
const hash = yield crypto.subtle.digest('SHA-256', data);
|
|
26
|
+
return base64URLEncode(new Uint8Array(hash));
|
|
27
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as Corti from "../../api/index.mjs";
|
|
2
|
+
export type TokenRequest = Corti.AuthGetTokenRequest & Partial<{
|
|
3
|
+
grantType: "client_credentials" | "authorization_code" | "refresh_token" | "password";
|
|
4
|
+
code: string;
|
|
5
|
+
redirectUri: string;
|
|
6
|
+
refreshToken: string;
|
|
7
|
+
codeVerifier: string;
|
|
8
|
+
username: string;
|
|
9
|
+
password: string;
|
|
10
|
+
}>;
|
|
11
|
+
export declare const buildTokenRequestBody: (request: TokenRequest) => URLSearchParams;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as serializers from "../../serialization/index.mjs";
|
|
2
|
+
export const buildTokenRequestBody = (request) => {
|
|
3
|
+
const serializedRequest = serializers.AuthGetTokenRequest.jsonOrThrow(request, {
|
|
4
|
+
unrecognizedObjectKeys: "strip",
|
|
5
|
+
omitUndefined: true,
|
|
6
|
+
});
|
|
7
|
+
const tokenRequestBody = {
|
|
8
|
+
scope: "openid",
|
|
9
|
+
grant_type: request.grantType || "client_credentials",
|
|
10
|
+
};
|
|
11
|
+
Object.entries(serializedRequest).forEach(([key, value]) => {
|
|
12
|
+
if (value != null) {
|
|
13
|
+
tokenRequestBody[key] = String(value);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
if (request.grantType === "authorization_code") {
|
|
17
|
+
if (request.code != null) {
|
|
18
|
+
tokenRequestBody.code = request.code;
|
|
19
|
+
}
|
|
20
|
+
if (request.redirectUri != null) {
|
|
21
|
+
tokenRequestBody.redirect_uri = request.redirectUri;
|
|
22
|
+
}
|
|
23
|
+
if (request.codeVerifier != null) {
|
|
24
|
+
tokenRequestBody.code_verifier = request.codeVerifier;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (request.grantType === "refresh_token" && request.refreshToken != null) {
|
|
28
|
+
tokenRequestBody.refresh_token = request.refreshToken;
|
|
29
|
+
}
|
|
30
|
+
if (request.grantType === "password") {
|
|
31
|
+
if (request.username != null) {
|
|
32
|
+
tokenRequestBody.username = request.username;
|
|
33
|
+
}
|
|
34
|
+
if (request.password != null) {
|
|
35
|
+
tokenRequestBody.password = request.password;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return new URLSearchParams(tokenRequestBody);
|
|
39
|
+
};
|
package/dist/esm/index.d.mts
CHANGED
|
@@ -15,3 +15,7 @@ export { Auth as CortiAuth } from "./custom/CortiAuth.mjs";
|
|
|
15
15
|
*/
|
|
16
16
|
export { JsonError } from "./core/schemas/builders/schema-utils/JsonError.mjs";
|
|
17
17
|
export { ParseError } from "./core/schemas/builders/schema-utils/ParseError.mjs";
|
|
18
|
+
/**
|
|
19
|
+
* Patch: added new export to provide SDK-level error handling.
|
|
20
|
+
*/
|
|
21
|
+
export { CortiSDKError } from "./custom/CortiSDKError.mjs";
|
package/dist/esm/index.mjs
CHANGED
|
@@ -15,3 +15,7 @@ export { Auth as CortiAuth } from "./custom/CortiAuth.mjs";
|
|
|
15
15
|
*/
|
|
16
16
|
export { JsonError } from "./core/schemas/builders/schema-utils/JsonError.mjs";
|
|
17
17
|
export { ParseError } from "./core/schemas/builders/schema-utils/ParseError.mjs";
|
|
18
|
+
/**
|
|
19
|
+
* Patch: added new export to provide SDK-level error handling.
|
|
20
|
+
*/
|
|
21
|
+
export { CortiSDKError } from "./custom/CortiSDKError.mjs";
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
import * as core from "../../../../../core/index.mjs";
|
|
5
5
|
export const AuthGetTokenRequest = core.serialization.object({
|
|
6
6
|
clientId: core.serialization.property("client_id", core.serialization.string()),
|
|
7
|
-
clientSecret: core.serialization.property("client_secret", core.serialization.string()),
|
|
7
|
+
clientSecret: core.serialization.property("client_secret", core.serialization.string().optional()),
|
|
8
8
|
});
|
package/dist/esm/version.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "0.
|
|
1
|
+
export declare const SDK_VERSION = "0.6.0";
|
package/dist/esm/version.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION = "0.
|
|
1
|
+
export const SDK_VERSION = "0.6.0";
|