brightspace-mcp-server 1.6.2 → 2.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.
Files changed (92) hide show
  1. package/README.md +34 -7
  2. package/build/api/client.d.ts +5 -3
  3. package/build/api/client.d.ts.map +1 -1
  4. package/build/api/client.js +71 -79
  5. package/build/api/client.js.map +1 -1
  6. package/build/api/errors.d.ts +4 -0
  7. package/build/api/errors.d.ts.map +1 -1
  8. package/build/api/errors.js +7 -0
  9. package/build/api/errors.js.map +1 -1
  10. package/build/auth/auth-cooldown.d.ts +16 -0
  11. package/build/auth/auth-cooldown.d.ts.map +1 -0
  12. package/build/auth/auth-cooldown.js +47 -0
  13. package/build/auth/auth-cooldown.js.map +1 -0
  14. package/build/auth/auth-lock.d.ts +7 -0
  15. package/build/auth/auth-lock.d.ts.map +1 -0
  16. package/build/auth/auth-lock.js +114 -0
  17. package/build/auth/auth-lock.js.map +1 -0
  18. package/build/auth/auth-runner.d.ts +17 -7
  19. package/build/auth/auth-runner.d.ts.map +1 -1
  20. package/build/auth/auth-runner.js +122 -26
  21. package/build/auth/auth-runner.js.map +1 -1
  22. package/build/auth/browser-auth.d.ts +19 -67
  23. package/build/auth/browser-auth.d.ts.map +1 -1
  24. package/build/auth/browser-auth.js +258 -574
  25. package/build/auth/browser-auth.js.map +1 -1
  26. package/build/auth/browser-state-store.d.ts +19 -0
  27. package/build/auth/browser-state-store.d.ts.map +1 -0
  28. package/build/auth/browser-state-store.js +101 -0
  29. package/build/auth/browser-state-store.js.map +1 -0
  30. package/build/auth/credential-store.d.ts +29 -0
  31. package/build/auth/credential-store.d.ts.map +1 -0
  32. package/build/auth/credential-store.js +233 -0
  33. package/build/auth/credential-store.js.map +1 -0
  34. package/build/auth/encrypted-store.d.ts +25 -0
  35. package/build/auth/encrypted-store.d.ts.map +1 -0
  36. package/build/auth/encrypted-store.js +61 -0
  37. package/build/auth/encrypted-store.js.map +1 -0
  38. package/build/auth/legacy-profile.d.ts +3 -0
  39. package/build/auth/legacy-profile.d.ts.map +1 -0
  40. package/build/auth/legacy-profile.js +41 -0
  41. package/build/auth/legacy-profile.js.map +1 -0
  42. package/build/auth/legacy-state.d.ts +14 -0
  43. package/build/auth/legacy-state.d.ts.map +1 -0
  44. package/build/auth/legacy-state.js +107 -0
  45. package/build/auth/legacy-state.js.map +1 -0
  46. package/build/auth/purdue-sso.d.ts +18 -36
  47. package/build/auth/purdue-sso.d.ts.map +1 -1
  48. package/build/auth/purdue-sso.js +165 -192
  49. package/build/auth/purdue-sso.js.map +1 -1
  50. package/build/auth/session-store.d.ts +16 -38
  51. package/build/auth/session-store.d.ts.map +1 -1
  52. package/build/auth/session-store.js +157 -152
  53. package/build/auth/session-store.js.map +1 -1
  54. package/build/auth/sso-flow.d.ts +14 -3
  55. package/build/auth/sso-flow.d.ts.map +1 -1
  56. package/build/auth/sso-flow.js +16 -1
  57. package/build/auth/sso-flow.js.map +1 -1
  58. package/build/auth/suny-sso.d.ts +3 -2
  59. package/build/auth/suny-sso.d.ts.map +1 -1
  60. package/build/auth/suny-sso.js +15 -24
  61. package/build/auth/suny-sso.js.map +1 -1
  62. package/build/auth/token-manager.d.ts +10 -3
  63. package/build/auth/token-manager.d.ts.map +1 -1
  64. package/build/auth/token-manager.js +62 -26
  65. package/build/auth/token-manager.js.map +1 -1
  66. package/build/auth/token-mint.d.ts +2 -2
  67. package/build/auth/token-mint.d.ts.map +1 -1
  68. package/build/auth/token-mint.js +31 -9
  69. package/build/auth/token-mint.js.map +1 -1
  70. package/build/auth-cli.d.ts +1 -7
  71. package/build/auth-cli.d.ts.map +1 -1
  72. package/build/auth-cli.js +29 -73
  73. package/build/auth-cli.js.map +1 -1
  74. package/build/index.js +8 -4
  75. package/build/index.js.map +1 -1
  76. package/build/setup.js +14 -8
  77. package/build/setup.js.map +1 -1
  78. package/build/types/index.d.ts +6 -0
  79. package/build/types/index.d.ts.map +1 -1
  80. package/build/utils/config-store.d.ts +1 -0
  81. package/build/utils/config-store.d.ts.map +1 -1
  82. package/build/utils/config-store.js +3 -0
  83. package/build/utils/config-store.js.map +1 -1
  84. package/build/utils/config.d.ts +2 -1
  85. package/build/utils/config.d.ts.map +1 -1
  86. package/build/utils/config.js +30 -10
  87. package/build/utils/config.js.map +1 -1
  88. package/build/utils/secure-config.d.ts +6 -0
  89. package/build/utils/secure-config.d.ts.map +1 -0
  90. package/build/utils/secure-config.js +57 -0
  91. package/build/utils/secure-config.js.map +1 -0
  92. package/package.json +4 -2
