image
(function() { // Utility: Generate PKCE code verifier function generateCodeVerifier() { const array = new Uint32Array(56); window.crypto.getRandomValues(array); return Array.from(array, dec => ('0' + dec.toString(16)).substr(-2)).join(''); } // Utility: Generate PKCE code challenge from verifier async function generateCodeChallenge(codeVerifier) { const encoder = new TextEncoder(); const data = encoder.encode(codeVerifier); const digest = await window.crypto.subtle.digest('SHA-256', data); return btoa(String.fromCharCode(...new Uint8Array(digest))) .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); } // Initiate Vipps login when button clicked document.addEventListener('DOMContentLoaded', () => { const loginBtn = document.getElementById('vipps-login'); if (loginBtn) { loginBtn.addEventListener('click', async () => { const codeVerifier = generateCodeVerifier(); sessionStorage.setItem('pkce_verifier', codeVerifier); const codeChallenge = await generateCodeChallenge(codeVerifier); // Build the authorization URL exactly as Vipps expects const authUrl = 'https://api.vippsmobilepay.com/access-management-1.0/access/oauth2/auth?' + `client_id=${encodeURIComponent(window.VIPPS_CONFIG.CLIENT_ID)}` + `&redirect_uri=${encodeURIComponent(window.VIPPS_CONFIG.REDIRECT_URI)}` + `&response_type=code` + `&scope=${encodeURIComponent(window.VIPPS_CONFIG.SCOPES)}` + `&code_challenge=${codeChallenge}` + `&code_challenge_method=S256`; window.location.href = authUrl; }); } }); // Handle Vipps OAuth callback on /auth/callback page if (window.location.pathname === '/auth/callback') { (async () => { const params = new URLSearchParams(window.location.search); const code = params.get('code'); const codeVerifier = sessionStorage.getItem('pkce_verifier'); if (!code) { document.body.innerHTML = '

Error: No authorization code found in URL.

'; return; } // Exchange authorization code for tokens const tokenResponse = await fetch('https://api.vippsmobilepay.com/access-management-1.0/access/oauth2/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ client_id: window.VIPPS_CONFIG.CLIENT_ID, code_verifier: codeVerifier, grant_type: 'authorization_code', redirect_uri: window.VIPPS_CONFIG.REDIRECT_URI, code: code }) }); if (!tokenResponse.ok) { document.body.innerHTML = `

Error exchanging code for token: ${tokenResponse.statusText}

`; return; } const { access_token, id_token } = await tokenResponse.json(); // Fetch user info from Vipps const userInfoResponse = await fetch('https://api.vippsmobilepay.com/vipps-userinfo-api/userinfo', { headers: { 'Authorization': `Bearer ${access_token}` } }); if (!userInfoResponse.ok) { document.body.innerHTML = `

Error fetching user info: ${userInfoResponse.statusText}

`; return; } const userInfo = await userInfoResponse.json(); // Store user info securely in sessionStorage (consider cookies for production) sessionStorage.setItem('vipps_sub', userInfo.sub); sessionStorage.setItem('vipps_email', userInfo.email); sessionStorage.setItem('vipps_name', userInfo.name || ''); // Clean up PKCE verifier sessionStorage.removeItem('pkce_verifier'); // Redirect user to your JSM portal (replace with your actual portal URL) window.location.href = 'https://hjelp.nettvis.no/servicedesk/customer/portal/1?sub=' + encodeURIComponent(userInfo.sub); })(); } })();