MCPcopy
hub / github.com/MiniMax-AI/cli / deviceCodeLogin

Function deviceCodeLogin

src/auth/oauth.ts:35–114  ·  view source on GitHub ↗
(region: Region)

Source from the content-addressed store, hash-verified

33 * user code, and polls /oauth2/token until the user approves.
34 */
35export async function deviceCodeLogin(region: Region): Promise<OAuthCredentials> {
36 const host = OAUTH_HOSTS[region];
37
38 const { randomBytes, createHash } = await import('crypto');
39 const codeVerifier = randomBytes(32).toString('base64url');
40 const codeChallenge = createHash('sha256').update(codeVerifier).digest('base64url');
41 const state = randomBytes(16).toString('base64url');
42
43 const codeRes = await fetch(`${host}/oauth2/device/code`, {
44 method: 'POST',
45 headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
46 body: new URLSearchParams({
47 client_id: CLIENT_ID,
48 scope: SCOPES.join(' '),
49 code_challenge: codeChallenge,
50 code_challenge_method: 'S256',
51 state,
52 }),
53 });
54
55 if (!codeRes.ok) {
56 const body = await codeRes.text().catch(() => '');
57 throw new CLIError(
58 `Failed to start device-code flow (HTTP ${codeRes.status}).`,
59 ExitCode.AUTH,
60 body || `URL: ${host}/oauth2/device/code`,
61 );
62 }
63
64 const data = (await codeRes.json()) as DeviceCodeResponse;
65 if (data.state !== state) {
66 throw new CLIError('OAuth state mismatch.', ExitCode.AUTH);
67 }
68
69 openBrowser(data.verification_uri);
70 process.stderr.write(`\nOpened: ${data.verification_uri}\n`);
71 process.stderr.write(`Code: ${data.user_code}\n`);
72 process.stderr.write(`Client: ${CLIENT_NAME}\n`);
73 process.stderr.write('Waiting for authorization...\n');
74
75 const deadline = data.expired_in;
76 const intervalMs = data.interval || 3000;
77
78 while (Date.now() < deadline) {
79 await sleep(intervalMs);
80
81 const tokRes = await fetch(`${host}/oauth2/token`, {
82 method: 'POST',
83 headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
84 body: new URLSearchParams({
85 grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
86 client_id: CLIENT_ID,
87 user_code: data.user_code,
88 code_verifier: codeVerifier,
89 }),
90 });
91
92 if (!tokRes.ok) {

Callers 2

runOAuthLoginFunction · 0.90
oauth.test.tsFile · 0.85

Calls 4

fetchFunction · 0.85
openBrowserFunction · 0.85
sleepFunction · 0.85
updateMethod · 0.65

Tested by

no test coverage detected