Problem
The IDP currently has no human-friendly entry point. Every URL assumes you're already in an OIDC flow:
- `/idp/auth` without `client_id` → `Authentication Error: invalid_request, missing required parameter 'client_id'`. Hard wall.
- `/idp/interaction/:uid` requires a UID provisioned by an in-flight OIDC interaction.
- `/idp/register` works standalone, but its "Already have an account? Sign In" link points at `/idp/auth` — i.e. straight back into the broken-without-client_id error.
So a fresh visitor to `https://jss.live/idp\` (or any of the above) has nothing to do except register. After registering, they get bounced to the same dead links.
Proposal
Three small surfaces, designed together:
1. `GET /idp` — friendly landing
Plain HTML card, two buttons: Sign In and Create Account. Same visual treatment as the new register page (gradient header, etc). No OIDC plumbing — just navigation.
2. `GET /idp/login` — standalone login
Username + password form, no `client_id` required. On submit: set the IDP session cookie (same mechanism the OIDC interaction flow already uses to remember an authenticated account) and redirect to a configurable `?next=` URL, defaulting to `/idp` (or to the user's pod root `/alice/`, TBD).
Plumbing-wise, this is most of `handleLogin` minus the interaction-finished step: authenticate via `accounts.authenticate`, write the session, redirect.
3. `/idp/auth` without `client_id` → friendly redirect
Current behaviour returns the OIDC error verbatim. Instead, detect the no-client-id case in the route wrapper and 302 to `/idp` (the new landing) with a `message=needs_client` query param so the landing page can optionally show context. Preserves the OIDC contract for clients sending a real auth request — only changes the human-fat-fingered case.
Connections to other open work
Non-goals
- Account management UI (change password, delete pod, view active sessions). Separate issue.
- A full pod browser. `/idp`'s buttons just navigate; the pod browser is mashlib's territory.
- Federated / WebID-OIDC sign-in. The standalone `/idp/login` is local-account first.
Scope estimate
Smallest viable cut: ~80 lines of view + ~40 lines of route handler + the `/idp/auth` redirect guard + tests. One PR, no OIDC-protocol changes (just additive routes that reuse existing session machinery).
Happy to PR.
Problem
The IDP currently has no human-friendly entry point. Every URL assumes you're already in an OIDC flow:
So a fresh visitor to `https://jss.live/idp\` (or any of the above) has nothing to do except register. After registering, they get bounced to the same dead links.
Proposal
Three small surfaces, designed together:
1. `GET /idp` — friendly landing
Plain HTML card, two buttons: Sign In and Create Account. Same visual treatment as the new register page (gradient header, etc). No OIDC plumbing — just navigation.
2. `GET /idp/login` — standalone login
Username + password form, no `client_id` required. On submit: set the IDP session cookie (same mechanism the OIDC interaction flow already uses to remember an authenticated account) and redirect to a configurable `?next=` URL, defaulting to `/idp` (or to the user's pod root `/alice/`, TBD).
Plumbing-wise, this is most of `handleLogin` minus the interaction-finished step: authenticate via `accounts.authenticate`, write the session, redirect.
3. `/idp/auth` without `client_id` → friendly redirect
Current behaviour returns the OIDC error verbatim. Instead, detect the no-client-id case in the route wrapper and 302 to `/idp` (the new landing) with a `message=needs_client` query param so the landing page can optionally show context. Preserves the OIDC contract for clients sending a real auth request — only changes the human-fat-fingered case.
Connections to other open work
Non-goals
Scope estimate
Smallest viable cut: ~80 lines of view + ~40 lines of route handler + the `/idp/auth` redirect guard + tests. One PR, no OIDC-protocol changes (just additive routes that reuse existing session machinery).
Happy to PR.