UNPKG

google-oauth-token-generator

Version:

A simple web-based tool to generate Google OAuth access tokens and refresh tokens

461 lines (428 loc) 18.9 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Google OAuth Access Token Creator</title> <style> body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; background-color: #f5f5f5; } .container { background-color: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); margin-bottom: 20px; } .input-group { margin-bottom: 15px; max-width: 500px; } input[type="text"] { width: 100%; padding: 8px; margin-top: 5px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; line-height: 1.5; height: 36px; box-sizing: border-box; } button { background-color: #4285f4; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; } button:hover { background-color: #357abd; } .result { margin-top: 20px; padding: 15px; border: 1px solid #ddd; border-radius: 4px; background-color: #f8f9fa; word-break: break-all; overflow-x: auto; } .hidden { display: none; } .instructions { background-color: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); margin-bottom: 20px; } .instructions ol { padding-left: 20px; } .instructions li { margin-bottom: 10px; } .instructions code { background: #f0f0f0; padding: 2px 5px; border-radius: 3px; } .note { background-color: #fff3cd; border: 1px solid #ffeeba; padding: 10px; border-radius: 4px; margin: 10px 0; } .token-container { position: relative; margin-bottom: 20px; } .copy-btn { position: absolute; top: 0; right: 0; padding: 5px 10px; background: #4285f4; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px; } .copy-btn:hover { background: #357abd; } .token-text { background: white; padding: 10px; border: 1px solid #ddd; border-radius: 4px; margin-top: 5px; white-space: pre-wrap; word-break: break-all; } .password-input-container { position: relative; display: flex; align-items: center; max-width: 500px; } .password-input-container input[type="password"], .password-input-container input[type="text"] { flex: 1; padding: 8px; margin-top: 5px; border: 1px solid #ddd; border-radius: 4px; width: 100%; font-size: 14px; line-height: 1.5; height: 36px; box-sizing: border-box; } .toggle-password { position: absolute; right: 5px; top: 50%; transform: translateY(-50%); margin-top: 2px; background: none; border: none; cursor: pointer; padding: 5px; color: #666; display: flex; align-items: center; justify-content: center; transition: color 0.2s ease; width: 30px; height: 30px; } .toggle-password:hover { background: none; color: #4285f4; } .toggle-password svg { width: 20px; height: 20px; fill: currentColor; } .eye-icon { font-size: 16px; line-height: 1; } input[type="text"][list] { width: 100%; padding: 8px; margin-top: 5px; border: 1px solid #ddd; border-radius: 4px; background-color: white; } input[type="text"][list]:focus { outline: none; border-color: #4285f4; box-shadow: 0 0 0 2px rgba(66, 133, 244, 0.2); } </style> </head> <body> <div class="instructions"> <h2>Setup Instructions</h2> <ol> <li> <strong>Go to Google Cloud Console:</strong> <br> <a href="https://console.cloud.google.com" target="_blank">https://console.cloud.google.com</a> </li> <li> <strong>Create a new project or select an existing one:</strong> <br> Click on the project selector in the top right corner → "New Project" or select an existing project </li> <li> <strong>Configure OAuth Settings:</strong> <br> Go to "APIs & Services" → "OAuth consent screen" and configure: <ul> <li>User Type: Select "External"</li> <li>Publishing Status: Set to "In Production" (Required for public access)</li> <li>Fill in the required information (App name, User support email, etc.)</li> <li>Add authorized domains if needed</li> </ul> </li> <li> <strong>Create credentials:</strong> <ul> <li>Go to "APIs & Services" → "Credentials" → "Create Credentials" → "OAuth client ID"</li> <li>Application type: Select "Web application"</li> <li>Authorized JavaScript origins: <code id="jsOrigin">Loading...</code></li> <li>Authorized redirect URIs: <code id="redirectUriExample">Loading...</code></li> <li>After creating, save both the Client ID and Client Secret - you'll need both</li> </ul> </li> <li> <strong>Copy your Client ID:</strong> <br> Paste the generated Client ID into the form below </li> </ol> <div class="note"> <strong>Important Note:</strong> <ul> <li>This application must be run on a web server (e.g., <code id="localExample">Loading...</code>).</li> <li>The default scope is set to <code>https://www.googleapis.com/auth/userinfo.profile</code>.</li> <li>Different APIs may require different scopes. Remember to enable the APIs you want to use in Google Cloud Console.</li> </ul> </div> <h3>Common Scopes:</h3> <ul> <li><code>https://www.googleapis.com/auth/userinfo.profile</code> - User profile information</li> <li><code>https://www.googleapis.com/auth/userinfo.email</code> - User email information</li> <li><code>https://www.googleapis.com/auth/calendar</code> - Google Calendar access</li> <li><code>https://www.googleapis.com/auth/drive</code> - Full Google Drive access</li> <li><code>https://www.googleapis.com/auth/gmail.readonly</code> - Gmail read-only access</li> </ul> <div class="note"> <strong>Other API Scopes:</strong> <p>You can find a complete list of scopes for all Google APIs in the official documentation:</p> <p><a href="https://developers.google.com/identity/protocols/oauth2/scopes" target="_blank">Google OAuth 2.0 Scopes for Google APIs</a></p> <p><strong>Note:</strong> Some scopes provide access to sensitive data and may require Google verification and app verification.</p> </div> </div> <div class="container"> <h1>Google OAuth Access Token Creator</h1> <div class="note"> <strong>Redirect URI:</strong> <code id="currentUrl">Loading...</code> <p>You must add this URL to both "Authorized JavaScript origins" and "Authorized redirect URIs" in Google Cloud Console.</p> </div> <div class="input-group"> <label for="clientId">Client ID:</label> <input type="text" id="clientId" placeholder="Enter your Google Client ID"> </div> <div class="input-group"> <label for="clientSecret">Client Secret:</label> <div class="password-input-container"> <input type="password" id="clientSecret" placeholder="Enter your Google Client Secret"> <button type="button" class="toggle-password" onclick="togglePasswordVisibility()" aria-label="Toggle password visibility"> <svg class="eye-show" viewBox="0 0 24 24"> <path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/> </svg> <svg class="eye-hide" viewBox="0 0 24 24" style="display: none;"> <path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"/> </svg> </button> </div> </div> <div class="input-group"> <label for="scope">Scope:</label> <input type="text" id="scope" list="scopeList" placeholder="Enter or select the required scope"> <datalist id="scopeList"> <option value="https://www.googleapis.com/auth/userinfo.profile">User Profile Information</option> <option value="https://www.googleapis.com/auth/userinfo.email">User Email Information</option> <option value="https://www.googleapis.com/auth/calendar">Google Calendar Access</option> <option value="https://www.googleapis.com/auth/drive">Google Drive Full Access</option> <option value="https://www.googleapis.com/auth/gmail.readonly">Gmail Read-only Access</option> <option value="https://www.googleapis.com/auth/cloud-platform">Google Cloud Platform Full Access</option> <option value="https://www.googleapis.com/auth/cloud-platform.read-only">Google Cloud Platform Read-only Access</option> <option value="https://www.googleapis.com/auth/youtube">YouTube Account Management</option> <option value="https://www.googleapis.com/auth/youtube.readonly">YouTube Read-only Access</option> <option value="https://www.googleapis.com/auth/youtube.upload">YouTube Video Management</option> <option value="https://www.googleapis.com/auth/yt-analytics.readonly">YouTube Analytics Access</option> <option value="https://www.googleapis.com/auth/youtube.force-ssl">YouTube Force SSL Access</option> <option value="https://www.googleapis.com/auth/admob.readonly">AdMob Read-only Access</option> <option value="https://www.googleapis.com/auth/admob.report">AdMob Reporting Access</option> </datalist> </div> <button onclick="initiateOAuth()">Get Access Token</button> <div id="result" class="result hidden"> <div class="token-container"> <h3>Access Token: <button onclick="copyToken()" class="copy-btn">Copy</button></h3> <div id="accessToken" class="token-text"></div> </div> <div class="token-container"> <h3>Refresh Token: <button onclick="copyRefreshToken()" class="copy-btn">Copy</button></h3> <div id="refreshToken" class="token-text"></div> </div> <div class="token-container"> <h3>Token Info: <button onclick="copyTokenInfo()" class="copy-btn">Copy</button></h3> <div id="tokenInfo" class="token-text"></div> </div> </div> </div> <script> // OAuth configuration const redirectUri = window.location.origin; // Display current URL in all places function updateUrls() { const elements = ['currentUrl', 'jsOrigin', 'redirectUriExample', 'localExample']; elements.forEach(id => { const element = document.getElementById(id); if (element) { element.textContent = redirectUri; } }); } // Update URLs immediately updateUrls(); function initiateOAuth() { const clientId = document.getElementById('clientId').value; const clientSecret = document.getElementById('clientSecret').value; const scope = document.getElementById('scope').value; if (!clientId) { alert('Please enter your Client ID'); return; } // Store credentials in the state parameter const state = btoa(JSON.stringify({ clientId, clientSecret })); const authUrl = `https://accounts.google.com/o/oauth2/v2/auth? client_id=${encodeURIComponent(clientId)}& redirect_uri=${encodeURIComponent(redirectUri)}& response_type=code& access_type=offline& prompt=consent& state=${encodeURIComponent(state)}& scope=${encodeURIComponent(scope)}& include_granted_scopes=true`; window.location.href = authUrl.replace(/\s/g, ''); } // Copy functions function copyToClipboard(text) { navigator.clipboard.writeText(text).then(() => { alert('Copied!'); }).catch(err => { console.error('Copy error:', err); alert('Copy failed'); }); } function copyToken() { const token = document.getElementById('accessToken').textContent; copyToClipboard(token); } function copyRefreshToken() { const token = document.getElementById('refreshToken').textContent; copyToClipboard(token); } function copyTokenInfo() { const info = document.getElementById('tokenInfo').textContent; copyToClipboard(info); } // Handle the OAuth callback window.onload = function() { // Display current URL updateUrls(); const urlParams = new URLSearchParams(window.location.search); const code = urlParams.get('code'); const state = urlParams.get('state'); if (code && state) { try { // Retrieve credentials from state parameter const credentials = JSON.parse(atob(state)); const clientId = credentials.clientId; const clientSecret = credentials.clientSecret; const tokenEndpoint = 'https://oauth2.googleapis.com/token'; const tokenRequest = { code: code, client_id: clientId, client_secret: clientSecret, redirect_uri: redirectUri, grant_type: 'authorization_code' }; fetch(tokenEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(tokenRequest) }) .then(response => response.json()) .then(data => { document.getElementById('result').classList.remove('hidden'); document.getElementById('accessToken').textContent = data.access_token; document.getElementById('refreshToken').textContent = data.refresh_token || 'No refresh token provided'; // Fetch token info return fetch(`https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=${data.access_token}`); }) .then(response => response.json()) .then(data => { document.getElementById('tokenInfo').textContent = JSON.stringify(data, null, 2); }) .catch(error => { console.error('Error:', error); alert('Error exchanging code for tokens. Check the console for details.'); }); } catch (error) { console.error('Error parsing state:', error); alert('Error retrieving credentials. Please try again.'); } } }; function togglePasswordVisibility() { const input = document.getElementById('clientSecret'); const showIcon = document.querySelector('.eye-show'); const hideIcon = document.querySelector('.eye-hide'); if (input.type === 'password') { input.type = 'text'; showIcon.style.display = 'none'; hideIcon.style.display = 'block'; } else { input.type = 'password'; showIcon.style.display = 'block'; hideIcon.style.display = 'none'; } } </script> </body> </html>