UNPKG

@warriorteam/redai-zalo-sdk

Version:

Comprehensive TypeScript/JavaScript SDK for Zalo APIs - Official Account, ZNS, Consultation Service, Group Messaging, and Social APIs

180 lines (142 loc) 5.89 kB
/** * Example: Official Account Authentication with PKCE * Demonstrates how to use the updated createOAAuthUrl method with PKCE support */ import { ZaloSDK } from '../src'; // Initialize SDK const sdk = new ZaloSDK({ appId: 'your_app_id', appSecret: 'your_app_secret', }); // Example 1: Basic OA Auth without PKCE async function basicOAAuth() { console.log('=== Basic OA Auth (without PKCE) ==='); const redirectUri = 'https://your-app.com/callback'; // Create auth URL - state will be auto-generated with 'zalo_oa_' prefix const authResult = sdk.auth.createOAAuthUrl(redirectUri); console.log('Authorization URL:', authResult.url); console.log('Generated State:', authResult.state); // You can also provide custom state const customAuthResult = sdk.auth.createOAAuthUrl(redirectUri, 'my_custom_state'); console.log('Custom State URL:', customAuthResult.url); console.log('Custom State:', customAuthResult.state); } // Example 2: OA Auth with PKCE for enhanced security (Manual PKCE) async function oaAuthWithPKCE() { console.log('\n=== OA Auth with Manual PKCE ==='); const redirectUri = 'https://your-app.com/callback'; // Step 1: Generate PKCE configuration const pkce = sdk.auth.generatePKCE(); console.log('Generated PKCE:'); console.log('- Code Verifier:', pkce.code_verifier); console.log('- Code Challenge:', pkce.code_challenge); console.log('- Challenge Method:', pkce.code_challenge_method); // Step 2: Create auth URL with manual PKCE const authResult = sdk.auth.createOAAuthUrl(redirectUri, undefined, pkce, true); console.log('\nAuthorization URL with PKCE:', authResult.url); console.log('Generated State:', authResult.state); console.log('Used PKCE:', authResult.pkce); // IMPORTANT: Store the code_verifier and state for later use // You'll need these when exchanging the authorization code for access token console.log('\n⚠️ IMPORTANT: Store these values for token exchange:'); console.log('- Code Verifier:', pkce.code_verifier); console.log('- State:', authResult.state); return { pkce, state: authResult.state }; } // Example 2b: OA Auth with Auto-Generated PKCE async function oaAuthWithAutoPKCE() { console.log('\n=== OA Auth with Auto-Generated PKCE ==='); const redirectUri = 'https://your-app.com/callback'; // Create auth URL with auto-generated PKCE (pkce=undefined, usePkce=true) const authResult = sdk.auth.createOAAuthUrl(redirectUri, undefined, undefined, true); console.log('Authorization URL with Auto PKCE:', authResult.url); console.log('Generated State:', authResult.state); console.log('Auto-Generated PKCE:', authResult.pkce); // IMPORTANT: Store the auto-generated PKCE and state console.log('\n⚠️ IMPORTANT: Store these auto-generated values:'); console.log('- Code Verifier:', authResult.pkce?.code_verifier); console.log('- State:', authResult.state); return authResult; } // Example 3: Complete flow - Authorization + Token Exchange async function completeOAFlow() { console.log('\n=== Complete OA Flow with PKCE ==='); const redirectUri = 'https://your-app.com/callback'; // Step 1: Generate PKCE and create auth URL const pkce = sdk.auth.generatePKCE(); const authResult = sdk.auth.createOAAuthUrl(redirectUri, 'my_oa_flow', pkce); console.log('1. Redirect user to:', authResult.url); console.log('2. Store state and code_verifier:', { state: authResult.state, code_verifier: pkce.code_verifier }); // Step 2: After user authorizes and returns with code // (This would happen in your callback handler) const simulateCallback = async (authorizationCode: string, returnedState: string) => { console.log('\n3. User returned with authorization code'); // Verify state matches if (returnedState !== authResult.state) { throw new Error('State mismatch - possible CSRF attack'); } // Step 3: Exchange code for access token with PKCE try { const tokenResult = await sdk.auth.getOAAccessToken({ app_id: 'your_app_id', app_secret: 'your_app_secret', code: authorizationCode, redirect_uri: redirectUri, code_verifier: pkce.code_verifier, // Include code_verifier for PKCE }); console.log('4. Successfully obtained access token:', { access_token: tokenResult.access_token.substring(0, 20) + '...', expires_in: tokenResult.expires_in, has_refresh_token: !!tokenResult.refresh_token }); return tokenResult; } catch (error) { console.error('Failed to exchange code for token:', error); throw error; } }; // Simulate the callback (in real app, this would be handled by your callback endpoint) console.log('\n--- Simulating callback ---'); // await simulateCallback('simulated_auth_code', authResult.state); } // Example 4: Using getAuthUrls method async function getAuthUrlsExample() { console.log('\n=== Get Auth URLs ==='); const redirectUri = 'https://your-app.com/callback'; const pkce = sdk.auth.generatePKCE(); const authUrls = sdk.auth.getAuthUrls(redirectUri, pkce); console.log('All auth URLs:', { oa_auth_url: authUrls.oa_auth_url, social_auth_url: authUrls.social_auth_url, token_url: authUrls.token_url, refresh_url: authUrls.refresh_url }); } // Run examples async function runExamples() { try { await basicOAAuth(); await oaAuthWithPKCE(); await oaAuthWithAutoPKCE(); await completeOAFlow(); await getAuthUrlsExample(); } catch (error) { console.error('Example error:', error); } } // Export for use in other files export { basicOAAuth, oaAuthWithPKCE, oaAuthWithAutoPKCE, completeOAFlow, getAuthUrlsExample, runExamples }; // Run if this file is executed directly if (require.main === module) { runExamples(); }