@auth-gate/core 0.15.0 → 0.15.2

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/index.cjs CHANGED
@@ -727,13 +727,31 @@ var AuthGateClient = class {
727
727
  /**
728
728
  * Exchange a refresh token for a new JWT.
729
729
  *
730
- * Refresh tokens are single-use — each call returns a new JWT and
731
- * invalidates the previous refresh token (rotation).
730
+ * Refresh tokens are single-use: each call invalidates the token it was
731
+ * given, so callers must store the `refresh_token` it returns or their next
732
+ * refresh fails.
733
+ *
734
+ * Returns `null` for any failure. To end a session, use
735
+ * {@link attemptRefresh}, which separates a rejected token from a temporary
736
+ * failure.
732
737
  *
733
738
  * @param refreshToken - The opaque refresh token.
734
- * @returns A new JWT and its `expires_in` (seconds), or `null` if the refresh token is invalid.
739
+ * @returns A new JWT, its `expires_in` (seconds) and the rotated
740
+ * `refresh_token`, or `null` if the refresh failed.
735
741
  */
736
742
  async refreshToken(refreshToken) {
743
+ const outcome = await this.attemptRefresh(refreshToken);
744
+ return outcome.status === "refreshed" ? outcome : null;
745
+ }
746
+ /**
747
+ * Exchange a refresh token for a new JWT and report why it failed, if it did.
748
+ *
749
+ * @param refreshToken - The opaque refresh token.
750
+ * @returns `refreshed` with the new tokens, `rejected` when the server refused
751
+ * the token, or `unavailable` when it gave no verdict (408, 429, 5xx, network
752
+ * error). Only `rejected` should end a session.
753
+ */
754
+ async attemptRefresh(refreshToken) {
737
755
  try {
738
756
  const response = await fetch(`${this.config.baseUrl}/api/proxy/token/refresh`, {
739
757
  method: "POST",
@@ -743,10 +761,13 @@ var AuthGateClient = class {
743
761
  },
744
762
  body: JSON.stringify({ refresh_token: refreshToken })
745
763
  });
746
- if (!response.ok) return null;
747
- return response.json();
764
+ if (response.ok) return {
765
+ status: "refreshed",
766
+ ...await response.json()
767
+ };
768
+ return { status: response.status === 408 || response.status === 429 || response.status >= 500 ? "unavailable" : "rejected" };
748
769
  } catch {
749
- return null;
770
+ return { status: "unavailable" };
750
771
  }
751
772
  }
752
773
  /**
package/dist/index.d.cts CHANGED
@@ -158,6 +158,17 @@ interface BackupCodesResponse {
158
158
  }
159
159
  //#endregion
160
160
  //#region src/client.d.ts
161
+ /** The result of {@link AuthGateClient.attemptRefresh}. */
162
+ type TokenRefreshOutcome = {
163
+ status: "refreshed";
164
+ token: string;
165
+ refresh_token?: string;
166
+ expires_in: number;
167
+ } | {
168
+ status: "rejected";
169
+ } | {
170
+ status: "unavailable";
171
+ };
161
172
  /**
162
173
  * Core client for interacting with the AuthGate authentication proxy.
163
174
  *
@@ -360,16 +371,32 @@ declare class AuthGateClient {
360
371
  /**
361
372
  * Exchange a refresh token for a new JWT.
362
373
  *
363
- * Refresh tokens are single-use — each call returns a new JWT and
364
- * invalidates the previous refresh token (rotation).
374
+ * Refresh tokens are single-use: each call invalidates the token it was
375
+ * given, so callers must store the `refresh_token` it returns or their next
376
+ * refresh fails.
377
+ *
378
+ * Returns `null` for any failure. To end a session, use
379
+ * {@link attemptRefresh}, which separates a rejected token from a temporary
380
+ * failure.
365
381
  *
366
382
  * @param refreshToken - The opaque refresh token.
367
- * @returns A new JWT and its `expires_in` (seconds), or `null` if the refresh token is invalid.
383
+ * @returns A new JWT, its `expires_in` (seconds) and the rotated
384
+ * `refresh_token`, or `null` if the refresh failed.
368
385
  */
369
386
  refreshToken(refreshToken: string): Promise<{
370
387
  token: string;
388
+ refresh_token?: string;
371
389
  expires_in: number;
372
390
  } | null>;
391
+ /**
392
+ * Exchange a refresh token for a new JWT and report why it failed, if it did.
393
+ *
394
+ * @param refreshToken - The opaque refresh token.
395
+ * @returns `refreshed` with the new tokens, `rejected` when the server refused
396
+ * the token, or `unavailable` when it gave no verdict (408, 429, 5xx, network
397
+ * error). Only `rejected` should end a session.
398
+ */
399
+ attemptRefresh(refreshToken: string): Promise<TokenRefreshOutcome>;
373
400
  /**
374
401
  * Exchange a single-use authorization code (delivered on the callback URL)
375
402
  * for the JWT + refresh token. Codes are one-shot and expire after ~60s.
@@ -1034,4 +1061,4 @@ declare function mergePermissions(projectRole: UserRoleAssignment | null | undef
1034
1061
  */
1035
1062
  declare function hasMergedPermission(projectRole: UserRoleAssignment | null | undefined, orgMembership: OrgMembership | null | undefined, permission: string): boolean;
1036
1063
  //#endregion
1037
- export { AuthGateClient, type AuthGateConfig, type AuthGateConnection, AuthGateError, type AuthGateProjectConfig, type AuthGateUser, type BackupCodesResponse, type BillingEntitlement, type BillingEntitlementV2, type BillingPlan, type BillingPrice, type BillingSubscription, type BillingSubscriptionItem, type BooleanEntitlementDetail, ConfigurationError, type CookieOptions, DEFAULT_COOKIE_NAME, type EntitlementDetail, InvalidStateError, type MeteredEntitlementDetail, type MfaChallengeResponse, type MfaStatus, NONCE_COOKIE_NAME, type OAuthProvider, type OrgInvitation, type OrgMember, type OrgMembership, type OrgRole, type OrgWithMembership, type Organization, REFRESH_TOKEN_COOKIE_NAME, SESSION_MAX_AGE, STATE_TTL_MS, SUPPORTED_PROVIDERS, SessionDecryptionError, type SessionPayload, TokenVerificationError, type TokenVerifyResult, type TotpSetupResponse, type UsageEvent, type UserRoleAssignment, checkFeature, createAuthGateClient, defineConfig, hasAllPermissions, hasAnyPermission, hasFeature, hasMergedPermission, hasPermission, hasPlan, hasRole, mergePermissions };
1064
+ export { AuthGateClient, type AuthGateConfig, type AuthGateConnection, AuthGateError, type AuthGateProjectConfig, type AuthGateUser, type BackupCodesResponse, type BillingEntitlement, type BillingEntitlementV2, type BillingPlan, type BillingPrice, type BillingSubscription, type BillingSubscriptionItem, type BooleanEntitlementDetail, ConfigurationError, type CookieOptions, DEFAULT_COOKIE_NAME, type EntitlementDetail, InvalidStateError, type MeteredEntitlementDetail, type MfaChallengeResponse, type MfaStatus, NONCE_COOKIE_NAME, type OAuthProvider, type OrgInvitation, type OrgMember, type OrgMembership, type OrgRole, type OrgWithMembership, type Organization, REFRESH_TOKEN_COOKIE_NAME, SESSION_MAX_AGE, STATE_TTL_MS, SUPPORTED_PROVIDERS, SessionDecryptionError, type SessionPayload, type TokenRefreshOutcome, TokenVerificationError, type TokenVerifyResult, type TotpSetupResponse, type UsageEvent, type UserRoleAssignment, checkFeature, createAuthGateClient, defineConfig, hasAllPermissions, hasAnyPermission, hasFeature, hasMergedPermission, hasPermission, hasPlan, hasRole, mergePermissions };
package/dist/index.d.ts CHANGED
@@ -158,6 +158,17 @@ interface BackupCodesResponse {
158
158
  }
159
159
  //#endregion
160
160
  //#region src/client.d.ts
161
+ /** The result of {@link AuthGateClient.attemptRefresh}. */
162
+ type TokenRefreshOutcome = {
163
+ status: "refreshed";
164
+ token: string;
165
+ refresh_token?: string;
166
+ expires_in: number;
167
+ } | {
168
+ status: "rejected";
169
+ } | {
170
+ status: "unavailable";
171
+ };
161
172
  /**
162
173
  * Core client for interacting with the AuthGate authentication proxy.
163
174
  *
@@ -360,16 +371,32 @@ declare class AuthGateClient {
360
371
  /**
361
372
  * Exchange a refresh token for a new JWT.
362
373
  *
363
- * Refresh tokens are single-use — each call returns a new JWT and
364
- * invalidates the previous refresh token (rotation).
374
+ * Refresh tokens are single-use: each call invalidates the token it was
375
+ * given, so callers must store the `refresh_token` it returns or their next
376
+ * refresh fails.
377
+ *
378
+ * Returns `null` for any failure. To end a session, use
379
+ * {@link attemptRefresh}, which separates a rejected token from a temporary
380
+ * failure.
365
381
  *
366
382
  * @param refreshToken - The opaque refresh token.
367
- * @returns A new JWT and its `expires_in` (seconds), or `null` if the refresh token is invalid.
383
+ * @returns A new JWT, its `expires_in` (seconds) and the rotated
384
+ * `refresh_token`, or `null` if the refresh failed.
368
385
  */
369
386
  refreshToken(refreshToken: string): Promise<{
370
387
  token: string;
388
+ refresh_token?: string;
371
389
  expires_in: number;
372
390
  } | null>;
391
+ /**
392
+ * Exchange a refresh token for a new JWT and report why it failed, if it did.
393
+ *
394
+ * @param refreshToken - The opaque refresh token.
395
+ * @returns `refreshed` with the new tokens, `rejected` when the server refused
396
+ * the token, or `unavailable` when it gave no verdict (408, 429, 5xx, network
397
+ * error). Only `rejected` should end a session.
398
+ */
399
+ attemptRefresh(refreshToken: string): Promise<TokenRefreshOutcome>;
373
400
  /**
374
401
  * Exchange a single-use authorization code (delivered on the callback URL)
375
402
  * for the JWT + refresh token. Codes are one-shot and expire after ~60s.
@@ -1034,4 +1061,4 @@ declare function mergePermissions(projectRole: UserRoleAssignment | null | undef
1034
1061
  */
1035
1062
  declare function hasMergedPermission(projectRole: UserRoleAssignment | null | undefined, orgMembership: OrgMembership | null | undefined, permission: string): boolean;
1036
1063
  //#endregion
1037
- export { AuthGateClient, type AuthGateConfig, type AuthGateConnection, AuthGateError, type AuthGateProjectConfig, type AuthGateUser, type BackupCodesResponse, type BillingEntitlement, type BillingEntitlementV2, type BillingPlan, type BillingPrice, type BillingSubscription, type BillingSubscriptionItem, type BooleanEntitlementDetail, ConfigurationError, type CookieOptions, DEFAULT_COOKIE_NAME, type EntitlementDetail, InvalidStateError, type MeteredEntitlementDetail, type MfaChallengeResponse, type MfaStatus, NONCE_COOKIE_NAME, type OAuthProvider, type OrgInvitation, type OrgMember, type OrgMembership, type OrgRole, type OrgWithMembership, type Organization, REFRESH_TOKEN_COOKIE_NAME, SESSION_MAX_AGE, STATE_TTL_MS, SUPPORTED_PROVIDERS, SessionDecryptionError, type SessionPayload, TokenVerificationError, type TokenVerifyResult, type TotpSetupResponse, type UsageEvent, type UserRoleAssignment, checkFeature, createAuthGateClient, defineConfig, hasAllPermissions, hasAnyPermission, hasFeature, hasMergedPermission, hasPermission, hasPlan, hasRole, mergePermissions };
1064
+ export { AuthGateClient, type AuthGateConfig, type AuthGateConnection, AuthGateError, type AuthGateProjectConfig, type AuthGateUser, type BackupCodesResponse, type BillingEntitlement, type BillingEntitlementV2, type BillingPlan, type BillingPrice, type BillingSubscription, type BillingSubscriptionItem, type BooleanEntitlementDetail, ConfigurationError, type CookieOptions, DEFAULT_COOKIE_NAME, type EntitlementDetail, InvalidStateError, type MeteredEntitlementDetail, type MfaChallengeResponse, type MfaStatus, NONCE_COOKIE_NAME, type OAuthProvider, type OrgInvitation, type OrgMember, type OrgMembership, type OrgRole, type OrgWithMembership, type Organization, REFRESH_TOKEN_COOKIE_NAME, SESSION_MAX_AGE, STATE_TTL_MS, SUPPORTED_PROVIDERS, SessionDecryptionError, type SessionPayload, type TokenRefreshOutcome, TokenVerificationError, type TokenVerifyResult, type TotpSetupResponse, type UsageEvent, type UserRoleAssignment, checkFeature, createAuthGateClient, defineConfig, hasAllPermissions, hasAnyPermission, hasFeature, hasMergedPermission, hasPermission, hasPlan, hasRole, mergePermissions };
package/dist/index.mjs CHANGED
@@ -726,13 +726,31 @@ var AuthGateClient = class {
726
726
  /**
727
727
  * Exchange a refresh token for a new JWT.
728
728
  *
729
- * Refresh tokens are single-use — each call returns a new JWT and
730
- * invalidates the previous refresh token (rotation).
729
+ * Refresh tokens are single-use: each call invalidates the token it was
730
+ * given, so callers must store the `refresh_token` it returns or their next
731
+ * refresh fails.
732
+ *
733
+ * Returns `null` for any failure. To end a session, use
734
+ * {@link attemptRefresh}, which separates a rejected token from a temporary
735
+ * failure.
731
736
  *
732
737
  * @param refreshToken - The opaque refresh token.
733
- * @returns A new JWT and its `expires_in` (seconds), or `null` if the refresh token is invalid.
738
+ * @returns A new JWT, its `expires_in` (seconds) and the rotated
739
+ * `refresh_token`, or `null` if the refresh failed.
734
740
  */
735
741
  async refreshToken(refreshToken) {
742
+ const outcome = await this.attemptRefresh(refreshToken);
743
+ return outcome.status === "refreshed" ? outcome : null;
744
+ }
745
+ /**
746
+ * Exchange a refresh token for a new JWT and report why it failed, if it did.
747
+ *
748
+ * @param refreshToken - The opaque refresh token.
749
+ * @returns `refreshed` with the new tokens, `rejected` when the server refused
750
+ * the token, or `unavailable` when it gave no verdict (408, 429, 5xx, network
751
+ * error). Only `rejected` should end a session.
752
+ */
753
+ async attemptRefresh(refreshToken) {
736
754
  try {
737
755
  const response = await fetch(`${this.config.baseUrl}/api/proxy/token/refresh`, {
738
756
  method: "POST",
@@ -742,10 +760,13 @@ var AuthGateClient = class {
742
760
  },
743
761
  body: JSON.stringify({ refresh_token: refreshToken })
744
762
  });
745
- if (!response.ok) return null;
746
- return response.json();
763
+ if (response.ok) return {
764
+ status: "refreshed",
765
+ ...await response.json()
766
+ };
767
+ return { status: response.status === 408 || response.status === 429 || response.status >= 500 ? "unavailable" : "rejected" };
747
768
  } catch {
748
- return null;
769
+ return { status: "unavailable" };
749
770
  }
750
771
  }
751
772
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@auth-gate/core",
3
- "version": "0.15.0",
3
+ "version": "0.15.2",
4
4
  "description": "Core client library for AuthGate — the OAuth proxy that handles provider configuration, token exchange, and user normalization so you don't have to.",
5
5
  "type": "module",
6
6
  "exports": {