Skip to main content
Glama
get-oauth-token.ts4.84 kB
/** * Script to obtain OAuth 2.0 refresh token for Google Tasks API * * This script helps you get a refresh token for your private Google account. * * Usage: * 1. Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in .env * 2. Run: bun run get-oauth-token.ts * 3. Follow the instructions to authorize and get your refresh token */ import { google } from 'googleapis'; import { readFileSync, writeFileSync } from 'fs'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); // Load environment variables function loadEnv() { try { const envPath = join(__dirname, '.env'); const envContent = readFileSync(envPath, 'utf-8'); const env: Record<string, string> = {}; envContent.split('\n').forEach((line) => { const trimmed = line.trim(); if (trimmed && !trimmed.startsWith('#')) { const [key, ...valueParts] = trimmed.split('='); if (key && valueParts.length > 0) { env[key.trim()] = valueParts .join('=') .trim() .replace(/^["']|["']$/g, ''); } } }); return env; } catch { return {}; } } async function getRefreshToken() { const env = loadEnv(); const clientId = process.env.GOOGLE_CLIENT_ID || env.GOOGLE_CLIENT_ID; const clientSecret = process.env.GOOGLE_CLIENT_SECRET || env.GOOGLE_CLIENT_SECRET; if (!clientId || !clientSecret) { console.error('❌ Missing GOOGLE_CLIENT_ID or GOOGLE_CLIENT_SECRET'); console.error('\nPlease set these in your .env file:'); console.error(' GOOGLE_CLIENT_ID=your_client_id'); console.error(' GOOGLE_CLIENT_SECRET=your_client_secret'); console.error( '\nTo get these credentials, see: https://console.cloud.google.com/apis/credentials' ); process.exit(1); } const oauth2Client = new google.auth.OAuth2( clientId, clientSecret, 'http://localhost:3000/oauth2callback' // Redirect URI ); // Scopes required for Google Tasks API const scopes = ['https://www.googleapis.com/auth/tasks']; // Generate authorization URL const authUrl = oauth2Client.generateAuthUrl({ access_type: 'offline', // Required to get refresh token scope: scopes, prompt: 'consent', // Force consent screen to get refresh token }); console.log('🔐 OAuth 2.0 Authorization\n'); console.log('1. Open this URL in your browser:'); console.log(`\n ${authUrl}\n`); console.log('2. Sign in with your Google account'); console.log('3. Grant permission to access Google Tasks'); console.log('4. Copy the authorization code from the redirect URL\n'); console.log(' The redirect URL will look like:'); console.log(' http://localhost:3000/oauth2callback?code=4/0A...\n'); console.log('5. Paste the authorization code below:\n'); // Read authorization code from stdin const readline = await import('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); rl.question('Authorization code: ', async (code) => { rl.close(); try { const { tokens } = await oauth2Client.getToken(code.trim()); if (!tokens.refresh_token) { console.error('\n❌ No refresh token received. Make sure you:'); console.error(' - Used access_type=offline'); console.error(' - Used prompt=consent'); console.error(' - Are authorizing for the first time'); process.exit(1); } console.log('\n✅ Successfully obtained tokens!\n'); console.log('Your refresh token:'); console.log(` ${tokens.refresh_token}\n`); console.log('Add this to your .env file:'); console.log(` GOOGLE_REFRESH_TOKEN=${tokens.refresh_token}\n`); // Optionally save to .env try { const envPath = join(__dirname, '.env'); let envContent = ''; try { envContent = readFileSync(envPath, 'utf-8'); } catch { // File doesn't exist, that's OK } if (!envContent.includes('GOOGLE_REFRESH_TOKEN=')) { envContent += `\nGOOGLE_REFRESH_TOKEN=${tokens.refresh_token}\n`; writeFileSync(envPath, envContent); console.log('✅ Refresh token saved to .env file'); } else { console.log('⚠️ .env already contains GOOGLE_REFRESH_TOKEN'); console.log(' Please update it manually with the token above'); } } catch { console.log('⚠️ Could not auto-save to .env, please add manually'); } } catch (error) { console.error('\n❌ Failed to exchange authorization code:'); if (error instanceof Error) { console.error(` ${error.message}`); } process.exit(1); } }); } getRefreshToken();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/adamgrzybowski/google-task-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server