|
|
@@ -552,21 +552,15 @@ export async function XaiAuthPlugin(input: PluginInput, options: XaiAuthPluginOp
|
|
|
label: "xAI Grok OAuth (SuperGrok Subscription)",
|
|
|
type: "oauth",
|
|
|
authorize: async () => {
|
|
|
- await startOAuthServer()
|
|
|
- const pkce = await generatePKCE()
|
|
|
- const state = generateState()
|
|
|
- const nonce = generateState()
|
|
|
- const authUrl = buildAuthorizeUrl(pkce, state, nonce, options)
|
|
|
-
|
|
|
- const callbackPromise = waitForOAuthCallback(pkce, state)
|
|
|
-
|
|
|
+ const device = await requestDeviceCode(options)
|
|
|
+ const browserUrl = device.verification_uri_complete ?? device.verification_uri
|
|
|
return {
|
|
|
- url: authUrl,
|
|
|
- instructions: "Complete authorization in your browser. This window will close automatically.",
|
|
|
+ url: browserUrl,
|
|
|
+ instructions: `Open ${device.verification_uri} on any device and enter code: ${device.user_code}`,
|
|
|
method: "auto" as const,
|
|
|
callback: async () => {
|
|
|
try {
|
|
|
- const tokens = await callbackPromise
|
|
|
+ const tokens = await pollDeviceCodeToken(device, options)
|
|
|
return {
|
|
|
type: "success" as const,
|
|
|
refresh: tokens.refresh_token,
|
|
|
@@ -575,34 +569,30 @@ export async function XaiAuthPlugin(input: PluginInput, options: XaiAuthPluginOp
|
|
|
}
|
|
|
} catch (err) {
|
|
|
return { type: "failed" as const }
|
|
|
- } finally {
|
|
|
- stopOAuthServer()
|
|
|
}
|
|
|
},
|
|
|
}
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
- // RFC 8628 device-code flow. The CLI prints a verification URL
|
|
|
- // and a short user_code that the user enters in a browser on
|
|
|
- // any device. No loopback callback server runs on the CLI host,
|
|
|
- // so this works on VPS / SSH / Docker / CI / WSL / any
|
|
|
- // environment where 127.0.0.1:56121 isn't reachable from the
|
|
|
- // user's browser. Defends the only attack surface (the polling
|
|
|
- // loop) with the standard authorization_pending / slow_down
|
|
|
- // backoff and a hard deadline from xAI's `expires_in`.
|
|
|
- label: "xAI Grok OAuth (Headless / Remote / VPS)",
|
|
|
+ label: "xAI Grok OAuth (Local Callback)",
|
|
|
type: "oauth",
|
|
|
authorize: async () => {
|
|
|
- const device = await requestDeviceCode(options)
|
|
|
- const browserUrl = device.verification_uri_complete ?? device.verification_uri
|
|
|
+ await startOAuthServer()
|
|
|
+ const pkce = await generatePKCE()
|
|
|
+ const state = generateState()
|
|
|
+ const nonce = generateState()
|
|
|
+ const authUrl = buildAuthorizeUrl(pkce, state, nonce, options)
|
|
|
+
|
|
|
+ const callbackPromise = waitForOAuthCallback(pkce, state)
|
|
|
+
|
|
|
return {
|
|
|
- url: browserUrl,
|
|
|
- instructions: `Open ${device.verification_uri} on any device and enter code: ${device.user_code}`,
|
|
|
+ url: authUrl,
|
|
|
+ instructions: "Complete authorization in your browser. This window will close automatically.",
|
|
|
method: "auto" as const,
|
|
|
callback: async () => {
|
|
|
try {
|
|
|
- const tokens = await pollDeviceCodeToken(device, options)
|
|
|
+ const tokens = await callbackPromise
|
|
|
return {
|
|
|
type: "success" as const,
|
|
|
refresh: tokens.refresh_token,
|
|
|
@@ -611,6 +601,8 @@ export async function XaiAuthPlugin(input: PluginInput, options: XaiAuthPluginOp
|
|
|
}
|
|
|
} catch (err) {
|
|
|
return { type: "failed" as const }
|
|
|
+ } finally {
|
|
|
+ stopOAuthServer()
|
|
|
}
|
|
|
},
|
|
|
}
|