Skip to content

IdP login form re-renders silently on failed authentication — error not shown to user #514

@melvincarvalho

Description

@melvincarvalho

Problem

When a user submits the IdP's sign-in form with invalid credentials, handleLogin in src/idp/interactions.js correctly:

  1. Sets interaction.lastError = 'Invalid username or password' (line 121)
  2. Saves the interaction
  3. Redirects back to /idp/interaction/<uid>

The GET handler then re-renders loginPage(uid, params.client_id, interaction.lastError) — passing lastError as the third argument. The error message never appears in the rendered HTML. The page looks identical to the initial sign-in form. User has no idea what went wrong.

Symptom from the user's perspective

  • Click Sign In with wrong password
  • Page flickers / "reloads"
  • Same Sign In form appears
  • No red banner, no "Invalid username or password" text, nothing
  • User assumes the form is broken, retries identically, fails again

Where the rendering gap lives

loginPage() in src/idp/views.js accepts lastError (third positional arg per interactions.js:30) but apparently doesn't render it. Likely a missing template literal — the function probably accepted the parameter at some point but the HTML output never received the \${lastError} interpolation.

Quick check needed: grep lastError in src/idp/views.js. If absent or referenced but not in the output HTML, that's the gap.

Repro

jss start --port 5446 --single-user --single-user-password correct --idp \
  --root /tmp/jss-test/pod-data

Visit any path that triggers the IdP, e.g. http://localhost:5446/idp/auth?..., then submit Username: me, Password: wrong. Expected: visible error. Actual: silent re-render.

Why it matters

This is a credibility cliff. The OIDC handshake is most users' first contact with the server; if the login form silently fails, users assume the system is broken — not that they typed the wrong password. I wasted hours debugging an imagined OIDC regression here (now closed as #513) when the actual cause was a password mismatch that the IdP simply refused to surface.

Suggested fix

In src/idp/views.js's loginPage(), render lastError near the top of the form if truthy:

${lastError ? `<div class="auth-error" role="alert">${escapeHtml(lastError)}</div>` : ''}

Style with red text on a faint pink background, accessible via role="alert" so screen readers announce it.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions