Changeset b919a67 in Klonkt


Ignore:
Timestamp:
06/19/2026 08:00:37 AM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
2900f1d
Parents:
70679063
Message:

auth: all Google login errors as clear explanation blocks (codes instead of bare alert)

The Google callback now redirects with ?gerr=<code> (admin/session/email/linked/
unavailable/failed) and auth-login.ejs maps each code to a clear explanation block
with icon + heading + text (admin gets the two login paths as well). Completes the
error indication consistently; free-form ?error= text remains as fallback for the
regular alert.

Co-Authored-By: Claude <noreply@…>

Location:
src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/routes/auth.js

    r70679063 rb919a67  
    236236router.get('/google', (req, res) => {
    237237  if (!fanLoginReady()) {
    238     return res.redirect('/auth/login?error=' + encodeURIComponent('Inloggen met Google is op deze site niet beschikbaar.'));
     238    return res.redirect('/auth/login?gerr=unavailable');
    239239  }
    240240  const state = crypto.randomBytes(16).toString('hex');
     
    256256
    257257router.get('/google/callback', async (req, res) => {
    258   const fail = (msg) => res.redirect('/auth/login?error=' + encodeURIComponent(msg));
    259   if (!fanLoginReady()) return fail('Inloggen met Google is op deze site niet beschikbaar.');
     258  const fail = (code) => res.redirect('/auth/login?gerr=' + code);
     259  if (!fanLoginReady()) return fail('unavailable');
    260260  try {
    261261    const { code, state } = req.query;
    262     if (!code || !state || state !== req.session.oauthState) return fail('Login afgebroken of ongeldige sessie.');
     262    if (!code || !state || state !== req.session.oauthState) return fail('session');
    263263    const next = safeNext(req.session.oauthNext) || '';
    264264    delete req.session.oauthState;
     
    268268    const info = await fetchUserinfo(tok.access_token);
    269269    const email = (info.email || '').trim().toLowerCase();
    270     if (!email || info.email_verified === false) return fail('Geen geverifieerd Google-e-mailadres.');
     270    if (!email || info.email_verified === false) return fail('email');
    271271
    272272    let user = db.prepare('SELECT * FROM users WHERE LOWER(email) = ?').get(email);
     
    277277      if (user.role === 'god' || user.role === 'admin') {
    278278        // Eigen, duidelijke uitleg-pagina (zie auth-login.ejs) i.p.v. een kale melding.
    279         return res.redirect('/auth/login?gerr=admin');
     279        return fail('admin');
    280280      }
    281281      // Bestaande luisteraar: koppel google_sub/avatar als die ontbreken; weiger
    282282      // als al aan een ander Google-account gekoppeld.
    283283      if (user.google_sub && info.sub && user.google_sub !== info.sub) {
    284         return fail('Dit e-mailadres is al aan een ander Google-account gekoppeld.');
     284        return fail('linked');
    285285      }
    286286      db.prepare(`
     
    307307  } catch (e) {
    308308    console.error('[auth/google/callback]', e.message);
    309     fail('Google-login mislukt. Probeer opnieuw.');
     309    fail('failed');
    310310  }
    311311});
  • src/views/pages/auth-login.ejs

    r70679063 rb919a67  
    22  <h1>Inloggen</h1>
    33  <% if (typeof success !== 'undefined' && success) { %><div class="alert alert-success"><%= success %></div><% } %>
    4   <% if (typeof gerr !== 'undefined' && gerr === 'admin') { %>
     4  <%
     5    var GMAP = {
     6      admin: { icon: '🔐', title: 'Dit is een beheerders-account',
     7        body: 'Je logde in met Google, maar dit e-mailadres hoort bij de beheerder van deze site. Inloggen met Google is alleen voor luisteraars/fans — beheerders gebruiken altijd hun wachtwoord (zo kan een Google-login nooit per ongeluk beheerrechten geven).',
     8        list: ['<strong>Ben je de beheerder?</strong> Log hieronder in met je <strong>gebruikersnaam + wachtwoord</strong>.', '<strong>Wil je als fan inloggen?</strong> Gebruik een <strong>ander Google-account</strong> (niet je beheerdersadres).'] },
     9      session: { icon: '⏱️', title: 'Login afgebroken', body: 'De Google-login is afgebroken of de sessie was verlopen. Probeer het gewoon opnieuw.' },
     10      email: { icon: '✉️', title: 'Geen geverifieerd e-mailadres', body: 'Je Google-account heeft geen geverifieerd e-mailadres. Verifieer je adres bij Google, of log in met je wachtwoord.' },
     11      linked: { icon: '🔗', title: 'Adres al gekoppeld', body: 'Dit e-mailadres is al aan een ander Google-account gekoppeld. Gebruik dat account, of neem contact op met de beheerder.' },
     12      unavailable: { icon: '🚫', title: 'Google-login niet beschikbaar', body: 'Inloggen met Google is op deze site (nog) niet ingesteld. Log in met je gebruikersnaam en wachtwoord.' },
     13      failed: { icon: '⚠️', title: 'Google-login mislukt', body: 'Er ging iets mis bij het inloggen met Google. Probeer het opnieuw.' },
     14    };
     15    var _g = (typeof gerr !== 'undefined' && gerr && GMAP[gerr]) ? GMAP[gerr] : null;
     16  %>
     17  <% if (_g) { %>
    518    <div class="auth-notice">
    6       <div class="auth-notice-icon">🔐</div>
    7       <h2 class="auth-notice-title">Dit is een beheerders-account</h2>
    8       <p>Je logde in met Google, maar dit e-mailadres hoort bij de <strong>beheerder</strong> van deze site.
    9          Inloggen met Google is alleen voor luisteraars/fans — beheerders gebruiken altijd hun wachtwoord
    10          (zo kan een Google-login nooit per ongeluk beheerrechten geven).</p>
    11       <ul class="auth-notice-list">
    12         <li><strong>Ben je de beheerder?</strong> Log hieronder in met je <strong>gebruikersnaam + wachtwoord</strong>.</li>
    13         <li><strong>Wil je als fan inloggen?</strong> Gebruik een <strong>ander Google-account</strong> (niet je beheerdersadres).</li>
    14       </ul>
     19      <div class="auth-notice-icon"><%= _g.icon %></div>
     20      <h2 class="auth-notice-title"><%= _g.title %></h2>
     21      <p><%= _g.body %></p>
     22      <% if (_g.list) { %><ul class="auth-notice-list"><% _g.list.forEach(function(li){ %><li><%- li %></li><% }); %></ul><% } %>
    1523    </div>
    1624  <% } else if (error) { %><div class="alert alert-error"><%= error %></div><% } %>
Note: See TracChangeset for help on using the changeset viewer.