@authyon/auth 0.2.0-beta.4 → 0.2.0-beta.6

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.
@@ -289,6 +289,12 @@ type AuthState = "signed_out" | "authenticated" | "expired";
289
289
  interface AuthyonClientOptions {
290
290
  /** Publishable environment key (`pk_live_...` / `pk_test_...`). */
291
291
  envKey: string;
292
+ /**
293
+ * Originating client IP to forward on every API call as `X-Forwarded-For`.
294
+ * Browsers cannot reliably discover their public IP by themselves; set this
295
+ * only when your application receives it from trusted infrastructure.
296
+ */
297
+ clientIp?: string;
292
298
  /** API origin. Defaults to `https://api.authyon.com`; HTTPS is required outside loopback. */
293
299
  baseUrl?: string;
294
300
  /** Allow an HTTP `baseUrl`. Intended only for explicitly trusted local development. */
@@ -312,6 +318,7 @@ interface AuthyonClientOptions {
312
318
 
313
319
  declare class AuthyonClient {
314
320
  private readonly envKey;
321
+ private readonly clientIp?;
315
322
  private readonly baseUrl;
316
323
  private readonly storage;
317
324
  private readonly autoRefresh;
@@ -289,6 +289,12 @@ type AuthState = "signed_out" | "authenticated" | "expired";
289
289
  interface AuthyonClientOptions {
290
290
  /** Publishable environment key (`pk_live_...` / `pk_test_...`). */
291
291
  envKey: string;
292
+ /**
293
+ * Originating client IP to forward on every API call as `X-Forwarded-For`.
294
+ * Browsers cannot reliably discover their public IP by themselves; set this
295
+ * only when your application receives it from trusted infrastructure.
296
+ */
297
+ clientIp?: string;
292
298
  /** API origin. Defaults to `https://api.authyon.com`; HTTPS is required outside loopback. */
293
299
  baseUrl?: string;
294
300
  /** Allow an HTTP `baseUrl`. Intended only for explicitly trusted local development. */
@@ -312,6 +318,7 @@ interface AuthyonClientOptions {
312
318
 
313
319
  declare class AuthyonClient {
314
320
  private readonly envKey;
321
+ private readonly clientIp?;
315
322
  private readonly baseUrl;
316
323
  private readonly storage;
317
324
  private readonly autoRefresh;
package/dist/index.cjs CHANGED
@@ -403,6 +403,28 @@ var JsonHttpClient = class {
403
403
  }
404
404
  };
405
405
 
406
+ // ../../internal/core/http/clientIp.ts
407
+ function clientIpHeaders(context) {
408
+ if (!context?.clientIp) return {};
409
+ return { "X-Forwarded-For": normalizeClientIp(context.clientIp) };
410
+ }
411
+ function normalizeClientIp(value) {
412
+ let ip = value.trim();
413
+ if (ip.startsWith("[") && ip.endsWith("]")) ip = ip.slice(1, -1);
414
+ if (!ip || ip.length > 45 || ip.includes(",") || /[\r\n\s]/.test(ip) || !/^[0-9a-f:.]+$/i.test(ip) || !ip.includes(".") && !ip.includes(":")) {
415
+ throw invalidClientIp();
416
+ }
417
+ try {
418
+ new URL(ip.includes(":") ? `http://[${ip}]` : `http://${ip}`);
419
+ } catch {
420
+ throw invalidClientIp();
421
+ }
422
+ return ip;
423
+ }
424
+ function invalidClientIp() {
425
+ return new Error("Authyon: `clientIp` must be a single valid IPv4 or IPv6 address");
426
+ }
427
+
406
428
  // src/client/authyonClient.ts
407
429
  var FALLBACK_EXPIRES_IN = 1800;
408
430
  function readTokens(raw) {
@@ -618,6 +640,7 @@ var AuthyonClient = class {
618
640
  if (!options.envKey)
619
641
  throw new Error("Authyon: `envKey` is required (pk_live_... / pk_test_...)");
620
642
  this.envKey = options.envKey;
643
+ this.clientIp = options.clientIp;
621
644
  this.transport = createSharedTransport({
622
645
  baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
623
646
  allowInsecureHttp: options.allowInsecureHttp,
@@ -730,6 +753,7 @@ var AuthyonClient = class {
730
753
  async request(path, options = {}, isRetry = false) {
731
754
  const headers = {
732
755
  "X-Authyon-Environment": this.envKey,
756
+ ...clientIpHeaders({ clientIp: this.clientIp }),
733
757
  ...options.headers
734
758
  };
735
759
  if (options.bearer) {
@@ -894,6 +918,10 @@ var AuthyonClientBuilder = class {
894
918
  this.options.autoRefresh = enabled;
895
919
  return this;
896
920
  }
921
+ withClientIp(clientIp) {
922
+ this.options.clientIp = clientIp;
923
+ return this;
924
+ }
897
925
  withTimeout(timeoutMs) {
898
926
  this.options.timeoutMs = timeoutMs;
899
927
  return this;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-g6nBpOQM.cjs';
2
- export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as Activity, h as AuthEvent, i as AuthState, j as AuthStateListener, k as AuthenticatorSetup, l as AuthyonAbility, m as AuthyonAbilityBuilder, n as AuthyonAbilityOptions, o as AuthyonClientOptions, p as AuthyonPermissionSource, q as AuthyonSessionController, C as CreateOrganizationInput, F as FetchHttpAdapter, r as HttpAdapterRequest, s as HttpLogEvent, t as HttpLogger, I as IntrospectResult, u as InviteMemberInput, L as LoggingHttpAdapter, v as LoginInput, w as LoginResult, O as Organization, x as OrganizationMember, P as Paged, y as PaginationOptions, R as RegisterInput, z as Role, S as Session, B as SessionControllerOptions, D as SessionInfo, E as SessionSnapshot, G as SessionSnapshotListener, J as SessionStatus, K as SsoProvider, M as TwoFactorChallenge, N as TwoFactorMethod, Q as TwoFactorStatus, U as User, V as ValidateResult, W as VerifyTwoFactorInput, X as WebAuthnAssertion, Y as WebAuthnCeremonyStart, Z as WebAuthnCredential, _ as createAuthyonAbility, $ as createAuthyonRules, a0 as createClient, a1 as hasPermission } from './ability-g6nBpOQM.cjs';
1
+ import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-CypQZBLW.cjs';
2
+ export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as Activity, h as AuthEvent, i as AuthState, j as AuthStateListener, k as AuthenticatorSetup, l as AuthyonAbility, m as AuthyonAbilityBuilder, n as AuthyonAbilityOptions, o as AuthyonClientOptions, p as AuthyonPermissionSource, q as AuthyonSessionController, C as CreateOrganizationInput, F as FetchHttpAdapter, r as HttpAdapterRequest, s as HttpLogEvent, t as HttpLogger, I as IntrospectResult, u as InviteMemberInput, L as LoggingHttpAdapter, v as LoginInput, w as LoginResult, O as Organization, x as OrganizationMember, P as Paged, y as PaginationOptions, R as RegisterInput, z as Role, S as Session, B as SessionControllerOptions, D as SessionInfo, E as SessionSnapshot, G as SessionSnapshotListener, J as SessionStatus, K as SsoProvider, M as TwoFactorChallenge, N as TwoFactorMethod, Q as TwoFactorStatus, U as User, V as ValidateResult, W as VerifyTwoFactorInput, X as WebAuthnAssertion, Y as WebAuthnCeremonyStart, Z as WebAuthnCredential, _ as createAuthyonAbility, $ as createAuthyonRules, a0 as createClient, a1 as hasPermission } from './ability-CypQZBLW.cjs';
3
3
 
4
4
  /** Builds an Authyon browser client through explicit, progressive configuration. */
5
5
  declare class AuthyonClientBuilder {
@@ -8,6 +8,7 @@ declare class AuthyonClientBuilder {
8
8
  withBaseUrl(baseUrl: string, allowInsecureHttp?: boolean): this;
9
9
  withStorage(storage: TokenStorage): this;
10
10
  withAutomaticRefresh(enabled?: boolean): this;
11
+ withClientIp(clientIp: string): this;
11
12
  withTimeout(timeoutMs: number): this;
12
13
  withHttpAdapter(httpAdapter: HttpAdapter): this;
13
14
  withHttpLogger(httpLogger: HttpLoggerOptions): this;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-g6nBpOQM.js';
2
- export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as Activity, h as AuthEvent, i as AuthState, j as AuthStateListener, k as AuthenticatorSetup, l as AuthyonAbility, m as AuthyonAbilityBuilder, n as AuthyonAbilityOptions, o as AuthyonClientOptions, p as AuthyonPermissionSource, q as AuthyonSessionController, C as CreateOrganizationInput, F as FetchHttpAdapter, r as HttpAdapterRequest, s as HttpLogEvent, t as HttpLogger, I as IntrospectResult, u as InviteMemberInput, L as LoggingHttpAdapter, v as LoginInput, w as LoginResult, O as Organization, x as OrganizationMember, P as Paged, y as PaginationOptions, R as RegisterInput, z as Role, S as Session, B as SessionControllerOptions, D as SessionInfo, E as SessionSnapshot, G as SessionSnapshotListener, J as SessionStatus, K as SsoProvider, M as TwoFactorChallenge, N as TwoFactorMethod, Q as TwoFactorStatus, U as User, V as ValidateResult, W as VerifyTwoFactorInput, X as WebAuthnAssertion, Y as WebAuthnCeremonyStart, Z as WebAuthnCredential, _ as createAuthyonAbility, $ as createAuthyonRules, a0 as createClient, a1 as hasPermission } from './ability-g6nBpOQM.js';
1
+ import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-CypQZBLW.js';
2
+ export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as Activity, h as AuthEvent, i as AuthState, j as AuthStateListener, k as AuthenticatorSetup, l as AuthyonAbility, m as AuthyonAbilityBuilder, n as AuthyonAbilityOptions, o as AuthyonClientOptions, p as AuthyonPermissionSource, q as AuthyonSessionController, C as CreateOrganizationInput, F as FetchHttpAdapter, r as HttpAdapterRequest, s as HttpLogEvent, t as HttpLogger, I as IntrospectResult, u as InviteMemberInput, L as LoggingHttpAdapter, v as LoginInput, w as LoginResult, O as Organization, x as OrganizationMember, P as Paged, y as PaginationOptions, R as RegisterInput, z as Role, S as Session, B as SessionControllerOptions, D as SessionInfo, E as SessionSnapshot, G as SessionSnapshotListener, J as SessionStatus, K as SsoProvider, M as TwoFactorChallenge, N as TwoFactorMethod, Q as TwoFactorStatus, U as User, V as ValidateResult, W as VerifyTwoFactorInput, X as WebAuthnAssertion, Y as WebAuthnCeremonyStart, Z as WebAuthnCredential, _ as createAuthyonAbility, $ as createAuthyonRules, a0 as createClient, a1 as hasPermission } from './ability-CypQZBLW.js';
3
3
 
4
4
  /** Builds an Authyon browser client through explicit, progressive configuration. */
5
5
  declare class AuthyonClientBuilder {
@@ -8,6 +8,7 @@ declare class AuthyonClientBuilder {
8
8
  withBaseUrl(baseUrl: string, allowInsecureHttp?: boolean): this;
9
9
  withStorage(storage: TokenStorage): this;
10
10
  withAutomaticRefresh(enabled?: boolean): this;
11
+ withClientIp(clientIp: string): this;
11
12
  withTimeout(timeoutMs: number): this;
12
13
  withHttpAdapter(httpAdapter: HttpAdapter): this;
13
14
  withHttpLogger(httpLogger: HttpLoggerOptions): this;
package/dist/index.js CHANGED
@@ -371,6 +371,28 @@ var JsonHttpClient = class {
371
371
  }
372
372
  };
373
373
 
374
+ // ../../internal/core/http/clientIp.ts
375
+ function clientIpHeaders(context) {
376
+ if (!context?.clientIp) return {};
377
+ return { "X-Forwarded-For": normalizeClientIp(context.clientIp) };
378
+ }
379
+ function normalizeClientIp(value) {
380
+ let ip = value.trim();
381
+ if (ip.startsWith("[") && ip.endsWith("]")) ip = ip.slice(1, -1);
382
+ if (!ip || ip.length > 45 || ip.includes(",") || /[\r\n\s]/.test(ip) || !/^[0-9a-f:.]+$/i.test(ip) || !ip.includes(".") && !ip.includes(":")) {
383
+ throw invalidClientIp();
384
+ }
385
+ try {
386
+ new URL(ip.includes(":") ? `http://[${ip}]` : `http://${ip}`);
387
+ } catch {
388
+ throw invalidClientIp();
389
+ }
390
+ return ip;
391
+ }
392
+ function invalidClientIp() {
393
+ return new Error("Authyon: `clientIp` must be a single valid IPv4 or IPv6 address");
394
+ }
395
+
374
396
  // src/client/authyonClient.ts
375
397
  var FALLBACK_EXPIRES_IN = 1800;
376
398
  function readTokens(raw) {
@@ -586,6 +608,7 @@ var AuthyonClient = class {
586
608
  if (!options.envKey)
587
609
  throw new Error("Authyon: `envKey` is required (pk_live_... / pk_test_...)");
588
610
  this.envKey = options.envKey;
611
+ this.clientIp = options.clientIp;
589
612
  this.transport = createSharedTransport({
590
613
  baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
591
614
  allowInsecureHttp: options.allowInsecureHttp,
@@ -698,6 +721,7 @@ var AuthyonClient = class {
698
721
  async request(path, options = {}, isRetry = false) {
699
722
  const headers = {
700
723
  "X-Authyon-Environment": this.envKey,
724
+ ...clientIpHeaders({ clientIp: this.clientIp }),
701
725
  ...options.headers
702
726
  };
703
727
  if (options.bearer) {
@@ -862,6 +886,10 @@ var AuthyonClientBuilder = class {
862
886
  this.options.autoRefresh = enabled;
863
887
  return this;
864
888
  }
889
+ withClientIp(clientIp) {
890
+ this.options.clientIp = clientIp;
891
+ return this;
892
+ }
865
893
  withTimeout(timeoutMs) {
866
894
  this.options.timeoutMs = timeoutMs;
867
895
  return this;
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { U as User, B as SessionControllerOptions, A as AuthyonClient, E as SessionSnapshot, S as Session, f as AbilitySubject, n as AuthyonAbilityOptions, l as AuthyonAbility } from '../ability-g6nBpOQM.cjs';
4
- export { q as AuthyonSessionController, G as SessionSnapshotListener, J as SessionStatus } from '../ability-g6nBpOQM.cjs';
3
+ import { U as User, B as SessionControllerOptions, A as AuthyonClient, E as SessionSnapshot, S as Session, f as AbilitySubject, n as AuthyonAbilityOptions, l as AuthyonAbility } from '../ability-CypQZBLW.cjs';
4
+ export { q as AuthyonSessionController, G as SessionSnapshotListener, J as SessionStatus } from '../ability-CypQZBLW.cjs';
5
5
 
6
6
  interface AuthyonProviderProps<TUser extends User = User> extends SessionControllerOptions {
7
7
  client: AuthyonClient;
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { U as User, B as SessionControllerOptions, A as AuthyonClient, E as SessionSnapshot, S as Session, f as AbilitySubject, n as AuthyonAbilityOptions, l as AuthyonAbility } from '../ability-g6nBpOQM.js';
4
- export { q as AuthyonSessionController, G as SessionSnapshotListener, J as SessionStatus } from '../ability-g6nBpOQM.js';
3
+ import { U as User, B as SessionControllerOptions, A as AuthyonClient, E as SessionSnapshot, S as Session, f as AbilitySubject, n as AuthyonAbilityOptions, l as AuthyonAbility } from '../ability-CypQZBLW.js';
4
+ export { q as AuthyonSessionController, G as SessionSnapshotListener, J as SessionStatus } from '../ability-CypQZBLW.js';
5
5
 
6
6
  interface AuthyonProviderProps<TUser extends User = User> extends SessionControllerOptions {
7
7
  client: AuthyonClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@authyon/auth",
3
- "version": "0.2.0-beta.4",
3
+ "version": "0.2.0-beta.6",
4
4
  "description": "Authyon SDK for browsers — auth, sessions, multi-tenant and 2FA for vanilla JS/TS.",
5
5
  "license": "MIT",
6
6
  "type": "module",