121 lines
2.8 KiB
JavaScript
121 lines
2.8 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import {
|
|
mintMindSpaceMcpScopedToken,
|
|
verifyMindSpaceMcpScopedToken,
|
|
} from './mindspace-mcp-scoped-token.mjs';
|
|
|
|
const secret = 'mindspace-test-secret-1234';
|
|
|
|
test('MindSpace MCP token binds user, session, package, workspace, and tools', () => {
|
|
const token = mintMindSpaceMcpScopedToken({
|
|
secret,
|
|
userId: 'user-1',
|
|
sessionId: 'session-1',
|
|
packageId: 'cp_session-1',
|
|
workspaceRef:
|
|
'mindspace://users/user-1/workspace',
|
|
tools: ['write_file', 'read_file'],
|
|
now: 1_000_000,
|
|
tokenId: 'token-1',
|
|
});
|
|
|
|
const claims = verifyMindSpaceMcpScopedToken({
|
|
token,
|
|
secret,
|
|
tool: 'write_file',
|
|
now: 1_001_000,
|
|
});
|
|
|
|
assert.deepEqual(claims, {
|
|
userId: 'user-1',
|
|
sessionId: 'session-1',
|
|
packageId: 'cp_session-1',
|
|
workspaceRef:
|
|
'mindspace://users/user-1/workspace',
|
|
tools: ['read_file', 'write_file'],
|
|
issuedAt: 1_000_000,
|
|
expiresAt: 1_900_000,
|
|
tokenId: 'token-1',
|
|
});
|
|
});
|
|
|
|
test('MindSpace MCP token rejects tampering, expiry, and tools outside the allowlist', () => {
|
|
const token = mintMindSpaceMcpScopedToken({
|
|
secret,
|
|
userId: 'user-1',
|
|
sessionId: 'session-1',
|
|
packageId: 'cp_session-1',
|
|
workspaceRef:
|
|
'mindspace://users/user-1/workspace',
|
|
tools: ['read_file'],
|
|
ttlSeconds: 60,
|
|
now: 1_000_000,
|
|
tokenId: 'token-1',
|
|
});
|
|
|
|
assert.throws(
|
|
() =>
|
|
verifyMindSpaceMcpScopedToken({
|
|
token: `${token}x`,
|
|
secret,
|
|
now: 1_001_000,
|
|
}),
|
|
/signature/,
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
verifyMindSpaceMcpScopedToken({
|
|
token,
|
|
secret,
|
|
tool: 'write_file',
|
|
now: 1_001_000,
|
|
}),
|
|
(error) =>
|
|
error?.code === 'mcp_tool_forbidden',
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
verifyMindSpaceMcpScopedToken({
|
|
token,
|
|
secret,
|
|
now: 2_000_000,
|
|
clockSkewSeconds: 0,
|
|
}),
|
|
(error) =>
|
|
error?.code === 'expired_mcp_token',
|
|
);
|
|
});
|
|
|
|
test('MindSpace MCP token refuses incomplete scopes and weak secrets', () => {
|
|
assert.throws(
|
|
() =>
|
|
mintMindSpaceMcpScopedToken({
|
|
secret: 'short',
|
|
userId: 'user-1',
|
|
sessionId: 'session-1',
|
|
packageId: 'cp_session-1',
|
|
workspaceRef:
|
|
'mindspace://users/user-1/workspace',
|
|
tools: ['read_file'],
|
|
}),
|
|
(error) =>
|
|
error?.code ===
|
|
'invalid_mcp_token_secret',
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
mintMindSpaceMcpScopedToken({
|
|
secret,
|
|
userId: 'user-1',
|
|
sessionId: 'session-1',
|
|
packageId: 'cp_session-1',
|
|
workspaceRef:
|
|
'mindspace://users/user-1/workspace',
|
|
tools: [],
|
|
}),
|
|
(error) =>
|
|
error?.code === 'invalid_mcp_scope',
|
|
);
|
|
});
|