@authsec/sdk 4.0.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 +253 -0
- package/dist/ciba.d.ts +47 -0
- package/dist/ciba.d.ts.map +1 -0
- package/dist/ciba.js +172 -0
- package/dist/ciba.js.map +1 -0
- package/dist/config.d.ts +32 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +92 -0
- package/dist/config.js.map +1 -0
- package/dist/decorators.d.ts +59 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +142 -0
- package/dist/decorators.js.map +1 -0
- package/dist/http.d.ts +19 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +156 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server.d.ts +42 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +353 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/rbac.d.ts +12 -0
- package/dist/rbac.d.ts.map +1 -0
- package/dist/rbac.js +130 -0
- package/dist/rbac.js.map +1 -0
- package/dist/service-access.d.ts +31 -0
- package/dist/service-access.d.ts.map +1 -0
- package/dist/service-access.js +82 -0
- package/dist/service-access.js.map +1 -0
- package/dist/spiffe/index.d.ts +4 -0
- package/dist/spiffe/index.d.ts.map +1 -0
- package/dist/spiffe/index.js +10 -0
- package/dist/spiffe/index.js.map +1 -0
- package/dist/spiffe/proto/workload.proto +126 -0
- package/dist/spiffe/quick-start-svid.d.ts +74 -0
- package/dist/spiffe/quick-start-svid.d.ts.map +1 -0
- package/dist/spiffe/quick-start-svid.js +191 -0
- package/dist/spiffe/quick-start-svid.js.map +1 -0
- package/dist/spiffe/workload-api-client.d.ts +71 -0
- package/dist/spiffe/workload-api-client.d.ts.map +1 -0
- package/dist/spiffe/workload-api-client.js +355 -0
- package/dist/spiffe/workload-api-client.js.map +1 -0
- package/dist/spiffe/workload-svid.d.ts +44 -0
- package/dist/spiffe/workload-svid.d.ts.map +1 -0
- package/dist/spiffe/workload-svid.js +137 -0
- package/dist/spiffe/workload-svid.js.map +1 -0
- package/dist/types.d.ts +95 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -0
- package/src/spiffe/proto/workload.proto +126 -0
package/README.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# AuthSec TypeScript SDK (`@authsec/sdk`)
|
|
2
|
+
|
|
3
|
+
Add OAuth + RBAC protection to MCP tools and wrappers in TypeScript/JavaScript.
|
|
4
|
+
|
|
5
|
+
This SDK lets you:
|
|
6
|
+
- Protect tools with `protectedByAuthSec(...)`
|
|
7
|
+
- Register public tools with `mcpTool(...)`
|
|
8
|
+
- Run an MCP server with `runMcpServerWithOAuth(...)`
|
|
9
|
+
- Wrap another MCP server (for example memory server) and enforce AuthSec in front of it
|
|
10
|
+
|
|
11
|
+
## Package
|
|
12
|
+
|
|
13
|
+
- Name: `@authsec/sdk`
|
|
14
|
+
- Node: `>=18`
|
|
15
|
+
- Entry: `dist/index.js`
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
cd packages/typescript-sdk
|
|
21
|
+
npm install
|
|
22
|
+
npm run build
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Consumer install:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @authsec/sdk
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import {
|
|
35
|
+
mcpTool,
|
|
36
|
+
protectedByAuthSec,
|
|
37
|
+
runMcpServerWithOAuth,
|
|
38
|
+
} from "@authsec/sdk";
|
|
39
|
+
|
|
40
|
+
const ping = mcpTool(
|
|
41
|
+
{
|
|
42
|
+
name: "ping",
|
|
43
|
+
description: "Health check",
|
|
44
|
+
inputSchema: {
|
|
45
|
+
type: "object",
|
|
46
|
+
properties: {},
|
|
47
|
+
required: [],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
async () => [{ type: "text", text: "pong" }]
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const deleteInvoice = protectedByAuthSec(
|
|
54
|
+
{
|
|
55
|
+
toolName: "delete_invoice",
|
|
56
|
+
roles: ["admin"],
|
|
57
|
+
scopes: ["write"],
|
|
58
|
+
requireAll: true,
|
|
59
|
+
description: "Delete invoice by id",
|
|
60
|
+
inputSchema: {
|
|
61
|
+
type: "object",
|
|
62
|
+
properties: {
|
|
63
|
+
invoice_id: { type: "string" },
|
|
64
|
+
session_id: { type: "string" },
|
|
65
|
+
},
|
|
66
|
+
required: ["invoice_id"],
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
async (args) => {
|
|
70
|
+
const user = args?._user_info?.email_id ?? "unknown-user";
|
|
71
|
+
return [{ type: "text", text: `Deleted ${args.invoice_id} by ${user}` }];
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
runMcpServerWithOAuth({
|
|
76
|
+
tools: [ping, deleteInvoice],
|
|
77
|
+
clientId: process.env.AUTHSEC_CLIENT_ID!,
|
|
78
|
+
appName: "my-ts-mcp",
|
|
79
|
+
host: "127.0.0.1",
|
|
80
|
+
port: 3005,
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Run:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
AUTHSEC_CLIENT_ID="YOUR_CLIENT_ID" \
|
|
88
|
+
AUTHSEC_AUTH_SERVICE_URL="https://dev.api.authsec.dev/sdkmgr/mcp-auth" \
|
|
89
|
+
AUTHSEC_SERVICES_URL="https://dev.api.authsec.dev/sdkmgr/services" \
|
|
90
|
+
node <your-compiled-server-entry>.js
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Wrapping an Existing MCP Server (Memory Example)
|
|
94
|
+
|
|
95
|
+
This repo includes a ready wrapper:
|
|
96
|
+
|
|
97
|
+
- `packages/typescript-sdk/examples/memory-authsec-wrapper.mjs`
|
|
98
|
+
|
|
99
|
+
It:
|
|
100
|
+
- Connects to upstream memory MCP server over stdio
|
|
101
|
+
- Reads upstream tool list
|
|
102
|
+
- Wraps each tool with `protectedByAuthSec(...)`
|
|
103
|
+
- Exposes a new AuthSec-protected MCP server on `HOST:PORT`
|
|
104
|
+
|
|
105
|
+
### Run locally
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
cd packages/typescript-sdk
|
|
109
|
+
npm install
|
|
110
|
+
npm run build
|
|
111
|
+
|
|
112
|
+
AUTHSEC_CLIENT_ID="YOUR_CLIENT_ID" \
|
|
113
|
+
PORT=3005 \
|
|
114
|
+
HOST=127.0.0.1 \
|
|
115
|
+
node examples/memory-authsec-wrapper.mjs
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Optional wrapper env vars
|
|
119
|
+
|
|
120
|
+
- `AUTHSEC_APP_NAME` (default: autogenerated)
|
|
121
|
+
- `MEMORY_SERVER_COMMAND` (default: `npx`)
|
|
122
|
+
- `MEMORY_SERVER_ARGS_JSON` (default: `["-y","@modelcontextprotocol/server-memory"]`)
|
|
123
|
+
- `AUTHSEC_TOOL_ROLES_JSON` (per-tool RBAC map)
|
|
124
|
+
- `MEMORY_FILE_PATH` (memory server persistence path)
|
|
125
|
+
|
|
126
|
+
Example RBAC map:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
AUTHSEC_TOOL_ROLES_JSON='{"create_entities":["admin"],"delete_entities":["admin"]}'
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## How Protection Works
|
|
133
|
+
|
|
134
|
+
1. `tools/list` asks SDK Manager for OAuth + protected tool visibility.
|
|
135
|
+
2. `oauth_*` tools are delegated upstream to SDK Manager.
|
|
136
|
+
3. Protected tool call triggers upstream `protect-tool` check.
|
|
137
|
+
4. On success, handler receives:
|
|
138
|
+
- `args.session_id` (resolved session)
|
|
139
|
+
- `args._user_info` (claims)
|
|
140
|
+
|
|
141
|
+
Auth behavior note:
|
|
142
|
+
- OAuth/auth decisions are delegated upstream to SDK Manager.
|
|
143
|
+
- Keep local wrappers as thin transport/proxy layers; do not add local auth bypass logic in production.
|
|
144
|
+
|
|
145
|
+
## Environment Variables
|
|
146
|
+
|
|
147
|
+
SDK runtime:
|
|
148
|
+
- `AUTHSEC_AUTH_SERVICE_URL` (default dev URL)
|
|
149
|
+
- `AUTHSEC_SERVICES_URL` (default dev URL)
|
|
150
|
+
- `AUTHSEC_TIMEOUT_SECONDS` (default `15`)
|
|
151
|
+
- `AUTHSEC_RETRIES` (default `2`)
|
|
152
|
+
- `AUTHSEC_TOOLS_LIST_TIMEOUT_SECONDS` (default `8`)
|
|
153
|
+
|
|
154
|
+
Server runtime:
|
|
155
|
+
- `AUTHSEC_CLIENT_ID` (required by your app wrapper)
|
|
156
|
+
- `AUTHSEC_APP_NAME` (optional app name)
|
|
157
|
+
- `HOST` / `PORT`
|
|
158
|
+
|
|
159
|
+
Note:
|
|
160
|
+
- Tool filtering policy for hidden/visible protected tools is controlled in SDK Manager service configuration.
|
|
161
|
+
|
|
162
|
+
## Troubleshooting
|
|
163
|
+
|
|
164
|
+
- `MODULE_NOT_FOUND` when running example path
|
|
165
|
+
- Check exact file path and avoid trailing spaces in command.
|
|
166
|
+
- `OAuth tool failed: ... released back to the pool`
|
|
167
|
+
- SDK Manager backend deployment issue, not wrapper syntax.
|
|
168
|
+
- `verifyToken failed: 404`
|
|
169
|
+
- SDK Manager `AUTH_MANAGER_URL` is likely wrong for environment; ensure dev/prod endpoint is correct.
|
|
170
|
+
- Tools visible but calls denied
|
|
171
|
+
- Expected when server is configured to expose all tools and enforce RBAC at call-time.
|
|
172
|
+
|
|
173
|
+
## Prompt Template (Copy/Paste)
|
|
174
|
+
|
|
175
|
+
Use this prompt with any coding LLM to secure an MCP server with `@authsec/sdk`:
|
|
176
|
+
|
|
177
|
+
```text
|
|
178
|
+
You are editing a TypeScript MCP server codebase.
|
|
179
|
+
|
|
180
|
+
Goal:
|
|
181
|
+
1) Add @authsec/sdk to protect sensitive tools with OAuth + RBAC.
|
|
182
|
+
2) Keep selected tools unprotected.
|
|
183
|
+
3) Ensure all auth checks are delegated upstream to SDK Manager (no local auth bypasses).
|
|
184
|
+
|
|
185
|
+
Requirements:
|
|
186
|
+
- Use protectedByAuthSec(...) for sensitive tools.
|
|
187
|
+
- Use mcpTool(...) for public tools.
|
|
188
|
+
- Provide strict inputSchema for every tool.
|
|
189
|
+
- Run server via runMcpServerWithOAuth({ tools, clientId, appName, host, port }).
|
|
190
|
+
- Add startup instructions with AUTHSEC_CLIENT_ID, AUTHSEC_AUTH_SERVICE_URL, AUTHSEC_SERVICES_URL.
|
|
191
|
+
- If wrapping an upstream MCP server, preserve upstream tool names and normalize returned content.
|
|
192
|
+
|
|
193
|
+
Inputs:
|
|
194
|
+
- clientId: <YOUR_CLIENT_ID>
|
|
195
|
+
- appName: <YOUR_APP_NAME>
|
|
196
|
+
- protected tools + RBAC:
|
|
197
|
+
- <tool_1>: roles=[...], scopes=[...], requireAll=<true/false>
|
|
198
|
+
- <tool_2>: ...
|
|
199
|
+
- unprotected tools:
|
|
200
|
+
- <tool_3>
|
|
201
|
+
|
|
202
|
+
Deliverables:
|
|
203
|
+
- Updated TS source files.
|
|
204
|
+
- Run commands.
|
|
205
|
+
- MCP Inspector verification checklist.
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Publishing (npm)
|
|
209
|
+
|
|
210
|
+
### 1) Bump version
|
|
211
|
+
|
|
212
|
+
Update version consistently:
|
|
213
|
+
- `packages/typescript-sdk/package.json` -> `version`
|
|
214
|
+
- `packages/typescript-sdk/src/index.ts` -> `VERSION`
|
|
215
|
+
|
|
216
|
+
### 2) Build and pack
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
cd packages/typescript-sdk
|
|
220
|
+
npm ci
|
|
221
|
+
npm run clean
|
|
222
|
+
npm run build
|
|
223
|
+
npm pack
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### 3) Smoke test tarball (recommended)
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
mkdir -p /tmp/authsec-sdk-smoke && cd /tmp/authsec-sdk-smoke
|
|
230
|
+
npm init -y
|
|
231
|
+
npm install /absolute/path/to/packages/typescript-sdk/authsec-sdk-<version>.tgz
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### 4) Publish
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
cd /absolute/path/to/packages/typescript-sdk
|
|
238
|
+
npm login
|
|
239
|
+
npm publish --access public
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
If using private registry, set it before publish:
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
npm config set registry <your-registry-url>
|
|
246
|
+
npm publish
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### 5) Post-publish check
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
npm view @authsec/sdk version
|
|
253
|
+
```
|
package/dist/ciba.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CIBA SDK - Passwordless Authentication for Voice Clients
|
|
3
|
+
* Mirrors Python CIBAClient class
|
|
4
|
+
*
|
|
5
|
+
* Supports both Admin and End-User (tenant) authentication flows:
|
|
6
|
+
* - Admin flow: email only (original flow)
|
|
7
|
+
* - Tenant flow: email + client_id (multi-client architecture)
|
|
8
|
+
*/
|
|
9
|
+
export declare class CIBAClient {
|
|
10
|
+
private baseUrl;
|
|
11
|
+
private clientId;
|
|
12
|
+
private activePolls;
|
|
13
|
+
private retryCounts;
|
|
14
|
+
constructor(options?: {
|
|
15
|
+
clientId?: string;
|
|
16
|
+
baseUrl?: string;
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* Triggers a CIBA push notification and cancels any existing poll for this user.
|
|
20
|
+
*
|
|
21
|
+
* - If clientId is set: uses tenant endpoint (/tenant/ciba/initiate)
|
|
22
|
+
* - If clientId is null: uses admin endpoint (/ciba/initiate)
|
|
23
|
+
*/
|
|
24
|
+
initiateAppApproval(email: string): Promise<Record<string, any>>;
|
|
25
|
+
/**
|
|
26
|
+
* Verifies a TOTP code for authentication.
|
|
27
|
+
*
|
|
28
|
+
* - If clientId is set: uses tenant endpoint (/tenant/totp/login)
|
|
29
|
+
* - If clientId is null: uses admin endpoint (/totp/login)
|
|
30
|
+
*/
|
|
31
|
+
verifyTotp(email: string, code: string): Promise<Record<string, any>>;
|
|
32
|
+
/**
|
|
33
|
+
* Polls for CIBA approval status.
|
|
34
|
+
*
|
|
35
|
+
* - If clientId is set: uses tenant endpoint (/tenant/ciba/token)
|
|
36
|
+
* - If clientId is null: uses admin endpoint (/ciba/token)
|
|
37
|
+
*/
|
|
38
|
+
pollForApproval(email: string, authReqId: string, options?: {
|
|
39
|
+
interval?: number;
|
|
40
|
+
timeout?: number;
|
|
41
|
+
}): Promise<Record<string, any>>;
|
|
42
|
+
/**
|
|
43
|
+
* Cancels any ongoing poll and resets retry logic for the user.
|
|
44
|
+
*/
|
|
45
|
+
cancelApproval(email: string): Record<string, any>;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=ciba.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ciba.d.ts","sourceRoot":"","sources":["../src/ciba.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,WAAW,CAAsB;gBAE7B,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;IAO7D;;;;;OAKG;IACG,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAiCtE;;;;;OAKG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAuD3E;;;;;OAKG;IACG,eAAe,CACnB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAChD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAkD/B;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;CAKnD"}
|
package/dist/ciba.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CIBA SDK - Passwordless Authentication for Voice Clients
|
|
4
|
+
* Mirrors Python CIBAClient class
|
|
5
|
+
*
|
|
6
|
+
* Supports both Admin and End-User (tenant) authentication flows:
|
|
7
|
+
* - Admin flow: email only (original flow)
|
|
8
|
+
* - Tenant flow: email + client_id (multi-client architecture)
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.CIBAClient = void 0;
|
|
12
|
+
class CIBAClient {
|
|
13
|
+
baseUrl;
|
|
14
|
+
clientId;
|
|
15
|
+
activePolls;
|
|
16
|
+
retryCounts;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.baseUrl = options?.baseUrl ?? 'https://dev.api.authsec.dev';
|
|
19
|
+
this.clientId = options?.clientId ?? null;
|
|
20
|
+
this.activePolls = new Map();
|
|
21
|
+
this.retryCounts = new Map();
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Triggers a CIBA push notification and cancels any existing poll for this user.
|
|
25
|
+
*
|
|
26
|
+
* - If clientId is set: uses tenant endpoint (/tenant/ciba/initiate)
|
|
27
|
+
* - If clientId is null: uses admin endpoint (/ciba/initiate)
|
|
28
|
+
*/
|
|
29
|
+
async initiateAppApproval(email) {
|
|
30
|
+
this.retryCounts.set(email, 0);
|
|
31
|
+
if (this.activePolls.has(email)) {
|
|
32
|
+
this.activePolls.set(email, true);
|
|
33
|
+
}
|
|
34
|
+
let endpoint;
|
|
35
|
+
let payload;
|
|
36
|
+
if (this.clientId) {
|
|
37
|
+
endpoint = `${this.baseUrl}/uflow/auth/tenant/ciba/initiate`;
|
|
38
|
+
payload = {
|
|
39
|
+
client_id: this.clientId,
|
|
40
|
+
email,
|
|
41
|
+
binding_message: 'Authentication requested via Voice SDK',
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
endpoint = `${this.baseUrl}/uflow/auth/ciba/initiate`;
|
|
46
|
+
payload = {
|
|
47
|
+
login_hint: email,
|
|
48
|
+
binding_message: 'Authentication requested via Voice SDK',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const response = await fetch(endpoint, {
|
|
52
|
+
method: 'POST',
|
|
53
|
+
headers: { 'Content-Type': 'application/json' },
|
|
54
|
+
body: JSON.stringify(payload),
|
|
55
|
+
});
|
|
56
|
+
return (await response.json());
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Verifies a TOTP code for authentication.
|
|
60
|
+
*
|
|
61
|
+
* - If clientId is set: uses tenant endpoint (/tenant/totp/login)
|
|
62
|
+
* - If clientId is null: uses admin endpoint (/totp/login)
|
|
63
|
+
*/
|
|
64
|
+
async verifyTotp(email, code) {
|
|
65
|
+
if (!this.retryCounts.has(email)) {
|
|
66
|
+
this.retryCounts.set(email, 0);
|
|
67
|
+
}
|
|
68
|
+
if (this.retryCounts.get(email) >= 3) {
|
|
69
|
+
return { success: false, error: 'too_many_retries', remaining: 0 };
|
|
70
|
+
}
|
|
71
|
+
let endpoint;
|
|
72
|
+
let payload;
|
|
73
|
+
if (this.clientId) {
|
|
74
|
+
endpoint = `${this.baseUrl}/uflow/auth/tenant/totp/login`;
|
|
75
|
+
payload = { client_id: this.clientId, email, totp_code: code };
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// Admin flow (fallback to dev.api if base_url is localhost for compatibility)
|
|
79
|
+
if (this.baseUrl.includes('localhost') || this.baseUrl.includes('127.0.0.1')) {
|
|
80
|
+
endpoint = 'https://dev.api.authsec.dev/uflow/auth/totp/login';
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
endpoint = `${this.baseUrl}/uflow/auth/totp/login`;
|
|
84
|
+
}
|
|
85
|
+
payload = { email, totp_code: code };
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const response = await fetch(endpoint, {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
headers: { 'Content-Type': 'application/json' },
|
|
91
|
+
body: JSON.stringify(payload),
|
|
92
|
+
signal: AbortSignal.timeout(10000),
|
|
93
|
+
});
|
|
94
|
+
const resData = (await response.json());
|
|
95
|
+
const token = resData.token ?? resData.access_token;
|
|
96
|
+
if (token || resData.success === true) {
|
|
97
|
+
this.retryCounts.set(email, 0);
|
|
98
|
+
return { ...resData, success: true, token, remaining: 3 };
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
this.retryCounts.set(email, this.retryCounts.get(email) + 1);
|
|
102
|
+
return {
|
|
103
|
+
success: false,
|
|
104
|
+
error: 'invalid_code',
|
|
105
|
+
remaining: 3 - this.retryCounts.get(email),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
return {
|
|
111
|
+
success: false,
|
|
112
|
+
error: e.message ?? String(e),
|
|
113
|
+
remaining: 3 - (this.retryCounts.get(email) ?? 0),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Polls for CIBA approval status.
|
|
119
|
+
*
|
|
120
|
+
* - If clientId is set: uses tenant endpoint (/tenant/ciba/token)
|
|
121
|
+
* - If clientId is null: uses admin endpoint (/ciba/token)
|
|
122
|
+
*/
|
|
123
|
+
async pollForApproval(email, authReqId, options) {
|
|
124
|
+
const interval = (options?.interval ?? 5) * 1000;
|
|
125
|
+
const timeout = (options?.timeout ?? 300) * 1000;
|
|
126
|
+
this.activePolls.set(email, false);
|
|
127
|
+
let endpoint;
|
|
128
|
+
let payload;
|
|
129
|
+
if (this.clientId) {
|
|
130
|
+
endpoint = `${this.baseUrl}/uflow/auth/tenant/ciba/token`;
|
|
131
|
+
payload = { client_id: this.clientId, auth_req_id: authReqId };
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
endpoint = `${this.baseUrl}/uflow/auth/ciba/token`;
|
|
135
|
+
payload = { auth_req_id: authReqId };
|
|
136
|
+
}
|
|
137
|
+
const startTime = Date.now();
|
|
138
|
+
while (Date.now() - startTime < timeout) {
|
|
139
|
+
if (this.activePolls.get(email) === true) {
|
|
140
|
+
return { status: 'cancelled' };
|
|
141
|
+
}
|
|
142
|
+
const response = await fetch(endpoint, {
|
|
143
|
+
method: 'POST',
|
|
144
|
+
headers: { 'Content-Type': 'application/json' },
|
|
145
|
+
body: JSON.stringify(payload),
|
|
146
|
+
});
|
|
147
|
+
const data = (await response.json());
|
|
148
|
+
const token = data.access_token ?? data.token;
|
|
149
|
+
if (token) {
|
|
150
|
+
return { status: 'approved', token };
|
|
151
|
+
}
|
|
152
|
+
if (data.error === 'access_denied' || data.error === 'expired_token') {
|
|
153
|
+
return { status: data.error };
|
|
154
|
+
}
|
|
155
|
+
await new Promise((resolve) => setTimeout(resolve, interval));
|
|
156
|
+
if (timeout <= 2000) {
|
|
157
|
+
break; // Short check for manual check
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return { status: 'timeout' };
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Cancels any ongoing poll and resets retry logic for the user.
|
|
164
|
+
*/
|
|
165
|
+
cancelApproval(email) {
|
|
166
|
+
this.activePolls.set(email, true);
|
|
167
|
+
this.retryCounts.set(email, 0);
|
|
168
|
+
return { status: 'cancelled' };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
exports.CIBAClient = CIBAClient;
|
|
172
|
+
//# sourceMappingURL=ciba.js.map
|
package/dist/ciba.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ciba.js","sourceRoot":"","sources":["../src/ciba.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global configuration store for AuthSec SDK
|
|
3
|
+
* Mirrors Python authsec_sdk config
|
|
4
|
+
*/
|
|
5
|
+
import type { AuthSecConfig } from './types.js';
|
|
6
|
+
/** In-memory session cache for user info (best-effort, used for oauth_user_info) */
|
|
7
|
+
export declare const sessionUserInfo: Record<string, any>;
|
|
8
|
+
/**
|
|
9
|
+
* Normalize caller-provided clientId to the runtime form expected by SDK Manager.
|
|
10
|
+
*
|
|
11
|
+
* Accepts:
|
|
12
|
+
* - base UUID (`xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`)
|
|
13
|
+
* - base UUID with underscores
|
|
14
|
+
* - already-suffixed IDs (`...-main-client` or `..._main-client`)
|
|
15
|
+
*/
|
|
16
|
+
export declare function normalizeRuntimeClientId(clientId: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Configure authentication settings for tool protection.
|
|
19
|
+
*/
|
|
20
|
+
export declare function configureAuth(clientId: string, appName: string, options?: {
|
|
21
|
+
authServiceUrl?: string;
|
|
22
|
+
servicesBaseUrl?: string;
|
|
23
|
+
timeout?: number;
|
|
24
|
+
retries?: number;
|
|
25
|
+
}): void;
|
|
26
|
+
/** Get current configuration (for debugging). */
|
|
27
|
+
export declare function getConfig(): Record<string, any>;
|
|
28
|
+
/** Check if authentication is properly configured. */
|
|
29
|
+
export declare function isConfigured(): boolean;
|
|
30
|
+
/** Internal: get mutable config reference */
|
|
31
|
+
export declare function getInternalConfig(): AuthSecConfig;
|
|
32
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAahD,oFAAoF;AACpF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,CAAC;AAEvD;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAqBjE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IACR,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACA,IAAI,CAuBN;AAED,iDAAiD;AACjD,wBAAgB,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAM/C;AAED,sDAAsD;AACtD,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED,6CAA6C;AAC7C,wBAAgB,iBAAiB,IAAI,aAAa,CAEjD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Global configuration store for AuthSec SDK
|
|
4
|
+
* Mirrors Python authsec_sdk config
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.sessionUserInfo = void 0;
|
|
8
|
+
exports.normalizeRuntimeClientId = normalizeRuntimeClientId;
|
|
9
|
+
exports.configureAuth = configureAuth;
|
|
10
|
+
exports.getConfig = getConfig;
|
|
11
|
+
exports.isConfigured = isConfigured;
|
|
12
|
+
exports.getInternalConfig = getInternalConfig;
|
|
13
|
+
const _config = {
|
|
14
|
+
clientId: null,
|
|
15
|
+
appName: null,
|
|
16
|
+
authServiceUrl: 'https://dev.api.authsec.dev/sdkmgr/mcp-auth',
|
|
17
|
+
servicesBaseUrl: 'https://dev.api.authsec.dev/sdkmgr/services',
|
|
18
|
+
timeout: 10,
|
|
19
|
+
retries: 3,
|
|
20
|
+
spireSocketPath: null,
|
|
21
|
+
spireEnabled: false,
|
|
22
|
+
};
|
|
23
|
+
/** In-memory session cache for user info (best-effort, used for oauth_user_info) */
|
|
24
|
+
exports.sessionUserInfo = {};
|
|
25
|
+
/**
|
|
26
|
+
* Normalize caller-provided clientId to the runtime form expected by SDK Manager.
|
|
27
|
+
*
|
|
28
|
+
* Accepts:
|
|
29
|
+
* - base UUID (`xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`)
|
|
30
|
+
* - base UUID with underscores
|
|
31
|
+
* - already-suffixed IDs (`...-main-client` or `..._main-client`)
|
|
32
|
+
*/
|
|
33
|
+
function normalizeRuntimeClientId(clientId) {
|
|
34
|
+
let raw = (clientId ?? '').trim().replace(/^["']|["']$/g, '');
|
|
35
|
+
if (!raw) {
|
|
36
|
+
throw new Error('client_id must be a non-empty string');
|
|
37
|
+
}
|
|
38
|
+
raw = raw.replace('_main-client', '-main-client');
|
|
39
|
+
let base;
|
|
40
|
+
if (raw.endsWith('-main-client')) {
|
|
41
|
+
base = raw.slice(0, -'-main-client'.length);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
base = raw;
|
|
45
|
+
}
|
|
46
|
+
// Normalize UUID-like underscore format to hyphen format
|
|
47
|
+
if (base.includes('_') && (base.match(/_/g) || []).length === 4) {
|
|
48
|
+
base = base.replace(/_/g, '-');
|
|
49
|
+
}
|
|
50
|
+
return `${base}-main-client`;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Configure authentication settings for tool protection.
|
|
54
|
+
*/
|
|
55
|
+
function configureAuth(clientId, appName, options) {
|
|
56
|
+
if (!clientId || typeof clientId !== 'string') {
|
|
57
|
+
throw new Error('clientId must be a non-empty string');
|
|
58
|
+
}
|
|
59
|
+
if (!appName || typeof appName !== 'string') {
|
|
60
|
+
throw new Error('appName must be a non-empty string');
|
|
61
|
+
}
|
|
62
|
+
_config.clientId = clientId;
|
|
63
|
+
_config.appName = appName;
|
|
64
|
+
_config.timeout = options?.timeout ?? 10;
|
|
65
|
+
_config.retries = options?.retries ?? 3;
|
|
66
|
+
if (options?.authServiceUrl) {
|
|
67
|
+
_config.authServiceUrl = options.authServiceUrl.replace(/\/+$/, '');
|
|
68
|
+
}
|
|
69
|
+
if (options?.servicesBaseUrl) {
|
|
70
|
+
_config.servicesBaseUrl = options.servicesBaseUrl.replace(/\/+$/, '');
|
|
71
|
+
}
|
|
72
|
+
console.log(`Auth configured: ${appName} with client_id: ${clientId.slice(0, 8)}...`);
|
|
73
|
+
console.log(`Auth service URL: ${_config.authServiceUrl}`);
|
|
74
|
+
console.log(`Services URL: ${_config.servicesBaseUrl}`);
|
|
75
|
+
}
|
|
76
|
+
/** Get current configuration (for debugging). */
|
|
77
|
+
function getConfig() {
|
|
78
|
+
const copy = { ..._config };
|
|
79
|
+
if (copy.clientId) {
|
|
80
|
+
copy.clientId = copy.clientId.slice(0, 8) + '...' + copy.clientId.slice(-4);
|
|
81
|
+
}
|
|
82
|
+
return copy;
|
|
83
|
+
}
|
|
84
|
+
/** Check if authentication is properly configured. */
|
|
85
|
+
function isConfigured() {
|
|
86
|
+
return !!(getInternalConfig().clientId && getInternalConfig().appName);
|
|
87
|
+
}
|
|
88
|
+
/** Internal: get mutable config reference */
|
|
89
|
+
function getInternalConfig() {
|
|
90
|
+
return _config;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool decorator functions (higher-order functions)
|
|
3
|
+
* Mirrors Python @protected_by_AuthSec and @mcp_tool decorators
|
|
4
|
+
*/
|
|
5
|
+
import type { ToolDefinition, ToolHandler, ToolHandlerWithSession } from './types.js';
|
|
6
|
+
interface ProtectedToolOptions {
|
|
7
|
+
toolName: string;
|
|
8
|
+
roles?: string[];
|
|
9
|
+
groups?: string[];
|
|
10
|
+
resources?: string[];
|
|
11
|
+
scopes?: string[];
|
|
12
|
+
permissions?: string[];
|
|
13
|
+
requireAll?: boolean;
|
|
14
|
+
description?: string;
|
|
15
|
+
inputSchema?: Record<string, any>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Protect a tool via SDK Manager auth service API with optional RBAC.
|
|
19
|
+
*
|
|
20
|
+
* The handler receives (arguments, session) where session contains user context.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const adminTool = protectedByAuthSec({
|
|
25
|
+
* toolName: 'admin_dashboard',
|
|
26
|
+
* roles: ['admin'],
|
|
27
|
+
* description: 'Access admin dashboard',
|
|
28
|
+
* }, async (args, session) => {
|
|
29
|
+
* return [{ type: 'text', text: `Hello ${session.userId}` }];
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function protectedByAuthSec(options: ProtectedToolOptions, handler: ToolHandler | ToolHandlerWithSession): ToolDefinition;
|
|
34
|
+
interface McpToolOptions {
|
|
35
|
+
name?: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
inputSchema?: Record<string, any>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Define a standard MCP tool (no authentication required).
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const echoTool = mcpTool({
|
|
45
|
+
* name: 'echo',
|
|
46
|
+
* description: 'Echo a message',
|
|
47
|
+
* inputSchema: {
|
|
48
|
+
* type: 'object',
|
|
49
|
+
* properties: { message: { type: 'string' } },
|
|
50
|
+
* required: ['message'],
|
|
51
|
+
* },
|
|
52
|
+
* }, async (args) => {
|
|
53
|
+
* return [{ type: 'text', text: args.message }];
|
|
54
|
+
* });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function mcpTool(options: McpToolOptions, handler: ToolHandler): ToolDefinition;
|
|
58
|
+
export {};
|
|
59
|
+
//# sourceMappingURL=decorators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,sBAAsB,EAIvB,MAAM,YAAY,CAAC;AAGpB,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,WAAW,GAAG,sBAAsB,GAC5C,cAAc,CAgGhB;AAED,UAAU,cAAc;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,OAAO,CACrB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,WAAW,GACnB,cAAc,CAchB"}
|