Problem
When a user submits the IdP's sign-in form with invalid credentials, handleLogin in src/idp/interactions.js correctly:
- Sets
interaction.lastError = 'Invalid username or password' (line 121)
- Saves the interaction
- 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
Problem
When a user submits the IdP's sign-in form with invalid credentials,
handleLogininsrc/idp/interactions.jscorrectly:interaction.lastError = 'Invalid username or password'(line 121)/idp/interaction/<uid>The GET handler then re-renders
loginPage(uid, params.client_id, interaction.lastError)— passinglastErroras 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
Where the rendering gap lives
loginPage()insrc/idp/views.jsacceptslastError(third positional arg perinteractions.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
lastErrorinsrc/idp/views.js. If absent or referenced but not in the output HTML, that's the gap.Repro
Visit any path that triggers the IdP, e.g.
http://localhost:5446/idp/auth?..., then submitUsername: 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'sloginPage(), renderlastErrornear the top of the form if truthy:Style with red text on a faint pink background, accessible via
role="alert"so screen readers announce it.Related
lastErrorparameter