@oxyhq/core 1.11.16 → 1.11.17
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/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/mixins/OxyServices.auth.js +39 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/mixins/OxyServices.auth.js +39 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/mixins/OxyServices.auth.d.ts +36 -0
- package/package.json +1 -1
- package/src/mixins/OxyServices.auth.ts +65 -2
|
@@ -193,11 +193,47 @@ export declare function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(B
|
|
|
193
193
|
}>>;
|
|
194
194
|
/**
|
|
195
195
|
* Get access token by session ID
|
|
196
|
+
*
|
|
197
|
+
* SECURITY: this endpoint requires the caller to already hold a
|
|
198
|
+
* bearer token whose user owns the referenced session (C1 hardening
|
|
199
|
+
* in the API). For the device-flow / QR sign-in case where the
|
|
200
|
+
* client has no bearer token yet, use `claimSessionByToken` instead.
|
|
196
201
|
*/
|
|
197
202
|
getTokenBySession(sessionId: string): Promise<{
|
|
198
203
|
accessToken: string;
|
|
199
204
|
expiresAt: string;
|
|
200
205
|
}>;
|
|
206
|
+
/**
|
|
207
|
+
* Exchange a device-flow sessionToken for the first access token.
|
|
208
|
+
*
|
|
209
|
+
* The originating client holds a 128-bit `sessionToken` that nobody
|
|
210
|
+
* else has seen — it was generated client-side, sent once on
|
|
211
|
+
* `POST /auth/session/create`, and is never echoed back. After
|
|
212
|
+
* another authenticated device approves the session via
|
|
213
|
+
* `POST /auth/session/authorize/{sessionToken}` (bearer-authed) and
|
|
214
|
+
* the auth socket / poll loop notifies this client, the client
|
|
215
|
+
* exchanges its `sessionToken` here for the first access token,
|
|
216
|
+
* refresh token, sessionId, and the authorized user.
|
|
217
|
+
*
|
|
218
|
+
* This call requires no Authorization header — the high-entropy
|
|
219
|
+
* `sessionToken` IS the credential (RFC 8628 §3.4). The exchange is
|
|
220
|
+
* single-use; replay attempts are rejected with 401.
|
|
221
|
+
*
|
|
222
|
+
* @param sessionToken - The same sessionToken the SDK passed to
|
|
223
|
+
* `POST /auth/session/create` at the start of the flow.
|
|
224
|
+
* @param options.deviceFingerprint - Optional fingerprint of the
|
|
225
|
+
* originating client device.
|
|
226
|
+
*/
|
|
227
|
+
claimSessionByToken(sessionToken: string, options?: {
|
|
228
|
+
deviceFingerprint?: string;
|
|
229
|
+
}): Promise<{
|
|
230
|
+
accessToken: string;
|
|
231
|
+
refreshToken: string;
|
|
232
|
+
sessionId: string;
|
|
233
|
+
deviceId: string;
|
|
234
|
+
expiresAt: string;
|
|
235
|
+
user: User;
|
|
236
|
+
}>;
|
|
201
237
|
/**
|
|
202
238
|
* Get sessions by session ID
|
|
203
239
|
*/
|
package/package.json
CHANGED
|
@@ -440,6 +440,11 @@ export function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
440
440
|
|
|
441
441
|
/**
|
|
442
442
|
* Get access token by session ID
|
|
443
|
+
*
|
|
444
|
+
* SECURITY: this endpoint requires the caller to already hold a
|
|
445
|
+
* bearer token whose user owns the referenced session (C1 hardening
|
|
446
|
+
* in the API). For the device-flow / QR sign-in case where the
|
|
447
|
+
* client has no bearer token yet, use `claimSessionByToken` instead.
|
|
443
448
|
*/
|
|
444
449
|
async getTokenBySession(sessionId: string): Promise<{ accessToken: string; expiresAt: string }> {
|
|
445
450
|
try {
|
|
@@ -449,9 +454,67 @@ export function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
449
454
|
undefined,
|
|
450
455
|
{ cache: false, retry: false }
|
|
451
456
|
);
|
|
452
|
-
|
|
457
|
+
|
|
453
458
|
this.setTokens(res.accessToken);
|
|
454
|
-
|
|
459
|
+
|
|
460
|
+
return res;
|
|
461
|
+
} catch (error) {
|
|
462
|
+
throw this.handleError(error);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Exchange a device-flow sessionToken for the first access token.
|
|
468
|
+
*
|
|
469
|
+
* The originating client holds a 128-bit `sessionToken` that nobody
|
|
470
|
+
* else has seen — it was generated client-side, sent once on
|
|
471
|
+
* `POST /auth/session/create`, and is never echoed back. After
|
|
472
|
+
* another authenticated device approves the session via
|
|
473
|
+
* `POST /auth/session/authorize/{sessionToken}` (bearer-authed) and
|
|
474
|
+
* the auth socket / poll loop notifies this client, the client
|
|
475
|
+
* exchanges its `sessionToken` here for the first access token,
|
|
476
|
+
* refresh token, sessionId, and the authorized user.
|
|
477
|
+
*
|
|
478
|
+
* This call requires no Authorization header — the high-entropy
|
|
479
|
+
* `sessionToken` IS the credential (RFC 8628 §3.4). The exchange is
|
|
480
|
+
* single-use; replay attempts are rejected with 401.
|
|
481
|
+
*
|
|
482
|
+
* @param sessionToken - The same sessionToken the SDK passed to
|
|
483
|
+
* `POST /auth/session/create` at the start of the flow.
|
|
484
|
+
* @param options.deviceFingerprint - Optional fingerprint of the
|
|
485
|
+
* originating client device.
|
|
486
|
+
*/
|
|
487
|
+
async claimSessionByToken(
|
|
488
|
+
sessionToken: string,
|
|
489
|
+
options: { deviceFingerprint?: string } = {}
|
|
490
|
+
): Promise<{
|
|
491
|
+
accessToken: string;
|
|
492
|
+
refreshToken: string;
|
|
493
|
+
sessionId: string;
|
|
494
|
+
deviceId: string;
|
|
495
|
+
expiresAt: string;
|
|
496
|
+
user: User;
|
|
497
|
+
}> {
|
|
498
|
+
try {
|
|
499
|
+
const res = await this.makeRequest<{
|
|
500
|
+
accessToken: string;
|
|
501
|
+
refreshToken: string;
|
|
502
|
+
sessionId: string;
|
|
503
|
+
deviceId: string;
|
|
504
|
+
expiresAt: string;
|
|
505
|
+
user: User;
|
|
506
|
+
}>(
|
|
507
|
+
'POST',
|
|
508
|
+
'/auth/session/claim',
|
|
509
|
+
{
|
|
510
|
+
sessionToken,
|
|
511
|
+
...(options.deviceFingerprint ? { deviceFingerprint: options.deviceFingerprint } : {}),
|
|
512
|
+
},
|
|
513
|
+
{ cache: false, retry: false }
|
|
514
|
+
);
|
|
515
|
+
|
|
516
|
+
this.setTokens(res.accessToken, res.refreshToken);
|
|
517
|
+
|
|
455
518
|
return res;
|
|
456
519
|
} catch (error) {
|
|
457
520
|
throw this.handleError(error);
|