@@ -4,6 +4,7 @@
4
4
  * Licensed under MIT — see LICENSE file for details.
5
5
  */
6
6
  import type { TokenData } from "../types/index.js";
7
+ import { SessionStore } from "./session-store.js";
7
8
  import { mintAccessToken } from "./token-mint.js";
8
9
  export interface TokenManagerOptions {
9
10
  sessionDir?: string;
@@ -13,6 +14,8 @@ export interface TokenManagerOptions {
13
14
  tokenTtl?: number;
14
15
  /** Injection seam for tests. */
15
16
  mint?: typeof mintAccessToken;
17
+ /** Persistence injection keeps unit tests independent of native credentials. */
18
+ sessionStore?: Pick<SessionStore, "load" | "save" | "clear" | "saveIfCurrent" | "clearIfCurrent">;
16
19
  }
17
20
  /**
18
21
  * TokenManager manages token lifecycle with in-memory caching and disk persistence.
@@ -26,6 +29,7 @@ export declare class TokenManager {
26
29
  private readonly mint;
27
30
  /** Single in-flight mint, so concurrent callers share one request. */
28
31
  private mintInFlight;
32
+ private rejectedAccessToken;
29
33
  constructor(sessionDir?: string);
30
34
  constructor(options: TokenManagerOptions);
31
35
  /**
@@ -33,10 +37,9 @@ export declare class TokenManager {
33
37
  * Checks memory cache first, then loads from disk if needed.
34
38
  * Returns null if token is expired or within refresh buffer.
35
39
  */
36
- getToken(): Promise<TokenData | null>;
40
+ getToken(rejectedAccessToken?: string): Promise<TokenData | null>;
37
41
  /**
38
- * First candidate that carries both the cookie header and the XSRF token,
39
- * or null when neither can be used to mint.
42
+ * Only use persisted session material, including updates from other processes.
40
43
  */
41
44
  private pickMintable;
42
45
  /**
@@ -53,6 +56,10 @@ export declare class TokenManager {
53
56
  * Clear the token from memory and disk.
54
57
  */
55
58
  clearToken(): Promise<void>;
59
+ private isUsable;
60
+ private matchesTenant;
61
+ private sameToken;
62
+ private afterConcurrentChange;
56
63
  /**
57
64
  * Check if a token is valid (not expired and outside refresh buffer).
58
65
  * A token is valid if it expires more than REFRESH_BUFFER_MS from now.
@@ -1 +1 @@
1
- {"version":3,"file":"token-manager.d.ts","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAYlD,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,IAAI,CAAC,EAAE,OAAO,eAAe,CAAC;CAC/B;AAED;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,WAAW,CAA0B;IAC7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;IAC9C,sEAAsE;IACtE,OAAO,CAAC,YAAY,CAA0C;gBAElD,UAAU,CAAC,EAAE,MAAM;gBACnB,OAAO,EAAE,mBAAmB;IAaxC;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IA2B3C;;;OAGG;IACH,OAAO,CAAC,YAAY;IAUpB;;;OAGG;YACW,eAAe;YAaf,OAAO;IAkCrB;;OAEG;IACG,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IAiBlC;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;CAIvC"}
1
+ {"version":3,"file":"token-manager.d.ts","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAalD,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,IAAI,CAAC,EAAE,OAAO,eAAe,CAAC;IAC9B,gFAAgF;IAChF,YAAY,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,eAAe,GAAG,gBAAgB,CAAC,CAAC;CACnG;AAED;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,WAAW,CAA0B;IAC7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAmD;IAChF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;IAC9C,sEAAsE;IACtE,OAAO,CAAC,YAAY,CAA0C;IAC9D,OAAO,CAAC,mBAAmB,CAAuB;gBAEtC,UAAU,CAAC,EAAE,MAAM;gBACnB,OAAO,EAAE,mBAAmB;IAaxC;;;;OAIG;IACG,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IA8BvE;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;;OAGG;YACW,eAAe;YAaf,OAAO;IAmDrB;;OAEG;IACG,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,SAAS;YAKH,qBAAqB;IAMnC;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IAiBlC;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;CAIvC"}
@@ -6,6 +6,7 @@
6
6
  import { SessionStore } from "./session-store.js";
7
7
  import { mintAccessToken } from "./token-mint.js";
8
8
  import { log } from "../utils/logger.js";
9
+ import { TokenRefreshError } from "../api/errors.js";
9
10
  /**
10
11
  * Token refresh buffer - tokens within this time of expiry are considered invalid.
11
12
  * This prevents using tokens that might expire during a request.
@@ -25,12 +26,13 @@ export class TokenManager {
25
26
  mint;
26
27
  /** Single in-flight mint, so concurrent callers share one request. */
27
28
  mintInFlight = null;
29
+ rejectedAccessToken = null;
28
30
  constructor(sessionDirOrOptions) {
29
31
  const options = typeof sessionDirOrOptions === "string" || sessionDirOrOptions === undefined
30
32
  ? { sessionDir: sessionDirOrOptions }
31
33
  : sessionDirOrOptions;
32
- this.sessionStore = new SessionStore(options.sessionDir);
33
- this.baseUrl = options.baseUrl;
34
+ this.sessionStore = options.sessionStore ?? new SessionStore(options.sessionDir);
35
+ this.baseUrl = options.baseUrl ? new URL(options.baseUrl).origin : undefined;
34
36
  this.tokenTtl = options.tokenTtl ?? DEFAULT_TOKEN_TTL_SECONDS;
35
37
  this.mint = options.mint ?? mintAccessToken;
36
38
  }
@@ -39,22 +41,26 @@ export class TokenManager {
39
41
  * Checks memory cache first, then loads from disk if needed.
40
42
  * Returns null if token is expired or within refresh buffer.
41
43
  */
42
- async getToken() {
44
+ async getToken(rejectedAccessToken) {
45
+ if (rejectedAccessToken)
46
+ this.rejectedAccessToken = rejectedAccessToken;
43
47
  // Check memory cache first
44
- if (this.cachedToken && this.isValid(this.cachedToken)) {
48
+ if (this.cachedToken && this.isUsable(this.cachedToken)) {
45
49
  log("DEBUG", "Returning cached token");
46
50
  return this.cachedToken;
47
51
  }
48
52
  // Try loading from disk
49
53
  const storedToken = await this.sessionStore.load();
50
- if (storedToken && this.isValid(storedToken)) {
54
+ if (storedToken && this.isUsable(storedToken)) {
51
55
  log("DEBUG", "Loaded valid token from session store");
52
56
  this.cachedToken = storedToken;
53
57
  return storedToken;
54
58
  }
55
59
  // The token is stale, but if it carried the session material we can trade
56
60
  // that for a fresh JWT over plain HTTP instead of relaunching the browser.
57
- const mintable = this.pickMintable(this.cachedToken, storedToken);
61
+ // Disk may have been refreshed by another MCP process. Never prefer stale
62
+ // cached cookies over the current persisted session.
63
+ const mintable = this.pickMintable(storedToken);
58
64
  if (mintable) {
59
65
  const minted = await this.mintFromSession(mintable);
60
66
  if (minted)
@@ -64,17 +70,10 @@ export class TokenManager {
64
70
  return null;
65
71
  }
66
72
  /**
67
- * First candidate that carries both the cookie header and the XSRF token,
68
- * or null when neither can be used to mint.
73
+ * Only use persisted session material, including updates from other processes.
69
74
  */
70
- pickMintable(...candidates) {
71
- if (!this.baseUrl)
72
- return null;
73
- for (const candidate of candidates) {
74
- if (candidate?.cookieHeader && candidate.csrfToken)
75
- return candidate;
76
- }
77
- return null;
75
+ pickMintable(candidate) {
76
+ return this.baseUrl && candidate && this.matchesTenant(candidate) && candidate.cookieHeader && candidate.csrfToken ? candidate : null;
78
77
  }
79
78
  /**
80
79
  * Mint a fresh token from the stale one's session material, collapsing
@@ -93,39 +92,60 @@ export class TokenManager {
93
92
  }
94
93
  async runMint(stale) {
95
94
  log("DEBUG", "Trying to mint an access token from the session cookie");
96
- const result = await this.mint({
97
- baseUrl: this.baseUrl,
98
- cookieHeader: stale.cookieHeader,
99
- csrfToken: stale.csrfToken,
100
- });
95
+ let result;
96
+ try {
97
+ result = await this.mint({
98
+ baseUrl: this.baseUrl,
99
+ cookieHeader: stale.cookieHeader,
100
+ csrfToken: stale.csrfToken,
101
+ });
102
+ }
103
+ catch (error) {
104
+ throw new TokenRefreshError("token service request failed", error instanceof Error ? error : undefined);
105
+ }
106
+ // The auth CLI or another MCP process can finish a login while HTTP minting
107
+ // is in flight. Its newer session wins over either result of this request.
108
+ const current = await this.sessionStore.load();
109
+ if (current && !this.sameToken(current, stale)) {
110
+ this.cachedToken = current;
111
+ if (this.isUsable(current))
112
+ return current;
113
+ throw new TokenRefreshError("saved authentication changed during refresh");
114
+ }
101
115
  if (result.ok) {
102
116
  const now = Date.now();
103
117
  const token = {
104
118
  accessToken: result.accessToken,
119
+ tenantOrigin: this.baseUrl,
105
120
  capturedAt: now,
106
121
  expiresAt: now + this.tokenTtl * 1000,
107
122
  source: "browser",
108
123
  cookieHeader: stale.cookieHeader,
109
124
  csrfToken: stale.csrfToken,
110
125
  };
111
- await this.setToken(token);
126
+ if (!await this.sessionStore.saveIfCurrent(token, stale))
127
+ return this.afterConcurrentChange();
128
+ this.cachedToken = token;
129
+ this.rejectedAccessToken = null;
112
130
  log("INFO", "Minted a fresh access token from the session cookie");
113
131
  return token;
114
132
  }
115
133
  if (result.reason === "sessionExpired") {
116
134
  log("INFO", "The session cookie has expired, a browser login is needed");
117
- await this.clearToken();
135
+ if (!await this.sessionStore.clearIfCurrent(stale))
136
+ return this.afterConcurrentChange();
137
+ this.cachedToken = null;
118
138
  return null;
119
139
  }
120
- log("WARN", `Could not mint an access token: ${result.detail ?? "transport failure"}`);
121
- return null;
140
+ throw new TokenRefreshError(result.detail ?? "unexpected token service response");
122
141
  }
123
142
  /**
124
143
  * Set a new token, caching in memory and persisting to disk.
125
144
  */
126
145
  async setToken(token) {
127
- this.cachedToken = token;
128
146
  await this.sessionStore.save(token);
147
+ this.cachedToken = token;
148
+ this.rejectedAccessToken = null;
129
149
  log("DEBUG", "Token cached and persisted");
130
150
  }
131
151
  /**
@@ -136,6 +156,22 @@ export class TokenManager {
136
156
  await this.sessionStore.clear();
137
157
  log("DEBUG", "Token cleared from memory and disk");
138
158
  }
159
+ isUsable(token) {
160
+ return this.matchesTenant(token) && token.accessToken !== this.rejectedAccessToken && this.isValid(token);
161
+ }
162
+ matchesTenant(token) {
163
+ return this.baseUrl === undefined || token.tenantOrigin === this.baseUrl;
164
+ }
165
+ sameToken(a, b) {
166
+ return a.accessToken === b.accessToken && a.capturedAt === b.capturedAt &&
167
+ a.cookieHeader === b.cookieHeader && a.csrfToken === b.csrfToken && a.tenantOrigin === b.tenantOrigin;
168
+ }
169
+ async afterConcurrentChange() {
170
+ this.cachedToken = await this.sessionStore.load();
171
+ if (this.cachedToken && this.isUsable(this.cachedToken))
172
+ return this.cachedToken;
173
+ throw new TokenRefreshError("saved authentication changed during refresh");
174
+ }
139
175
  /**
140
176
  * Check if a token is valid (not expired and outside refresh buffer).
141
177
  * A token is valid if it expires more than REFRESH_BUFFER_MS from now.
@@ -1 +1 @@
1
- {"version":3,"file":"token-manager.js","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"token-manager.js","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"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"}
@@ -25,8 +25,8 @@ export type MintResult = {
25
25
  * Exchange the D2L session cookies for a fresh Bearer token in one request.
26
26
  * This is the cheap alternative to relaunching Chromium when the JWT expires.
27
27
  *
28
- * Classification order matters: a network throw is transport, the expiry marker
29
- * wins over the status code, then a non-2xx status, then a missing access_token.
28
+ * Only a 401 or the known login redirect proves session expiry. Server errors,
29
+ * permission failures and unknown response formats remain temporary failures.
30
30
  */
31
31
  export declare function mintAccessToken({ baseUrl, cookieHeader, csrfToken, fetchImpl, timeoutMs, }: MintOptions): Promise<MintResult>;
32
32
  //# sourceMappingURL=token-mint.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"token-mint.d.ts","sourceRoot":"","sources":["../../src/auth/token-mint.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,GAAG,WAAW,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAQ3E;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,EACpC,OAAO,EACP,YAAY,EACZ,SAAS,EACT,SAAiB,EACjB,SAA8B,GAC/B,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA6CnC"}
1
+ {"version":3,"file":"token-mint.d.ts","sourceRoot":"","sources":["../../src/auth/token-mint.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,GAAG,WAAW,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAmB3E;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,EACpC,OAAO,EACP,YAAY,EACZ,SAAS,EACT,SAAiB,EACjB,SAA8B,GAC/B,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAyDnC"}
@@ -10,7 +10,7 @@ import { log } from "../utils/logger.js";
10
10
  * carrying a script that redirects to /d2l/login?sessionExpired=1. There is no
11
11
  * 401 on this path, so the marker, not the status, is the only honest signal.
12
12
  */
13
- const EXPIRED_MARKER = "sessionExpired=1";
13
+ const EXPIRED_MARKER = "/d2l/login?sessionExpired=1";
14
14
  /** Same identity the API client sends, see buildAuthHeaders in api/client.ts. */
15
15
  const USER_AGENT = "BrightspaceMCP/1.0 (Rohan Muppa; github.com/rohanmuppa/brightspace-mcp-server)";
16
16
  const DEFAULT_TIMEOUT_MS = 15000;
@@ -19,17 +19,30 @@ const transport = (detail) => ({
19
19
  reason: "transport",
20
20
  detail,
21
21
  });
22
+ function expiredRedirect(location, tokenUrl) {
23
+ if (!location)
24
+ return false;
25
+ try {
26
+ const target = new URL(location, tokenUrl);
27
+ return target.origin === new URL(tokenUrl).origin &&
28
+ target.pathname === "/d2l/login" && target.searchParams.get("sessionExpired") === "1";
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
22
34
  /**
23
35
  * Exchange the D2L session cookies for a fresh Bearer token in one request.
24
36
  * This is the cheap alternative to relaunching Chromium when the JWT expires.
25
37
  *
26
- * Classification order matters: a network throw is transport, the expiry marker
27
- * wins over the status code, then a non-2xx status, then a missing access_token.
38
+ * Only a 401 or the known login redirect proves session expiry. Server errors,
39
+ * permission failures and unknown response formats remain temporary failures.
28
40
  */
29
41
  export async function mintAccessToken({ baseUrl, cookieHeader, csrfToken, fetchImpl = fetch, timeoutMs = DEFAULT_TIMEOUT_MS, }) {
30
42
  const url = `${baseUrl.replace(/\/+$/, "")}/d2l/lp/auth/oauth2/token`;
31
43
  let status;
32
44
  let body;
45
+ let location;
33
46
  try {
34
47
  const response = await fetchImpl(url, {
35
48
  method: "POST",
@@ -41,28 +54,37 @@ export async function mintAccessToken({ baseUrl, cookieHeader, csrfToken, fetchI
41
54
  },
42
55
  body: "scope=*:*:*",
43
56
  signal: AbortSignal.timeout(timeoutMs),
57
+ redirect: "manual",
44
58
  });
45
59
  status = response.status;
46
60
  body = await response.text();
61
+ location = response.headers?.get("location") ?? null;
47
62
  }
48
63
  catch (error) {
49
64
  const message = error instanceof Error ? error.message : String(error);
50
65
  return transport(message);
51
66
  }
52
- if (body.includes(EXPIRED_MARKER)) {
67
+ if (status >= 500 || status === 429)
68
+ return transport(`HTTP ${status}`);
69
+ let payload = null;
70
+ try {
71
+ payload = JSON.parse(body);
72
+ }
73
+ catch {
74
+ // The known expired-session response is an HTML login redirect.
75
+ }
76
+ if (status === 401 || (!payload && body.includes(EXPIRED_MARKER)) ||
77
+ expiredRedirect(location, url)) {
53
78
  log("DEBUG", "The token mint answered with the session-expired stub");
54
79
  return { ok: false, reason: "sessionExpired" };
55
80
  }
56
81
  if (status < 200 || status >= 300) {
57
82
  return transport(`HTTP ${status}`);
58
83
  }
59
- let accessToken;
60
- try {
61
- accessToken = JSON.parse(body).access_token;
62
- }
63
- catch {
84
+ if (!payload) {
64
85
  return transport("the token mint returned an unparseable body");
65
86
  }
87
+ const accessToken = payload.access_token;
66
88
  if (typeof accessToken !== "string" || accessToken.length === 0) {
67
89
  return transport("the token mint returned no access_token");
68
90
  }
@@ -1 +1 @@
1
- {"version":3,"file":"token-mint.js","sourceRoot":"","sources":["../../src/auth/token-mint.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAE1C,iFAAiF;AACjF,MAAM,UAAU,GACd,gFAAgF,CAAC;AAEnF,MAAM,kBAAkB,GAAG,KAAK,CAAC;AAiBjC,MAAM,SAAS,GAAG,CAAC,MAAc,EAAc,EAAE,CAAC,CAAC;IACjD,EAAE,EAAE,KAAK;IACT,MAAM,EAAE,WAAW;IACnB,MAAM;CACP,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EACpC,OAAO,EACP,YAAY,EACZ,SAAS,EACT,SAAS,GAAG,KAAK,EACjB,SAAS,GAAG,kBAAkB,GAClB;IACZ,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,2BAA2B,CAAC;IAEtE,IAAI,MAAc,CAAC;IACnB,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;YACpC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,mCAAmC;gBACnD,MAAM,EAAE,YAAY;gBACpB,cAAc,EAAE,SAAS;gBACzB,YAAY,EAAE,UAAU;aACzB;YACD,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC;SACvC,CAAC,CAAC;QACH,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;QACzB,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QAClC,GAAG,CAAC,OAAO,EAAE,uDAAuD,CAAC,CAAC;QACtE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IAED,IAAI,MAAM,GAAG,GAAG,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC,QAAQ,MAAM,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,WAAoB,CAAC;IACzB,IAAI,CAAC;QACH,WAAW,GAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgC,CAAC,YAAY,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC,6CAA6C,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChE,OAAO,SAAS,CAAC,yCAAyC,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"token-mint.js","sourceRoot":"","sources":["../../src/auth/token-mint.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,4 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Brightspace MCP Server
4
- * Copyright (c) 2026 Rohan Muppa. All rights reserved.
5
- * Licensed under MIT — see LICENSE file for details.
6
- *
7
- * https://github.com/rohanmuppa/brightspace-mcp-server
8
- */
2
+ /** Brightspace MCP Server. Copyright (c) 2026 Rohan Muppa. MIT licensed. */
9
3
  export {};
10
4
  //# sourceMappingURL=auth-cli.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-cli.d.ts","sourceRoot":"","sources":["../src/auth-cli.ts"],"names":[],"mappings":";AACA;;;;;;GAMG"}
1
+ {"version":3,"file":"auth-cli.d.ts","sourceRoot":"","sources":["../src/auth-cli.ts"],"names":[],"mappings":";AACA,4EAA4E"}
package/build/auth-cli.js CHANGED
@@ -1,93 +1,49 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Brightspace MCP Server
4
- * Copyright (c) 2026 Rohan Muppa. All rights reserved.
5
- * Licensed under MIT — see LICENSE file for details.
6
- *
7
- * https://github.com/rohanmuppa/brightspace-mcp-server
8
- */
9
- import * as fs from "node:fs/promises";
2
+ /** Brightspace MCP Server. Copyright (c) 2026 Rohan Muppa. MIT licensed. */
10
3
  import { readFileSync } from "node:fs";
11
4
  import * as path from "node:path";
12
5
  import { fileURLToPath } from "node:url";
13
6
  import dotenv from "dotenv";
14
7
  import { loadConfig } from "./utils/config.js";
15
8
  import { BrowserAuth, TokenManager } from "./auth/index.js";
16
- // Load .env file so credentials are available via process.env
9
+ import { NativeCredentialStoreError } from "./auth/credential-store.js";
10
+ import { retireLegacyProfile } from "./auth/legacy-profile.js";
17
11
  dotenv.config({ quiet: true });
18
- const pkgVersion = (() => {
19
- try {
20
- const pkg = JSON.parse(readFileSync(path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf-8"));
21
- return pkg.version ?? "unknown";
22
- }
23
- catch {
24
- return "unknown";
25
- }
26
- })();
12
+ const pkg = JSON.parse(readFileSync(path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf8"));
27
13
  async function main() {
14
+ const automatic = process.argv.includes("--automatic");
28
15
  try {
29
- // Load configuration from environment
30
- const config = loadConfig();
31
- // Print header
32
- console.log(`\n=== Brightspace Authentication v${pkgVersion} - by Rohan Muppa ===\n`);
33
- // Check for credentials and provide status
34
- if (config.username && config.password) {
35
- console.log(`Authenticating as: ${config.username}`);
36
- console.log("Approve the sign-in request in Microsoft Authenticator when prompted.");
37
- console.log("If it shows a number, it is printed below: enter that number in the app.");
38
- }
39
- else {
40
- console.log("No credentials. Opening browser for manual login.");
41
- }
42
- console.log("\nStarting authentication...\n");
43
- // Create BrowserAuth with config
44
- const browserAuth = new BrowserAuth(config);
45
- // Authenticate and get token
46
- const token = await browserAuth.authenticate();
47
- // Create TokenManager and persist token
16
+ const config = await loadConfig();
17
+ console.error(`\n=== Brightspace Authentication v${pkg.version} ===\n`);
18
+ console.error("Authentication runs headlessly. If Microsoft requests MFA, the number appears here.");
48
19
  const tokenManager = new TokenManager({
49
20
  sessionDir: config.sessionDir,
50
21
  baseUrl: config.baseUrl,
51
22
  tokenTtl: config.tokenTtl,
52
23
  });
53
- await tokenManager.setToken(token);
54
- // Verify session.json was actually written to disk
55
- const sessionFile = path.join(config.sessionDir, "session.json");
56
- try {
57
- await fs.access(sessionFile);
58
- }
59
- catch {
60
- console.error(`\nWARNING: session.json was not found at ${sessionFile} after save.`);
61
- console.error("Token was captured but failed to persist. Retrying save...");
62
- // Retry once — the directory should already exist from the first attempt
63
- await tokenManager.setToken(token);
64
- try {
65
- await fs.access(sessionFile);
66
- console.log("Retry succeeded — session.json saved.");
67
- }
68
- catch {
69
- console.error("Retry failed. Check directory permissions on", config.sessionDir);
70
- process.exit(1);
71
- }
72
- }
73
- // Print success
74
- console.log("\n=== Authentication successful! ===");
75
- console.log(`Session saved to ${sessionFile}`);
76
- console.log("\nThe MCP server will use this token automatically.");
77
- console.log("You can now add the server to your Claude Desktop configuration.\n");
78
- process.exit(0);
24
+ await new BrowserAuth(config).authenticate({
25
+ automatic,
26
+ onAuthenticated: async (token) => {
27
+ await tokenManager.setToken(token);
28
+ await retireLegacyProfile(config.sessionDir);
29
+ if (config.legacyBrowserStateMigrated && config.sessionRoot && config.sessionRoot !== config.sessionDir) {
30
+ await retireLegacyProfile(config.sessionRoot);
31
+ }
32
+ },
33
+ });
34
+ console.error("\nAuthentication successful. Your encrypted session is ready for the MCP server.");
79
35
  }
80
36
  catch (error) {
81
- console.error("\n=== Authentication failed ===");
82
- console.error("\nError:", error instanceof Error ? error.message : String(error));
83
- console.error("\nTroubleshooting tips:");
84
- console.error("1. Ensure D2L_USERNAME and D2L_PASSWORD are set correctly in .env");
85
- console.error("2. If MFA approval failed, approve the sign-in request in Microsoft Authenticator, entering the number shown above if there was one");
86
- console.error("3. Check that you have a stable internet connection");
87
- console.error("4. Try running with D2L_HEADLESS=false to see the browser");
88
- console.error("\nFor more details, check the error message above.\n");
89
- process.exit(1);
37
+ const code = error?.code;
38
+ process.exitCode = error instanceof NativeCredentialStoreError ? 5
39
+ : code === "AUTH_IN_PROGRESS" ? 2
40
+ : code === "AUTH_COOLDOWN" ? 3
41
+ : code === "AUTH_UNSUPPORTED" ? 4
42
+ : code === "AUTH_TRANSPORT" ? 6 : 1;
43
+ console.error("\nAuthentication failed:", error instanceof Error ? error.message : "Unknown authentication error");
44
+ console.error("Run `npx brightspace-mcp-server setup` to update saved credentials.");
45
+ console.error("Run `npx brightspace-mcp-server auth` to retry explicitly. This bypasses the automatic MFA cooldown.");
90
46
  }
91
47
  }
92
- main();
48
+ await main();
93
49
  //# sourceMappingURL=auth-cli.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-cli.js","sourceRoot":"","sources":["../src/auth-cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth-cli.js","sourceRoot":"","sources":["../src/auth-cli.ts"],"names":[],"mappings":"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"}
package/build/index.js CHANGED
@@ -47,14 +47,14 @@ else {
47
47
  async function main() {
48
48
  try {
49
49
  // Load configuration
50
- const config = loadConfig();
50
+ const config = await loadConfig();
51
51
  log("DEBUG", "Configuration loaded", { sessionDir: config.sessionDir });
52
52
  // Create MCP server instance
53
53
  const server = new McpServer({
54
54
  name: "brightspace",
55
55
  version: PKG_VERSION,
56
56
  description: "Brightspace MCP Server — by Rohan Muppa (github.com/rohanmuppa/brightspace-mcp-server)",
57
- });
57
+ }, { capabilities: { logging: {} } });
58
58
  log("INFO", "");
59
59
  log("INFO", "========================================");
60
60
  log("INFO", ` Brightspace MCP Server v${PKG_VERSION}`);
@@ -69,7 +69,11 @@ else {
69
69
  tokenTtl: config.tokenTtl,
70
70
  });
71
71
  // Create AuthRunner for auto-reauthentication
72
- const authRunner = new AuthRunner();
72
+ const authRunner = new AuthRunner({
73
+ onProgress: (message) => {
74
+ void server.sendLoggingMessage({ level: "info", logger: "brightspace-auth", data: message }).catch(() => { });
75
+ },
76
+ });
73
77
  // Create D2L API Client with auto-reauth support
74
78
  const apiClient = new D2LApiClient({
75
79
  baseUrl: config.baseUrl,
@@ -111,7 +115,7 @@ else {
111
115
  type: "text",
112
116
  text: "Not authenticated. Auto-reauthentication was attempted but failed. " +
113
117
  "Please run `brightspace-auth` manually in your terminal to log in. " +
114
- "Make sure your credentials in .env are correct and your internet connection is stable.",
118
+ "Run setup to update your saved credentials, and check your internet connection.",
115
119
  },
116
120
  ];
117
121
  const notice = getUpdateNotice();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}