auth nonce storage and handling web redirect

This commit is contained in:
pashpashpash 2025-01-21 20:07:51 -08:00
parent a0690ee4ca
commit a655c55278
2 changed files with 30 additions and 6 deletions

View file

@ -2,6 +2,7 @@ import { Anthropic } from "@anthropic-ai/sdk"
import axios from "axios"
import fs from "fs/promises"
import os from "os"
import crypto from "crypto"
import pWaitFor from "p-wait-for"
import * as path from "path"
import * as vscode from "vscode"
@ -44,6 +45,7 @@ type SecretKey =
| "deepSeekApiKey"
| "mistralApiKey"
| "authToken"
| "authNonce"
type GlobalStateKey =
| "apiProvider"
| "apiModelId"
@ -595,12 +597,17 @@ export class ClineProvider implements vscode.WebviewViewProvider {
case "getLatestState":
await this.postStateToWebview()
break
case "accountButtonClicked":
// Open browser for authentication
console.log("Account button clicked in top nav bar")
console.log("Opening auth page: https://app.cline.bot/auth")
vscode.env.openExternal(vscode.Uri.parse('https://app.cline.bot/auth'))
break
case "accountButtonClicked": {
// Generate nonce for state validation
const nonce = crypto.randomBytes(32).toString('hex')
await this.storeSecret('authNonce', nonce)
// Open browser for authentication with state param
console.log("Account button clicked in top nav bar")
console.log("Opening auth page with state param")
vscode.env.openExternal(vscode.Uri.parse(`https://app.cline.bot/auth?state=${encodeURIComponent(nonce)}`))
break
}
case "openMcpSettings": {
const mcpSettingsFilePath = await this.mcpHub?.getMcpSettingsFilePath()
if (mcpSettingsFilePath) {
@ -749,6 +756,15 @@ export class ClineProvider implements vscode.WebviewViewProvider {
// Auth
public async validateAuthState(state: string | null): Promise<boolean> {
const storedNonce = await this.getSecret("authNonce")
if (!state || state !== storedNonce) {
return false
}
await this.storeSecret("authNonce", undefined) // Clear after use
return true
}
async handleAuthCallback(token: string) {
// Store the auth token securely
await this.storeSecret("authToken", token)

View file

@ -151,6 +151,14 @@ export function activate(context: vscode.ExtensionContext) {
}
case "/auth": {
const token = query.get("token")
const state = query.get("state")
// Validate state parameter
if (!await visibleProvider.validateAuthState(state)) {
vscode.window.showErrorMessage("Invalid auth state")
return
}
if (token) {
await visibleProvider.handleAuthCallback(token)
}