• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

cofacts / rumors-api / 25995093023

17 May 2026 03:34PM UTC coverage: 78.958% (-3.3%) from 82.22%
25995093023

Pull #389

github

web-flow
Merge e212c2341 into 59e4e0b39
Pull Request #389: feat(mcp): add remote MCP server with OAuth 2.1 + PKCE

893 of 1209 branches covered (73.86%)

Branch coverage included in aggregate %.

20 of 110 new or added lines in 5 files covered. (18.18%)

8 existing lines in 1 file now uncovered.

1745 of 2132 relevant lines covered (81.85%)

16.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

56.25
/src/tokenRoute.js
1
import { createHash } from 'crypto';
2
import {
3
  verifyJWT,
4
  signLongLivedJWT,
5
  TOKEN_USE_AUTH_CODE,
6
  getCookieMaxAgeSec,
7
} from './lib/jwt';
8

9
export default async function tokenRoute(ctx) {
10
  const { code, code_verifier } = ctx.request.body;
8✔
11

12
  if (!code) {
8✔
13
    ctx.status = 400;
1✔
14
    ctx.body = { error: 'code is required' };
1✔
15
    return;
1✔
16
  }
17

18
  let payload;
19
  try {
7✔
20
    payload = await verifyJWT(code, { expectedUse: TOKEN_USE_AUTH_CODE });
7✔
21
  } catch (err) {
22
    ctx.status = 401;
4✔
23
    ctx.body = { error: 'Invalid or expired code' };
4✔
24
    return;
4✔
25
  }
26

27
  // PKCE flow: auth code carries code_challenge, so the caller must prove they
28
  // hold the original code_verifier (SHA256(verifier) == code_challenge).
29
  if (payload.code_challenge) {
3!
NEW
30
    if (!code_verifier) {
×
NEW
31
      ctx.status = 400;
×
NEW
32
      ctx.body = { error: 'code_verifier required' };
×
NEW
33
      return;
×
34
    }
NEW
35
    const computed = createHash('sha256')
×
36
      .update(code_verifier)
37
      .digest('base64url');
NEW
38
    if (computed !== payload.code_challenge) {
×
NEW
39
      ctx.status = 401;
×
NEW
40
      ctx.body = { error: 'invalid_code_verifier' };
×
NEW
41
      return;
×
42
    }
43
  }
44

45
  const userId = payload.sub;
3✔
46
  const token = await signLongLivedJWT(userId);
3✔
47
  const maxAgeSec = getCookieMaxAgeSec();
2✔
48
  ctx.body = {
2✔
49
    // 1st-party flow (cofacts.ai)
50
    token,
51

52
    // OAuth2 compatible (PKCE flow)
53
    access_token: token,
54
    token_type: 'Bearer',
55
    expires_in: maxAgeSec,
56
  };
57
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc