authmi 1.0.0 → 1.1.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 +7 -7
- package/dist/chunk-EAK7C6YO.mjs +688 -0
- package/dist/client-DmZsG2xs.d.mts +406 -0
- package/dist/client-DmZsG2xs.d.ts +406 -0
- package/dist/index.d.mts +48 -23
- package/dist/index.d.ts +48 -23
- package/dist/index.js +581 -386
- package/dist/index.mjs +115 -3
- package/dist/next.d.mts +7 -37
- package/dist/next.d.ts +7 -37
- package/dist/next.js +476 -416
- package/dist/next.mjs +5 -24
- package/dist/react.d.mts +29 -30
- package/dist/react.d.ts +29 -30
- package/dist/react.js +549 -444
- package/dist/react.mjs +77 -52
- package/package.json +8 -6
- package/dist/chunk-UNKK6FP4.mjs +0 -609
- package/dist/client-D6JiIhlU.d.mts +0 -332
- package/dist/client-D6JiIhlU.d.ts +0 -332
package/dist/next.js
CHANGED
|
@@ -4452,16 +4452,64 @@ var next_exports = {};
|
|
|
4452
4452
|
__export2(next_exports, {
|
|
4453
4453
|
AuthMiClient: () => AuthMiClient,
|
|
4454
4454
|
AuthMiError: () => AuthMiError,
|
|
4455
|
-
LocalStorageTokenStorage: () => LocalStorageTokenStorage,
|
|
4456
|
-
MemoryTokenStorage: () => MemoryTokenStorage,
|
|
4457
4455
|
ScopeError: () => ScopeError,
|
|
4458
4456
|
createAuthMiMiddleware: () => createAuthMiMiddleware,
|
|
4459
|
-
validateScopes: () => validateScopes
|
|
4460
|
-
withScope: () => withScope
|
|
4457
|
+
validateScopes: () => validateScopes
|
|
4461
4458
|
});
|
|
4462
4459
|
module.exports = __toCommonJS(next_exports);
|
|
4463
4460
|
var import_server = __toESM(require_server());
|
|
4464
4461
|
|
|
4462
|
+
// src/config.ts
|
|
4463
|
+
function resolveConfig(provider) {
|
|
4464
|
+
const raw = typeof provider === "function" ? provider() : provider;
|
|
4465
|
+
return {
|
|
4466
|
+
baseUrl: raw.baseUrl,
|
|
4467
|
+
apiKey: raw.apiKey ?? "",
|
|
4468
|
+
serviceId: raw.serviceId ?? "",
|
|
4469
|
+
clientId: raw.clientId ?? "",
|
|
4470
|
+
clientSecret: raw.clientSecret ?? "",
|
|
4471
|
+
defaultTokenExpiry: raw.defaultTokenExpiry ?? 24
|
|
4472
|
+
};
|
|
4473
|
+
}
|
|
4474
|
+
|
|
4475
|
+
// src/storage/localStorage.ts
|
|
4476
|
+
var STORAGE_KEY = "authmi_token";
|
|
4477
|
+
var LocalStorageTokenStorage = class {
|
|
4478
|
+
canAccess() {
|
|
4479
|
+
if (typeof window === "undefined") return false;
|
|
4480
|
+
try {
|
|
4481
|
+
const probe = "__authmi_storage_test__";
|
|
4482
|
+
localStorage.setItem(probe, "1");
|
|
4483
|
+
localStorage.removeItem(probe);
|
|
4484
|
+
return true;
|
|
4485
|
+
} catch {
|
|
4486
|
+
return false;
|
|
4487
|
+
}
|
|
4488
|
+
}
|
|
4489
|
+
getToken() {
|
|
4490
|
+
if (!this.canAccess()) return null;
|
|
4491
|
+
try {
|
|
4492
|
+
return localStorage.getItem(STORAGE_KEY);
|
|
4493
|
+
} catch {
|
|
4494
|
+
return null;
|
|
4495
|
+
}
|
|
4496
|
+
}
|
|
4497
|
+
setToken(token) {
|
|
4498
|
+
if (!this.canAccess()) return;
|
|
4499
|
+
try {
|
|
4500
|
+
localStorage.setItem(STORAGE_KEY, token);
|
|
4501
|
+
} catch {
|
|
4502
|
+
}
|
|
4503
|
+
}
|
|
4504
|
+
removeToken() {
|
|
4505
|
+
if (!this.canAccess()) return;
|
|
4506
|
+
try {
|
|
4507
|
+
localStorage.removeItem(STORAGE_KEY);
|
|
4508
|
+
} catch {
|
|
4509
|
+
}
|
|
4510
|
+
}
|
|
4511
|
+
};
|
|
4512
|
+
|
|
4465
4513
|
// src/types.ts
|
|
4466
4514
|
var AuthMiError = class extends Error {
|
|
4467
4515
|
constructor(message, code, statusCode) {
|
|
@@ -4479,82 +4527,38 @@ var ScopeError = class extends AuthMiError {
|
|
|
4479
4527
|
this.name = "ScopeError";
|
|
4480
4528
|
}
|
|
4481
4529
|
};
|
|
4482
|
-
var _LocalStorageTokenStorage = class _LocalStorageTokenStorage {
|
|
4483
|
-
getToken() {
|
|
4484
|
-
if (typeof window === "undefined") return null;
|
|
4485
|
-
return localStorage.getItem(_LocalStorageTokenStorage.KEY);
|
|
4486
|
-
}
|
|
4487
|
-
setToken(token) {
|
|
4488
|
-
if (typeof window === "undefined") return;
|
|
4489
|
-
localStorage.setItem(_LocalStorageTokenStorage.KEY, token);
|
|
4490
|
-
}
|
|
4491
|
-
removeToken() {
|
|
4492
|
-
if (typeof window === "undefined") return;
|
|
4493
|
-
localStorage.removeItem(_LocalStorageTokenStorage.KEY);
|
|
4494
|
-
}
|
|
4495
|
-
};
|
|
4496
|
-
_LocalStorageTokenStorage.KEY = "authmi_token";
|
|
4497
|
-
var LocalStorageTokenStorage = _LocalStorageTokenStorage;
|
|
4498
|
-
var MemoryTokenStorage = class {
|
|
4499
|
-
constructor() {
|
|
4500
|
-
this.token = null;
|
|
4501
|
-
}
|
|
4502
|
-
getToken() {
|
|
4503
|
-
return this.token;
|
|
4504
|
-
}
|
|
4505
|
-
setToken(token) {
|
|
4506
|
-
this.token = token;
|
|
4507
|
-
}
|
|
4508
|
-
removeToken() {
|
|
4509
|
-
this.token = null;
|
|
4510
|
-
}
|
|
4511
|
-
};
|
|
4512
4530
|
|
|
4513
4531
|
// src/client.ts
|
|
4514
4532
|
var AuthMiClient = class {
|
|
4515
|
-
constructor(config,
|
|
4516
|
-
this.
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
clientId: "",
|
|
4520
|
-
clientSecret: "",
|
|
4521
|
-
defaultTokenExpiry: 24,
|
|
4522
|
-
...config
|
|
4523
|
-
};
|
|
4524
|
-
this.tokenStorage = tokenStorage || new LocalStorageTokenStorage();
|
|
4533
|
+
constructor(config, options) {
|
|
4534
|
+
this.configProvider = config;
|
|
4535
|
+
this.storage = options?.storage ?? new LocalStorageTokenStorage();
|
|
4536
|
+
this.cache = options?.cache || null;
|
|
4525
4537
|
}
|
|
4526
|
-
/**
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
const encoded = btoa(`${this.config.clientId}:${this.config.clientSecret}`);
|
|
4530
|
-
return `Basic ${encoded}`;
|
|
4531
|
-
}
|
|
4532
|
-
return null;
|
|
4538
|
+
/** Resolve current config (supports lazy evaluation) */
|
|
4539
|
+
get config() {
|
|
4540
|
+
return resolveConfig(this.configProvider);
|
|
4533
4541
|
}
|
|
4534
|
-
// ============ HTTP
|
|
4535
|
-
async request(endpoint, options = {},
|
|
4536
|
-
const
|
|
4542
|
+
// ============ HTTP plumbing ============
|
|
4543
|
+
async request(endpoint, options = {}, requireUserToken = false) {
|
|
4544
|
+
const cfg = this.config;
|
|
4545
|
+
const url = `${cfg.baseUrl}${endpoint}`;
|
|
4537
4546
|
const headers = {
|
|
4538
4547
|
"Content-Type": "application/json",
|
|
4539
4548
|
...options.headers || {}
|
|
4540
4549
|
};
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
if (token && !headers["Authorization"]) {
|
|
4550
|
-
headers["Authorization"] = `Bearer ${token}`;
|
|
4550
|
+
if (!headers["Authorization"]) {
|
|
4551
|
+
if (requireUserToken) {
|
|
4552
|
+
const token = await this.storage.getToken();
|
|
4553
|
+
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
4554
|
+
} else if (cfg.clientId && cfg.clientSecret) {
|
|
4555
|
+
headers["Authorization"] = `Basic ${btoa(`${cfg.clientId}:${cfg.clientSecret}`)}`;
|
|
4556
|
+
} else if (cfg.apiKey) {
|
|
4557
|
+
headers["Authorization"] = `Bearer ${cfg.apiKey}`;
|
|
4551
4558
|
}
|
|
4552
4559
|
}
|
|
4553
4560
|
try {
|
|
4554
|
-
const response = await fetch(url, {
|
|
4555
|
-
...options,
|
|
4556
|
-
headers
|
|
4557
|
-
});
|
|
4561
|
+
const response = await fetch(url, { ...options, headers });
|
|
4558
4562
|
const data = await response.json();
|
|
4559
4563
|
if (!response.ok) {
|
|
4560
4564
|
if (response.status === 403 && data.required && data.provided) {
|
|
@@ -4572,9 +4576,7 @@ var AuthMiClient = class {
|
|
|
4572
4576
|
}
|
|
4573
4577
|
return data;
|
|
4574
4578
|
} catch (error) {
|
|
4575
|
-
if (error instanceof AuthMiError)
|
|
4576
|
-
throw error;
|
|
4577
|
-
}
|
|
4579
|
+
if (error instanceof AuthMiError) throw error;
|
|
4578
4580
|
throw new AuthMiError(
|
|
4579
4581
|
error instanceof Error ? error.message : "Network error",
|
|
4580
4582
|
"NETWORK_ERROR"
|
|
@@ -4582,384 +4584,497 @@ var AuthMiClient = class {
|
|
|
4582
4584
|
}
|
|
4583
4585
|
}
|
|
4584
4586
|
// ============ Configuration ============
|
|
4585
|
-
/**
|
|
4586
|
-
* Update the client's service configuration
|
|
4587
|
-
*/
|
|
4588
4587
|
configure(config) {
|
|
4589
|
-
|
|
4588
|
+
const current = resolveConfig(this.configProvider);
|
|
4589
|
+
this.configProvider = { ...current, ...config };
|
|
4590
4590
|
}
|
|
4591
|
-
/**
|
|
4592
|
-
* Get current configuration (without sensitive data)
|
|
4593
|
-
*/
|
|
4594
4591
|
getConfig() {
|
|
4595
|
-
const { apiKey: _, clientSecret: __, ...rest } = this.
|
|
4592
|
+
const { apiKey: _, clientSecret: __, ...rest } = resolveConfig(this.configProvider);
|
|
4596
4593
|
return rest;
|
|
4597
4594
|
}
|
|
4598
4595
|
// ============ Token Management ============
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
getAccessToken() {
|
|
4603
|
-
return this.tokenStorage.getToken();
|
|
4604
|
-
}
|
|
4605
|
-
/**
|
|
4606
|
-
* Store an access token
|
|
4607
|
-
*/
|
|
4596
|
+
async getAccessToken() {
|
|
4597
|
+
return this.storage.getToken();
|
|
4598
|
+
}
|
|
4608
4599
|
setAccessToken(token) {
|
|
4609
|
-
this.
|
|
4600
|
+
this.storage.setToken(token);
|
|
4610
4601
|
}
|
|
4611
|
-
/**
|
|
4612
|
-
* Remove the stored access token (logout)
|
|
4613
|
-
*/
|
|
4614
4602
|
clearAccessToken() {
|
|
4615
|
-
this.
|
|
4616
|
-
}
|
|
4617
|
-
/**
|
|
4618
|
-
* Check if user is logged in
|
|
4619
|
-
*/
|
|
4620
|
-
isLoggedIn() {
|
|
4621
|
-
return !!this.getAccessToken();
|
|
4622
|
-
}
|
|
4623
|
-
// ============ Scope Validation ============
|
|
4624
|
-
/**
|
|
4625
|
-
* Introspect a token or API key and validate required scopes
|
|
4626
|
-
*/
|
|
4627
|
-
async introspect(request) {
|
|
4628
|
-
return this.request("/api/v1/introspect", {
|
|
4629
|
-
method: "POST",
|
|
4630
|
-
body: JSON.stringify(request)
|
|
4631
|
-
});
|
|
4603
|
+
this.storage.removeToken();
|
|
4632
4604
|
}
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
async validateWithScopes(requiredScopes) {
|
|
4637
|
-
const token = this.getAccessToken();
|
|
4638
|
-
if (!token) {
|
|
4639
|
-
return { valid: false, error: "No token provided" };
|
|
4640
|
-
}
|
|
4641
|
-
if (!this.config.apiKey && !this.config.clientSecret) {
|
|
4642
|
-
return { valid: false, error: "Service credentials not configured" };
|
|
4643
|
-
}
|
|
4644
|
-
if (!this.config.serviceId) {
|
|
4645
|
-
return { valid: false, error: "Service ID not configured in AuthMiConfig" };
|
|
4646
|
-
}
|
|
4647
|
-
try {
|
|
4648
|
-
const result = await this.introspect({
|
|
4649
|
-
serviceId: this.config.serviceId,
|
|
4650
|
-
token,
|
|
4651
|
-
requiredScopes
|
|
4652
|
-
});
|
|
4653
|
-
return {
|
|
4654
|
-
valid: result.valid,
|
|
4655
|
-
type: result.type === "bearer" ? "token" : "api_key",
|
|
4656
|
-
scopes: result.scopes,
|
|
4657
|
-
userId: result.userId,
|
|
4658
|
-
email: result.email,
|
|
4659
|
-
error: result.error
|
|
4660
|
-
};
|
|
4661
|
-
} catch (error) {
|
|
4662
|
-
if (error instanceof ScopeError) {
|
|
4663
|
-
return {
|
|
4664
|
-
valid: false,
|
|
4665
|
-
error: error.message,
|
|
4666
|
-
scopes: error.providedScopes
|
|
4667
|
-
};
|
|
4668
|
-
}
|
|
4669
|
-
if (error instanceof AuthMiError && error.statusCode === 401) {
|
|
4670
|
-
return { valid: false, error: "Invalid or expired token" };
|
|
4671
|
-
}
|
|
4672
|
-
throw error;
|
|
4673
|
-
}
|
|
4605
|
+
async isLoggedIn() {
|
|
4606
|
+
const token = await this.storage.getToken();
|
|
4607
|
+
return !!token;
|
|
4674
4608
|
}
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
throw new AuthMiError(
|
|
4683
|
-
result.error || "Authentication required",
|
|
4684
|
-
"UNAUTHORIZED",
|
|
4685
|
-
401
|
|
4686
|
-
);
|
|
4687
|
-
}
|
|
4688
|
-
const hasScopes = requiredScopes.every(
|
|
4689
|
-
(scope) => result.scopes?.includes(scope)
|
|
4690
|
-
);
|
|
4691
|
-
if (!hasScopes) {
|
|
4692
|
-
throw new ScopeError(
|
|
4693
|
-
`Required scopes: ${requiredScopes.join(", ")}`,
|
|
4694
|
-
requiredScopes,
|
|
4695
|
-
result.scopes || []
|
|
4696
|
-
);
|
|
4697
|
-
}
|
|
4698
|
-
return result;
|
|
4699
|
-
}
|
|
4700
|
-
/**
|
|
4701
|
-
* Execute a function only if the user has the required scopes
|
|
4702
|
-
*/
|
|
4703
|
-
async withScope(scopes, fn) {
|
|
4704
|
-
await this.requireScopes(...scopes);
|
|
4705
|
-
return fn();
|
|
4706
|
-
}
|
|
4707
|
-
// ============ OAuth ============
|
|
4708
|
-
/**
|
|
4709
|
-
* Initiate OAuth login flow and return the authorization URL
|
|
4710
|
-
*/
|
|
4711
|
-
async initiateOAuth(provider, redirectUri) {
|
|
4712
|
-
if (!this.config.apiKey && !this.config.clientSecret) {
|
|
4713
|
-
throw new AuthMiError(
|
|
4714
|
-
"API key or client credentials required for OAuth. Configure the client first.",
|
|
4715
|
-
"MISSING_CREDENTIALS"
|
|
4716
|
-
);
|
|
4717
|
-
}
|
|
4718
|
-
if (!this.config.serviceId) {
|
|
4719
|
-
throw new AuthMiError(
|
|
4720
|
-
"serviceId required for OAuth. Configure the client first.",
|
|
4721
|
-
"MISSING_SERVICE_ID"
|
|
4722
|
-
);
|
|
4723
|
-
}
|
|
4724
|
-
const response = await this.request(
|
|
4725
|
-
"/api/v1/auth/oauth/initiate",
|
|
4726
|
-
{
|
|
4727
|
-
method: "POST",
|
|
4728
|
-
body: JSON.stringify({ provider, redirectUri, client_id: this.config.serviceId })
|
|
4729
|
-
}
|
|
4730
|
-
);
|
|
4731
|
-
return response.url;
|
|
4732
|
-
}
|
|
4733
|
-
/**
|
|
4734
|
-
* Handle OAuth callback URL and store the access token
|
|
4735
|
-
* Returns null if no OAuth params are present in the URL
|
|
4736
|
-
*/
|
|
4737
|
-
handleOAuthCallback(url) {
|
|
4738
|
-
const parsedUrl = typeof url === "string" ? new URL(url) : url;
|
|
4739
|
-
const token = parsedUrl.searchParams.get("token");
|
|
4740
|
-
const userId = parsedUrl.searchParams.get("user_id");
|
|
4741
|
-
const email = parsedUrl.searchParams.get("email");
|
|
4742
|
-
if (!token || !userId || !email) {
|
|
4743
|
-
return null;
|
|
4744
|
-
}
|
|
4745
|
-
this.setAccessToken(token);
|
|
4746
|
-
return { token, userId, email };
|
|
4747
|
-
}
|
|
4748
|
-
/**
|
|
4749
|
-
* Check if the current URL contains OAuth callback params
|
|
4750
|
-
*/
|
|
4751
|
-
isOAuthCallback(url) {
|
|
4752
|
-
const parsedUrl = typeof url === "string" ? new URL(url) : url;
|
|
4753
|
-
return parsedUrl.searchParams.has("token") && parsedUrl.searchParams.has("user_id") && parsedUrl.searchParams.has("email");
|
|
4609
|
+
// ============ Auth Endpoints ============
|
|
4610
|
+
async signup(credentials) {
|
|
4611
|
+
const response = await this.request("/api/v1/auth/signup", {
|
|
4612
|
+
method: "POST",
|
|
4613
|
+
body: JSON.stringify(credentials)
|
|
4614
|
+
});
|
|
4615
|
+
return this.mapAuthToken(response);
|
|
4754
4616
|
}
|
|
4755
|
-
// ============ Authentication ============
|
|
4756
|
-
/**
|
|
4757
|
-
* Login a user and store the access token
|
|
4758
|
-
*/
|
|
4759
4617
|
async login(credentials) {
|
|
4760
|
-
|
|
4761
|
-
throw new AuthMiError(
|
|
4762
|
-
"API key or client credentials required for login. Configure the client first.",
|
|
4763
|
-
"MISSING_CREDENTIALS"
|
|
4764
|
-
);
|
|
4765
|
-
}
|
|
4618
|
+
const cfg = this.config;
|
|
4766
4619
|
const response = await this.request("/api/v1/auth/login", {
|
|
4767
4620
|
method: "POST",
|
|
4768
4621
|
body: JSON.stringify({
|
|
4769
4622
|
email: credentials.email,
|
|
4770
4623
|
password: credentials.password,
|
|
4771
|
-
client_id:
|
|
4772
|
-
expires_in_hours: credentials.expiresInHours ||
|
|
4624
|
+
client_id: cfg.serviceId,
|
|
4625
|
+
expires_in_hours: credentials.expiresInHours || cfg.defaultTokenExpiry,
|
|
4773
4626
|
scopes: credentials.scopes
|
|
4774
4627
|
})
|
|
4775
4628
|
});
|
|
4776
|
-
const token =
|
|
4777
|
-
accessToken: response.access_token,
|
|
4778
|
-
tokenType: response.token_type,
|
|
4779
|
-
expiresIn: response.expires_in,
|
|
4780
|
-
expiresAt: response.expires_at,
|
|
4781
|
-
userId: response.user_id,
|
|
4782
|
-
email: response.email,
|
|
4783
|
-
scopes: response.scopes
|
|
4784
|
-
};
|
|
4629
|
+
const token = this.mapAuthToken(response);
|
|
4785
4630
|
this.setAccessToken(token.accessToken);
|
|
4786
4631
|
return token;
|
|
4787
4632
|
}
|
|
4788
|
-
/**
|
|
4789
|
-
* Logout the current user
|
|
4790
|
-
*/
|
|
4791
4633
|
async logout() {
|
|
4792
|
-
const token = this.
|
|
4634
|
+
const token = await this.storage.getToken();
|
|
4793
4635
|
if (token) {
|
|
4794
4636
|
try {
|
|
4795
|
-
await this.request("/api/v1/auth/logout", {
|
|
4796
|
-
|
|
4797
|
-
}, true);
|
|
4798
|
-
} catch (error) {
|
|
4637
|
+
await this.request("/api/v1/auth/logout", { method: "POST" }, true);
|
|
4638
|
+
} catch {
|
|
4799
4639
|
}
|
|
4800
4640
|
}
|
|
4801
4641
|
this.clearAccessToken();
|
|
4802
4642
|
}
|
|
4803
|
-
/**
|
|
4804
|
-
* Validate the current token or an API key
|
|
4805
|
-
* @deprecated Use validateWithScopes instead
|
|
4806
|
-
*/
|
|
4807
|
-
async validate(_credential) {
|
|
4808
|
-
return this.validateWithScopes();
|
|
4809
|
-
}
|
|
4810
|
-
/**
|
|
4811
|
-
* Refresh the current token
|
|
4812
|
-
*/
|
|
4813
4643
|
async refreshToken() {
|
|
4814
|
-
const response = await this.request("/api/v1/auth/refresh", {
|
|
4815
|
-
method: "POST"
|
|
4816
|
-
}, true);
|
|
4644
|
+
const response = await this.request("/api/v1/auth/refresh", { method: "POST" }, true);
|
|
4817
4645
|
const token = {
|
|
4818
4646
|
accessToken: response.access_token,
|
|
4819
|
-
tokenType:
|
|
4647
|
+
tokenType: "Bearer",
|
|
4820
4648
|
expiresIn: response.expires_in,
|
|
4821
4649
|
expiresAt: response.expires_at,
|
|
4822
4650
|
userId: "",
|
|
4823
|
-
// Refresh doesn't return user info
|
|
4824
4651
|
email: ""
|
|
4825
4652
|
};
|
|
4826
4653
|
this.setAccessToken(token.accessToken);
|
|
4827
4654
|
return token;
|
|
4828
4655
|
}
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
async
|
|
4834
|
-
|
|
4656
|
+
async getMe() {
|
|
4657
|
+
const response = await this.request("/api/v1/auth/me");
|
|
4658
|
+
return { userId: response.user_id, email: response.email, name: response.name, createdAt: response.created_at };
|
|
4659
|
+
}
|
|
4660
|
+
async forgotPassword(request) {
|
|
4661
|
+
return this.request("/api/v1/auth/forgot-password", {
|
|
4835
4662
|
method: "POST",
|
|
4836
|
-
body: JSON.stringify(request)
|
|
4663
|
+
body: JSON.stringify({ email: request.email, client_id: this.config.serviceId })
|
|
4664
|
+
});
|
|
4665
|
+
}
|
|
4666
|
+
async resetPassword(request) {
|
|
4667
|
+
return this.request("/api/v1/auth/reset-password", {
|
|
4668
|
+
method: "POST",
|
|
4669
|
+
body: JSON.stringify({ token: request.token, new_password: request.newPassword })
|
|
4670
|
+
});
|
|
4671
|
+
}
|
|
4672
|
+
async verifyEmail(request) {
|
|
4673
|
+
return this.request("/api/v1/auth/verify-email", {
|
|
4674
|
+
method: "POST",
|
|
4675
|
+
body: JSON.stringify({ token: request.token })
|
|
4676
|
+
});
|
|
4677
|
+
}
|
|
4678
|
+
async resendVerification(request) {
|
|
4679
|
+
return this.request("/api/v1/auth/resend-verification", {
|
|
4680
|
+
method: "POST",
|
|
4681
|
+
body: JSON.stringify({ email: request.email, client_id: this.config.serviceId })
|
|
4837
4682
|
});
|
|
4683
|
+
}
|
|
4684
|
+
async deactivateAccount(password) {
|
|
4685
|
+
await this.request("/api/v1/auth/deactivate", {
|
|
4686
|
+
method: "POST",
|
|
4687
|
+
body: JSON.stringify({ password })
|
|
4688
|
+
});
|
|
4689
|
+
}
|
|
4690
|
+
mapAuthToken(raw) {
|
|
4838
4691
|
return {
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4692
|
+
accessToken: raw.access_token,
|
|
4693
|
+
tokenType: raw.token_type,
|
|
4694
|
+
expiresIn: raw.expires_in,
|
|
4695
|
+
expiresAt: raw.expires_at,
|
|
4696
|
+
userId: raw.user_id,
|
|
4697
|
+
email: raw.email,
|
|
4698
|
+
emailVerified: raw.email_verified,
|
|
4699
|
+
scopes: raw.scopes
|
|
4842
4700
|
};
|
|
4843
4701
|
}
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4702
|
+
// ============ OAuth ============
|
|
4703
|
+
async initiateOAuth(provider, redirectUri) {
|
|
4704
|
+
const cfg = this.config;
|
|
4705
|
+
if (!cfg.clientId && !cfg.clientSecret && !cfg.apiKey) {
|
|
4706
|
+
throw new AuthMiError("Credentials required for OAuth", "MISSING_CREDENTIALS");
|
|
4707
|
+
}
|
|
4708
|
+
const response = await this.request("/api/v1/auth/oauth/initiate", {
|
|
4709
|
+
method: "POST",
|
|
4710
|
+
body: JSON.stringify({ provider, redirectUri, client_id: cfg.serviceId || cfg.clientId })
|
|
4711
|
+
});
|
|
4712
|
+
return response.url;
|
|
4713
|
+
}
|
|
4714
|
+
handleOAuthCallback(url) {
|
|
4715
|
+
const parsed = typeof url === "string" ? new URL(url) : url;
|
|
4716
|
+
const token = parsed.searchParams.get("token");
|
|
4717
|
+
const userId = parsed.searchParams.get("user_id");
|
|
4718
|
+
const email = parsed.searchParams.get("email");
|
|
4719
|
+
if (!token || !userId || !email) return null;
|
|
4720
|
+
this.setAccessToken(token);
|
|
4721
|
+
return { token, userId, email };
|
|
4722
|
+
}
|
|
4723
|
+
isOAuthCallback(url) {
|
|
4724
|
+
const parsed = typeof url === "string" ? new URL(url) : url;
|
|
4725
|
+
return !!(parsed.searchParams.has("token") && parsed.searchParams.has("user_id") && parsed.searchParams.has("email"));
|
|
4726
|
+
}
|
|
4727
|
+
// ============ SAML ============
|
|
4728
|
+
async initiateSaml(request) {
|
|
4729
|
+
return this.request("/api/v1/auth/saml/initiate", {
|
|
4730
|
+
method: "POST",
|
|
4731
|
+
body: JSON.stringify({ email: request.email, redirect_uri: request.redirectUri })
|
|
4732
|
+
});
|
|
4733
|
+
}
|
|
4734
|
+
async parseSamlMetadata(xml) {
|
|
4735
|
+
return this.request("/api/v1/auth/saml/parse-metadata", {
|
|
4736
|
+
method: "POST",
|
|
4737
|
+
body: JSON.stringify({ metadata_xml: xml })
|
|
4738
|
+
});
|
|
4739
|
+
}
|
|
4740
|
+
async listSamlConnections() {
|
|
4741
|
+
const response = await this.request("/api/v1/auth/saml/connections");
|
|
4742
|
+
return response.connections;
|
|
4743
|
+
}
|
|
4744
|
+
async createSamlConnection(request) {
|
|
4745
|
+
return this.request("/api/v1/auth/saml/connections", {
|
|
4746
|
+
method: "POST",
|
|
4747
|
+
body: JSON.stringify(request)
|
|
4748
|
+
});
|
|
4749
|
+
}
|
|
4750
|
+
async deleteSamlConnection(id) {
|
|
4751
|
+
await this.request(`/api/v1/auth/saml/connections/${encodeURIComponent(id)}`, {
|
|
4752
|
+
method: "DELETE"
|
|
4753
|
+
});
|
|
4754
|
+
}
|
|
4755
|
+
// ============ 2FA ============
|
|
4756
|
+
async setup2fa() {
|
|
4757
|
+
return this.request("/api/v1/auth/2fa/setup", { method: "POST" });
|
|
4758
|
+
}
|
|
4759
|
+
async enable2fa(code) {
|
|
4760
|
+
return this.request("/api/v1/auth/2fa/enable", {
|
|
4761
|
+
method: "POST",
|
|
4762
|
+
body: JSON.stringify({ code })
|
|
4763
|
+
});
|
|
4764
|
+
}
|
|
4765
|
+
async disable2fa(password) {
|
|
4766
|
+
await this.request("/api/v1/auth/2fa/disable", {
|
|
4767
|
+
method: "POST",
|
|
4768
|
+
body: JSON.stringify({ password })
|
|
4769
|
+
});
|
|
4770
|
+
}
|
|
4771
|
+
async regenerateBackupCodes() {
|
|
4772
|
+
return this.request("/api/v1/auth/2fa/backup-codes", { method: "POST" });
|
|
4773
|
+
}
|
|
4774
|
+
async challenge2fa(request) {
|
|
4775
|
+
return this.request("/api/v1/auth/2fa/challenge", {
|
|
4776
|
+
method: "POST",
|
|
4777
|
+
body: JSON.stringify(request)
|
|
4778
|
+
});
|
|
4779
|
+
}
|
|
4780
|
+
// ============ Users ============
|
|
4781
|
+
async createUser(request) {
|
|
4782
|
+
const response = await this.request(
|
|
4783
|
+
"/api/v1/users/create",
|
|
4784
|
+
{
|
|
4785
|
+
method: "POST",
|
|
4786
|
+
body: JSON.stringify(request)
|
|
4787
|
+
}
|
|
4788
|
+
);
|
|
4789
|
+
return { userId: response.user_id, email: response.email, name: response.name, createdAt: response.created_at };
|
|
4790
|
+
}
|
|
4847
4791
|
async listUsers() {
|
|
4848
4792
|
const response = await this.request("/api/v1/users/list");
|
|
4849
4793
|
return response.users.map((u) => ({
|
|
4850
4794
|
userId: u.user_id,
|
|
4851
4795
|
email: u.email,
|
|
4796
|
+
name: u.name,
|
|
4852
4797
|
createdAt: u.created_at
|
|
4853
4798
|
}));
|
|
4854
4799
|
}
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4800
|
+
async getUser(userId) {
|
|
4801
|
+
const response = await this.request(
|
|
4802
|
+
`/api/v1/users/${encodeURIComponent(userId)}`
|
|
4803
|
+
);
|
|
4804
|
+
return { userId: response.user_id, email: response.email, name: response.name, createdAt: response.created_at };
|
|
4805
|
+
}
|
|
4858
4806
|
async deleteUser(userId) {
|
|
4859
4807
|
await this.request("/api/v1/users/delete", {
|
|
4860
4808
|
method: "POST",
|
|
4861
4809
|
body: JSON.stringify({ user_id: userId })
|
|
4862
4810
|
});
|
|
4863
4811
|
}
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4812
|
+
async deleteUserById(userId) {
|
|
4813
|
+
await this.request(`/api/v1/users/${encodeURIComponent(userId)}`, { method: "DELETE" });
|
|
4814
|
+
}
|
|
4867
4815
|
async updatePassword(userId, oldPassword, newPassword) {
|
|
4868
4816
|
await this.request("/api/v1/users/password", {
|
|
4869
4817
|
method: "POST",
|
|
4870
|
-
body: JSON.stringify({
|
|
4871
|
-
user_id: userId,
|
|
4872
|
-
old_password: oldPassword,
|
|
4873
|
-
new_password: newPassword
|
|
4874
|
-
})
|
|
4818
|
+
body: JSON.stringify({ user_id: userId, old_password: oldPassword, new_password: newPassword })
|
|
4875
4819
|
});
|
|
4876
4820
|
}
|
|
4877
|
-
// ============
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
return response.
|
|
4821
|
+
// ============ Roles ============
|
|
4822
|
+
async createRole(request) {
|
|
4823
|
+
const response = await this.request(
|
|
4824
|
+
"/api/v1/users/roles/create",
|
|
4825
|
+
{ method: "POST", body: JSON.stringify(request) }
|
|
4826
|
+
);
|
|
4827
|
+
return { roleId: response.role_id, name: response.name, description: response.description, createdAt: response.created_at };
|
|
4884
4828
|
}
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4829
|
+
async listRoles() {
|
|
4830
|
+
const response = await this.request("/api/v1/users/roles/list");
|
|
4831
|
+
return response.roles.map((r) => ({
|
|
4832
|
+
roleId: r.role_id,
|
|
4833
|
+
name: r.name,
|
|
4834
|
+
description: r.description,
|
|
4835
|
+
createdAt: r.created_at
|
|
4836
|
+
}));
|
|
4837
|
+
}
|
|
4838
|
+
async deleteRole(roleId) {
|
|
4839
|
+
await this.request(`/api/v1/users/roles/${encodeURIComponent(roleId)}`, { method: "DELETE" });
|
|
4840
|
+
}
|
|
4841
|
+
async assignRole(userId, roleId) {
|
|
4842
|
+
await this.request("/api/v1/users/roles/assign", {
|
|
4890
4843
|
method: "POST",
|
|
4891
|
-
body: JSON.stringify(
|
|
4844
|
+
body: JSON.stringify({ user_id: userId, role_id: roleId })
|
|
4892
4845
|
});
|
|
4893
|
-
return {
|
|
4894
|
-
scopeId: response.scope_id,
|
|
4895
|
-
name: response.name,
|
|
4896
|
-
key: response.key,
|
|
4897
|
-
description: response.description,
|
|
4898
|
-
createdAt: response.created_at
|
|
4899
|
-
};
|
|
4900
4846
|
}
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
*/
|
|
4904
|
-
async deleteScope(scopeId) {
|
|
4905
|
-
await this.request("/api/v1/scopes/delete", {
|
|
4847
|
+
async unassignRole(userId, roleId) {
|
|
4848
|
+
await this.request("/api/v1/users/roles/unassign", {
|
|
4906
4849
|
method: "POST",
|
|
4907
|
-
body: JSON.stringify({
|
|
4850
|
+
body: JSON.stringify({ user_id: userId, role_id: roleId })
|
|
4908
4851
|
});
|
|
4909
4852
|
}
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4853
|
+
async getUserRoles(userId) {
|
|
4854
|
+
const response = await this.request(
|
|
4855
|
+
`/api/v1/users/${encodeURIComponent(userId)}/roles`
|
|
4856
|
+
);
|
|
4857
|
+
return response.roles.map((r) => ({
|
|
4858
|
+
roleId: r.role_id,
|
|
4859
|
+
name: r.name,
|
|
4860
|
+
description: r.description,
|
|
4861
|
+
createdAt: r.created_at
|
|
4862
|
+
}));
|
|
4863
|
+
}
|
|
4864
|
+
// ============ API Keys ============
|
|
4914
4865
|
async listApiKeys() {
|
|
4915
4866
|
const response = await this.request("/api/v1/keys/list");
|
|
4916
4867
|
return response.keys.map((k) => ({
|
|
4917
4868
|
keyId: k.keyId,
|
|
4918
4869
|
name: k.name,
|
|
4919
4870
|
scope: k.scope,
|
|
4920
|
-
scopes:
|
|
4871
|
+
scopes: k.scopes,
|
|
4921
4872
|
keyType: k.keyType,
|
|
4873
|
+
tpsLimit: k.tpsLimit,
|
|
4922
4874
|
revoked: k.revoked,
|
|
4923
|
-
createdAt: k.createdAt
|
|
4924
|
-
tpsLimit: k.tpsLimit
|
|
4875
|
+
createdAt: k.createdAt
|
|
4925
4876
|
}));
|
|
4926
4877
|
}
|
|
4927
|
-
/**
|
|
4928
|
-
* Create a new API key with optional custom scopes
|
|
4929
|
-
*/
|
|
4930
4878
|
async createApiKey(request) {
|
|
4931
|
-
const response = await this.request(
|
|
4879
|
+
const response = await this.request(
|
|
4880
|
+
"/api/v1/keys/create",
|
|
4881
|
+
{
|
|
4882
|
+
method: "POST",
|
|
4883
|
+
body: JSON.stringify({
|
|
4884
|
+
user_id: request.userId,
|
|
4885
|
+
name: request.name,
|
|
4886
|
+
scope: request.scope || "service",
|
|
4887
|
+
scopes: request.scopes,
|
|
4888
|
+
key_type: request.keyType || "service",
|
|
4889
|
+
tps_limit: request.tpsLimit || 100
|
|
4890
|
+
})
|
|
4891
|
+
}
|
|
4892
|
+
);
|
|
4893
|
+
return { keyId: response.key_id, apiKey: response.api_key, name: response.name, scope: response.scope, scopes: response.scopes };
|
|
4894
|
+
}
|
|
4895
|
+
async revokeApiKey(keyId) {
|
|
4896
|
+
await this.request("/api/v1/keys/revoke", {
|
|
4897
|
+
method: "POST",
|
|
4898
|
+
body: JSON.stringify({ key_id: keyId })
|
|
4899
|
+
});
|
|
4900
|
+
}
|
|
4901
|
+
// ============ Scopes ============
|
|
4902
|
+
async listScopes() {
|
|
4903
|
+
const response = await this.request("/api/v1/scopes/list");
|
|
4904
|
+
return response.scopes;
|
|
4905
|
+
}
|
|
4906
|
+
async createScope(request) {
|
|
4907
|
+
const response = await this.request(
|
|
4908
|
+
"/api/v1/scopes/create",
|
|
4909
|
+
{ method: "POST", body: JSON.stringify(request) }
|
|
4910
|
+
);
|
|
4911
|
+
return { scopeId: response.scope_id, name: response.name, key: response.key, description: response.description, createdAt: response.created_at };
|
|
4912
|
+
}
|
|
4913
|
+
async deleteScope(scopeId) {
|
|
4914
|
+
await this.request("/api/v1/scopes/delete", {
|
|
4915
|
+
method: "POST",
|
|
4916
|
+
body: JSON.stringify({ scope_id: scopeId })
|
|
4917
|
+
});
|
|
4918
|
+
}
|
|
4919
|
+
// ============ Introspection & Validation ============
|
|
4920
|
+
async introspect(request) {
|
|
4921
|
+
if (this.cache && request.token) {
|
|
4922
|
+
const cached = this.cache.get(request.token);
|
|
4923
|
+
if (cached) return cached;
|
|
4924
|
+
}
|
|
4925
|
+
const result = await this.request("/api/v1/introspect", {
|
|
4932
4926
|
method: "POST",
|
|
4933
4927
|
body: JSON.stringify({
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
key_type: request.keyType || "service",
|
|
4939
|
-
tps_limit: request.tpsLimit || 100
|
|
4928
|
+
serviceId: request.serviceId,
|
|
4929
|
+
token: request.token,
|
|
4930
|
+
apiKey: request.apiKey,
|
|
4931
|
+
requiredScopes: request.requiredScopes
|
|
4940
4932
|
})
|
|
4941
4933
|
});
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
scope: response.scope,
|
|
4947
|
-
scopes: response.scopes
|
|
4948
|
-
};
|
|
4934
|
+
if (this.cache && request.token) {
|
|
4935
|
+
this.cache.set(request.token, result);
|
|
4936
|
+
}
|
|
4937
|
+
return result;
|
|
4949
4938
|
}
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4939
|
+
async validate() {
|
|
4940
|
+
const cfg = this.config;
|
|
4941
|
+
const token = await this.storage.getToken();
|
|
4942
|
+
if (!token) return { valid: false, error: "No token stored" };
|
|
4943
|
+
if (!cfg.serviceId) return { valid: false, error: "Service ID not configured" };
|
|
4944
|
+
if (!cfg.apiKey && !cfg.clientSecret) return { valid: false, error: "Service credentials not configured" };
|
|
4945
|
+
try {
|
|
4946
|
+
const result = await this.introspect({ serviceId: cfg.serviceId, token });
|
|
4947
|
+
return {
|
|
4948
|
+
valid: result.valid,
|
|
4949
|
+
type: result.type === "bearer" ? "token" : "api_key",
|
|
4950
|
+
scopes: result.scopes,
|
|
4951
|
+
userId: result.userId,
|
|
4952
|
+
email: result.email,
|
|
4953
|
+
error: result.error
|
|
4954
|
+
};
|
|
4955
|
+
} catch (error) {
|
|
4956
|
+
if (error instanceof ScopeError) {
|
|
4957
|
+
return { valid: false, error: error.message, scopes: error.providedScopes };
|
|
4958
|
+
}
|
|
4959
|
+
if (error instanceof AuthMiError && error.statusCode === 401) {
|
|
4960
|
+
return { valid: false, error: "Invalid or expired token" };
|
|
4961
|
+
}
|
|
4962
|
+
throw error;
|
|
4963
|
+
}
|
|
4964
|
+
}
|
|
4965
|
+
async validateWithScopes(requiredScopes) {
|
|
4966
|
+
const cfg = this.config;
|
|
4967
|
+
const token = await this.storage.getToken();
|
|
4968
|
+
if (!token) return { valid: false, error: "No token provided" };
|
|
4969
|
+
if (!cfg.apiKey && !cfg.clientSecret) return { valid: false, error: "Service credentials not configured" };
|
|
4970
|
+
if (!cfg.serviceId) return { valid: false, error: "Service ID not configured" };
|
|
4971
|
+
try {
|
|
4972
|
+
const result = await this.introspect({ serviceId: cfg.serviceId, token, requiredScopes });
|
|
4973
|
+
return {
|
|
4974
|
+
valid: result.valid,
|
|
4975
|
+
type: result.type === "bearer" ? "token" : "api_key",
|
|
4976
|
+
scopes: result.scopes,
|
|
4977
|
+
userId: result.userId,
|
|
4978
|
+
email: result.email,
|
|
4979
|
+
error: result.error
|
|
4980
|
+
};
|
|
4981
|
+
} catch (error) {
|
|
4982
|
+
if (error instanceof ScopeError) {
|
|
4983
|
+
return { valid: false, error: error.message, scopes: error.providedScopes };
|
|
4984
|
+
}
|
|
4985
|
+
if (error instanceof AuthMiError && error.statusCode === 401) {
|
|
4986
|
+
return { valid: false, error: "Invalid or expired token" };
|
|
4987
|
+
}
|
|
4988
|
+
throw error;
|
|
4989
|
+
}
|
|
4990
|
+
}
|
|
4991
|
+
async requireScopes(...requiredScopes) {
|
|
4992
|
+
const result = await this.validateWithScopes(requiredScopes);
|
|
4993
|
+
if (!result.valid) {
|
|
4994
|
+
throw new AuthMiError(result.error || "Authentication required", "UNAUTHORIZED", 401);
|
|
4995
|
+
}
|
|
4996
|
+
const hasScopes = requiredScopes.every((s) => result.scopes?.includes(s));
|
|
4997
|
+
if (!hasScopes) {
|
|
4998
|
+
throw new ScopeError(`Required: ${requiredScopes.join(", ")}`, requiredScopes, result.scopes || []);
|
|
4999
|
+
}
|
|
5000
|
+
return result;
|
|
5001
|
+
}
|
|
5002
|
+
async withScope(scopes, fn) {
|
|
5003
|
+
await this.requireScopes(...scopes);
|
|
5004
|
+
return fn();
|
|
5005
|
+
}
|
|
5006
|
+
// ============ Webhooks ============
|
|
5007
|
+
async listWebhooks() {
|
|
5008
|
+
const response = await this.request("/api/v1/webhooks/list");
|
|
5009
|
+
return response.webhooks;
|
|
5010
|
+
}
|
|
5011
|
+
async registerWebhook(request) {
|
|
5012
|
+
const response = await this.request(
|
|
5013
|
+
"/api/v1/webhooks/register",
|
|
5014
|
+
{ method: "POST", body: JSON.stringify(request) }
|
|
5015
|
+
);
|
|
5016
|
+
return { webhookId: response.webhook_id, url: response.url, events: response.events, active: response.active, createdAt: response.created_at };
|
|
5017
|
+
}
|
|
5018
|
+
async deleteWebhook(webhookId) {
|
|
5019
|
+
await this.request("/api/v1/webhooks/delete", {
|
|
4955
5020
|
method: "POST",
|
|
4956
|
-
body: JSON.stringify({
|
|
5021
|
+
body: JSON.stringify({ webhook_id: webhookId })
|
|
5022
|
+
});
|
|
5023
|
+
}
|
|
5024
|
+
// ============ Billing ============
|
|
5025
|
+
async listPlans() {
|
|
5026
|
+
const response = await this.request("/api/v1/billing/plans");
|
|
5027
|
+
return response.plans;
|
|
5028
|
+
}
|
|
5029
|
+
async getSubscription() {
|
|
5030
|
+
return this.request("/api/v1/billing/subscription");
|
|
5031
|
+
}
|
|
5032
|
+
async createCheckout(priceId) {
|
|
5033
|
+
return this.request("/api/v1/billing/checkout", {
|
|
5034
|
+
method: "POST",
|
|
5035
|
+
body: JSON.stringify({ price_id: priceId })
|
|
5036
|
+
});
|
|
5037
|
+
}
|
|
5038
|
+
async createPortalSession() {
|
|
5039
|
+
return this.request("/api/v1/billing/portal", { method: "POST" });
|
|
5040
|
+
}
|
|
5041
|
+
// ============ Audit ============
|
|
5042
|
+
async getAuditLogs(query) {
|
|
5043
|
+
const params = new URLSearchParams();
|
|
5044
|
+
if (query?.limit) params.set("limit", String(query.limit));
|
|
5045
|
+
if (query?.offset) params.set("offset", String(query.offset));
|
|
5046
|
+
if (query?.actorId) params.set("actor_id", query.actorId);
|
|
5047
|
+
if (query?.action) params.set("action", query.action);
|
|
5048
|
+
if (query?.resourceType) params.set("resource_type", query.resourceType);
|
|
5049
|
+
if (query?.startDate) params.set("start_date", query.startDate);
|
|
5050
|
+
if (query?.endDate) params.set("end_date", query.endDate);
|
|
5051
|
+
const qs = params.toString();
|
|
5052
|
+
const response = await this.request(
|
|
5053
|
+
`/api/v1/audit-logs${qs ? `?${qs}` : ""}`
|
|
5054
|
+
);
|
|
5055
|
+
return response.logs;
|
|
5056
|
+
}
|
|
5057
|
+
// ============ Services ============
|
|
5058
|
+
async getService(serviceId) {
|
|
5059
|
+
return this.request(`/api/v1/services/${encodeURIComponent(serviceId)}`);
|
|
5060
|
+
}
|
|
5061
|
+
async updateService(serviceId, data) {
|
|
5062
|
+
return this.request(`/api/v1/services/${encodeURIComponent(serviceId)}`, {
|
|
5063
|
+
method: "POST",
|
|
5064
|
+
body: JSON.stringify(data)
|
|
4957
5065
|
});
|
|
4958
5066
|
}
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
5067
|
+
async rotateClientSecret(serviceId) {
|
|
5068
|
+
return this.request(
|
|
5069
|
+
`/api/v1/services/${encodeURIComponent(serviceId)}/rotate-secret`,
|
|
5070
|
+
{ method: "POST" }
|
|
5071
|
+
);
|
|
5072
|
+
}
|
|
5073
|
+
// ============ JWKS ============
|
|
5074
|
+
async getJwks(serviceId) {
|
|
5075
|
+
return this.request(`/.well-known/jwks.json?service_id=${encodeURIComponent(serviceId)}`);
|
|
5076
|
+
}
|
|
5077
|
+
// ============ Onboarding (admin only) ============
|
|
4963
5078
|
async onboardService(request, masterAdminKey) {
|
|
4964
5079
|
const response = await this.request("/api/v1/services/onboard", {
|
|
4965
5080
|
method: "POST",
|
|
@@ -4980,9 +5095,6 @@ var AuthMiClient = class {
|
|
|
4980
5095
|
createdAt: response.created_at
|
|
4981
5096
|
};
|
|
4982
5097
|
}
|
|
4983
|
-
/**
|
|
4984
|
-
* Delete a service (requires master admin key)
|
|
4985
|
-
*/
|
|
4986
5098
|
async deleteService(serviceId, masterAdminKey) {
|
|
4987
5099
|
await this.request("/api/v1/services/deboard", {
|
|
4988
5100
|
method: "POST",
|
|
@@ -4992,45 +5104,9 @@ var AuthMiClient = class {
|
|
|
4992
5104
|
body: JSON.stringify({ service_id: serviceId })
|
|
4993
5105
|
});
|
|
4994
5106
|
}
|
|
4995
|
-
// ============ Webhook Management ============
|
|
4996
|
-
/**
|
|
4997
|
-
* List webhooks
|
|
4998
|
-
*/
|
|
4999
|
-
async listWebhooks() {
|
|
5000
|
-
const response = await this.request(
|
|
5001
|
-
"/api/v1/webhooks/list"
|
|
5002
|
-
);
|
|
5003
|
-
return response.webhooks;
|
|
5004
|
-
}
|
|
5005
|
-
/**
|
|
5006
|
-
* Register a webhook
|
|
5007
|
-
*/
|
|
5008
|
-
async registerWebhook(request) {
|
|
5009
|
-
const response = await this.request("/api/v1/webhooks/register", {
|
|
5010
|
-
method: "POST",
|
|
5011
|
-
body: JSON.stringify(request)
|
|
5012
|
-
});
|
|
5013
|
-
return {
|
|
5014
|
-
webhookId: response.webhook_id,
|
|
5015
|
-
url: response.url,
|
|
5016
|
-
events: response.events,
|
|
5017
|
-
active: response.active,
|
|
5018
|
-
createdAt: response.created_at
|
|
5019
|
-
};
|
|
5020
|
-
}
|
|
5021
|
-
/**
|
|
5022
|
-
* Delete a webhook
|
|
5023
|
-
*/
|
|
5024
|
-
async deleteWebhook(webhookId) {
|
|
5025
|
-
await this.request("/api/v1/webhooks/delete", {
|
|
5026
|
-
method: "POST",
|
|
5027
|
-
body: JSON.stringify({ webhook_id: webhookId })
|
|
5028
|
-
});
|
|
5029
|
-
}
|
|
5030
5107
|
};
|
|
5031
5108
|
|
|
5032
5109
|
// src/next.tsx
|
|
5033
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
5034
5110
|
function createAuthMiMiddleware(options) {
|
|
5035
5111
|
return async function middleware(request) {
|
|
5036
5112
|
const {
|
|
@@ -5048,10 +5124,7 @@ function createAuthMiMiddleware(options) {
|
|
|
5048
5124
|
}
|
|
5049
5125
|
const token = request.cookies.get("authmi_token")?.value || request.headers.get("Authorization")?.replace("Bearer ", "");
|
|
5050
5126
|
if (!token) {
|
|
5051
|
-
if (protectedPaths.some((p) => pathname.startsWith(p))) {
|
|
5052
|
-
return import_server.NextResponse.redirect(new URL(loginPath, request.url));
|
|
5053
|
-
}
|
|
5054
|
-
if (Object.keys(scopedPaths).some((p) => pathname.startsWith(p))) {
|
|
5127
|
+
if (protectedPaths.some((p) => pathname.startsWith(p)) || Object.keys(scopedPaths).some((p) => pathname.startsWith(p))) {
|
|
5055
5128
|
return import_server.NextResponse.redirect(new URL(loginPath, request.url));
|
|
5056
5129
|
}
|
|
5057
5130
|
return import_server.NextResponse.next();
|
|
@@ -5083,9 +5156,7 @@ function createAuthMiMiddleware(options) {
|
|
|
5083
5156
|
requestHeaders.set("x-user-email", introspectResult.email || "");
|
|
5084
5157
|
requestHeaders.set("x-user-scopes", JSON.stringify(introspectResult.scopes || []));
|
|
5085
5158
|
return import_server.NextResponse.next({
|
|
5086
|
-
request: {
|
|
5087
|
-
headers: requestHeaders
|
|
5088
|
-
}
|
|
5159
|
+
request: { headers: requestHeaders }
|
|
5089
5160
|
});
|
|
5090
5161
|
} catch (error) {
|
|
5091
5162
|
console.error("Auth middleware error:", error);
|
|
@@ -5096,11 +5167,6 @@ function createAuthMiMiddleware(options) {
|
|
|
5096
5167
|
}
|
|
5097
5168
|
};
|
|
5098
5169
|
}
|
|
5099
|
-
function withScope(Component, _requiredScopes, _config) {
|
|
5100
|
-
return function WithScopeWrapper(props) {
|
|
5101
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ...props });
|
|
5102
|
-
};
|
|
5103
|
-
}
|
|
5104
5170
|
async function validateScopes(request, options) {
|
|
5105
5171
|
const { baseUrl, apiKey, requiredScopes, serviceId } = options;
|
|
5106
5172
|
const authHeader = request.headers.get("Authorization");
|
|
@@ -5109,12 +5175,9 @@ async function validateScopes(request, options) {
|
|
|
5109
5175
|
return { valid: false, error: "No token provided", status: 401 };
|
|
5110
5176
|
}
|
|
5111
5177
|
const client = new AuthMiClient({ baseUrl, apiKey, serviceId });
|
|
5112
|
-
if (!serviceId) {
|
|
5113
|
-
return { valid: false, error: "Service ID not configured", status: 500 };
|
|
5114
|
-
}
|
|
5115
5178
|
try {
|
|
5116
5179
|
const result = await client.introspect({
|
|
5117
|
-
serviceId
|
|
5180
|
+
serviceId,
|
|
5118
5181
|
token,
|
|
5119
5182
|
requiredScopes
|
|
5120
5183
|
});
|
|
@@ -5139,10 +5202,7 @@ async function validateScopes(request, options) {
|
|
|
5139
5202
|
0 && (module.exports = {
|
|
5140
5203
|
AuthMiClient,
|
|
5141
5204
|
AuthMiError,
|
|
5142
|
-
LocalStorageTokenStorage,
|
|
5143
|
-
MemoryTokenStorage,
|
|
5144
5205
|
ScopeError,
|
|
5145
5206
|
createAuthMiMiddleware,
|
|
5146
|
-
validateScopes
|
|
5147
|
-
withScope
|
|
5207
|
+
validateScopes
|
|
5148
5208
|
});
|