@vybit/oauth2-sdk 1.1.0 → 1.2.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 +41 -2
- package/dist/oauth2-client.d.ts +13 -1
- package/dist/oauth2-client.d.ts.map +1 -1
- package/dist/oauth2-client.js +23 -5
- package/dist/oauth2-client.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -55,6 +55,44 @@ await apiClient.triggerVybit('vybit-key', {
|
|
|
55
55
|
});
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
## PKCE Flow (Public Clients)
|
|
59
|
+
|
|
60
|
+
For native apps, SPAs, MCP clients, and other public clients that cannot store a client secret:
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { VybitOAuth2Client } from '@vybit/oauth2-sdk';
|
|
64
|
+
import { generateCodeVerifier, generateCodeChallenge } from '@vybit/core';
|
|
65
|
+
|
|
66
|
+
// No clientSecret needed
|
|
67
|
+
const oauthClient = new VybitOAuth2Client({
|
|
68
|
+
clientId: 'your-client-id',
|
|
69
|
+
redirectUri: 'https://yourapp.com/oauth/callback'
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Step 1: Generate PKCE verifier and challenge
|
|
73
|
+
const codeVerifier = generateCodeVerifier();
|
|
74
|
+
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
75
|
+
|
|
76
|
+
// Step 2: Generate authorization URL with code_challenge
|
|
77
|
+
const authUrl = oauthClient.getAuthorizationUrl({
|
|
78
|
+
state: 'unique-state-value',
|
|
79
|
+
codeChallenge
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Redirect user to authUrl, store codeVerifier in session...
|
|
83
|
+
|
|
84
|
+
// Step 3: Exchange code with code_verifier (no client_secret needed)
|
|
85
|
+
const token = await oauthClient.exchangeCodeForToken(
|
|
86
|
+
'auth-code-from-callback',
|
|
87
|
+
codeVerifier
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// Step 4: Use the token with the API SDK
|
|
91
|
+
const apiClient = new VybitAPIClient({
|
|
92
|
+
accessToken: token.access_token
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
58
96
|
## Environment Management
|
|
59
97
|
|
|
60
98
|
The SDK uses production Vybit endpoints:
|
|
@@ -78,8 +116,9 @@ new VybitOAuth2Client(config: OAuth2Config)
|
|
|
78
116
|
- Generates OAuth2 authorization URL for user redirection
|
|
79
117
|
- Returns complete URL including all required parameters
|
|
80
118
|
|
|
81
|
-
**`exchangeCodeForToken(code: string): Promise<TokenResponse>`**
|
|
119
|
+
**`exchangeCodeForToken(code: string, codeVerifier?: string): Promise<TokenResponse>`**
|
|
82
120
|
- Exchanges authorization code for access token
|
|
121
|
+
- Pass `codeVerifier` for PKCE flow (omits `client_secret` if not configured)
|
|
83
122
|
- Automatically stores token for subsequent `verifyToken()` calls
|
|
84
123
|
|
|
85
124
|
**`verifyToken(accessToken?: string): Promise<boolean>`**
|
|
@@ -117,7 +156,7 @@ Full TypeScript support with comprehensive type definitions:
|
|
|
117
156
|
```typescript
|
|
118
157
|
interface OAuth2Config {
|
|
119
158
|
clientId: string;
|
|
120
|
-
clientSecret
|
|
159
|
+
clientSecret?: string; // Optional for PKCE-only public clients
|
|
121
160
|
redirectUri: string;
|
|
122
161
|
}
|
|
123
162
|
|
package/dist/oauth2-client.d.ts
CHANGED
|
@@ -26,6 +26,18 @@ import { OAuth2Config, TokenResponse, AuthorizationUrlOptions } from '@vybit/cor
|
|
|
26
26
|
* // 3. Exchange authorization code for token (in callback handler)
|
|
27
27
|
* const token = await oauth.exchangeCodeForToken(authCode);
|
|
28
28
|
*
|
|
29
|
+
* // --- PKCE flow (public clients, no client_secret needed) ---
|
|
30
|
+
* import { generateCodeVerifier, generateCodeChallenge } from '@vybit/core';
|
|
31
|
+
*
|
|
32
|
+
* const pkceClient = new VybitOAuth2Client({
|
|
33
|
+
* clientId: 'your-client-id',
|
|
34
|
+
* redirectUri: 'https://yourapp.com/oauth/callback'
|
|
35
|
+
* });
|
|
36
|
+
* const verifier = generateCodeVerifier();
|
|
37
|
+
* const challenge = await generateCodeChallenge(verifier);
|
|
38
|
+
* const pkceAuthUrl = pkceClient.getAuthorizationUrl({ codeChallenge: challenge });
|
|
39
|
+
* const pkceToken = await pkceClient.exchangeCodeForToken(authCode, verifier);
|
|
40
|
+
*
|
|
29
41
|
* // 4. Use token with API client for full Developer API access
|
|
30
42
|
* const api = new VybitAPIClient({ accessToken: token.access_token });
|
|
31
43
|
* const vybits = await api.listVybits();
|
|
@@ -80,7 +92,7 @@ export declare class VybitOAuth2Client {
|
|
|
80
92
|
* const api = new VybitAPIClient({ accessToken: token.access_token });
|
|
81
93
|
* ```
|
|
82
94
|
*/
|
|
83
|
-
exchangeCodeForToken(code: string): Promise<TokenResponse>;
|
|
95
|
+
exchangeCodeForToken(code: string, codeVerifier?: string): Promise<TokenResponse>;
|
|
84
96
|
/**
|
|
85
97
|
* Verifies that an access token is valid
|
|
86
98
|
* @param accessToken - Token to verify (uses stored token if not provided)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth2-client.d.ts","sourceRoot":"","sources":["../src/oauth2-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,YAAY,EACZ,aAAa,EACb,uBAAuB,EACxB,MAAM,aAAa,CAAC;AAErB
|
|
1
|
+
{"version":3,"file":"oauth2-client.d.ts","sourceRoot":"","sources":["../src/oauth2-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,YAAY,EACZ,aAAa,EACb,uBAAuB,EACxB,MAAM,aAAa,CAAC;AAErB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAS;IAE7B;;;;OAIG;gBACS,MAAM,EAAE,YAAY;IAKhC,OAAO,CAAC,cAAc;IAYtB;;;;;;;;;;;;;;;;;;OAkBG;IACH,mBAAmB,CAAC,OAAO,GAAE,uBAA4B,GAAG,MAAM;IAuBlE;;;;;;;;;;;;;;;;;;OAkBG;IACG,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAkDvF;;;;;OAKG;IACG,WAAW,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA2BzD;;;OAGG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAInC;;;OAGG;IACH,cAAc,IAAI,MAAM,GAAG,SAAS;CAGrC"}
|
package/dist/oauth2-client.js
CHANGED
|
@@ -29,6 +29,18 @@ const core_1 = require("@vybit/core");
|
|
|
29
29
|
* // 3. Exchange authorization code for token (in callback handler)
|
|
30
30
|
* const token = await oauth.exchangeCodeForToken(authCode);
|
|
31
31
|
*
|
|
32
|
+
* // --- PKCE flow (public clients, no client_secret needed) ---
|
|
33
|
+
* import { generateCodeVerifier, generateCodeChallenge } from '@vybit/core';
|
|
34
|
+
*
|
|
35
|
+
* const pkceClient = new VybitOAuth2Client({
|
|
36
|
+
* clientId: 'your-client-id',
|
|
37
|
+
* redirectUri: 'https://yourapp.com/oauth/callback'
|
|
38
|
+
* });
|
|
39
|
+
* const verifier = generateCodeVerifier();
|
|
40
|
+
* const challenge = await generateCodeChallenge(verifier);
|
|
41
|
+
* const pkceAuthUrl = pkceClient.getAuthorizationUrl({ codeChallenge: challenge });
|
|
42
|
+
* const pkceToken = await pkceClient.exchangeCodeForToken(authCode, verifier);
|
|
43
|
+
*
|
|
32
44
|
* // 4. Use token with API client for full Developer API access
|
|
33
45
|
* const api = new VybitAPIClient({ accessToken: token.access_token });
|
|
34
46
|
* const vybits = await api.listVybits();
|
|
@@ -48,9 +60,6 @@ class VybitOAuth2Client {
|
|
|
48
60
|
if (!config.clientId) {
|
|
49
61
|
throw new core_1.VybitValidationError('Client ID is required');
|
|
50
62
|
}
|
|
51
|
-
if (!config.clientSecret) {
|
|
52
|
-
throw new core_1.VybitValidationError('Client Secret is required');
|
|
53
|
-
}
|
|
54
63
|
if (!config.redirectUri) {
|
|
55
64
|
throw new core_1.VybitValidationError('Redirect URI is required');
|
|
56
65
|
}
|
|
@@ -89,6 +98,10 @@ class VybitOAuth2Client {
|
|
|
89
98
|
if (options.scope) {
|
|
90
99
|
params.append('scope', options.scope);
|
|
91
100
|
}
|
|
101
|
+
if (options.codeChallenge) {
|
|
102
|
+
params.append('code_challenge', options.codeChallenge);
|
|
103
|
+
params.append('code_challenge_method', options.codeChallengeMethod || 'S256');
|
|
104
|
+
}
|
|
92
105
|
return `${authDomain}?${params.toString()}`;
|
|
93
106
|
}
|
|
94
107
|
/**
|
|
@@ -110,15 +123,20 @@ class VybitOAuth2Client {
|
|
|
110
123
|
* const api = new VybitAPIClient({ accessToken: token.access_token });
|
|
111
124
|
* ```
|
|
112
125
|
*/
|
|
113
|
-
async exchangeCodeForToken(code) {
|
|
126
|
+
async exchangeCodeForToken(code, codeVerifier) {
|
|
114
127
|
const authDomain = (0, core_1.getAuthDomain)();
|
|
115
128
|
const tokenUrl = `${authDomain}/service/token`;
|
|
116
129
|
const formData = new URLSearchParams({
|
|
117
130
|
grant_type: 'authorization_code',
|
|
118
131
|
code,
|
|
119
132
|
client_id: this.config.clientId,
|
|
120
|
-
client_secret: this.config.clientSecret,
|
|
121
133
|
});
|
|
134
|
+
if (this.config.clientSecret) {
|
|
135
|
+
formData.append('client_secret', this.config.clientSecret);
|
|
136
|
+
}
|
|
137
|
+
if (codeVerifier) {
|
|
138
|
+
formData.append('code_verifier', codeVerifier);
|
|
139
|
+
}
|
|
122
140
|
try {
|
|
123
141
|
const response = await fetch(tokenUrl, {
|
|
124
142
|
method: 'POST',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth2-client.js","sourceRoot":"","sources":["../src/oauth2-client.ts"],"names":[],"mappings":";;;AAAA,sCAWqB;AAErB
|
|
1
|
+
{"version":3,"file":"oauth2-client.js","sourceRoot":"","sources":["../src/oauth2-client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vybit/oauth2-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "OAuth 2.0 SDK for Vybit authentication and authorization",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"node": ">=16.0.0"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@vybit/core": "^1.
|
|
42
|
+
"@vybit/core": "^1.3.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"node-fetch": "^3.0.0"
|