---
id: w4/m9/t002
title: Dashboard/auth passes login_challenge through; first-party login byte-identical
worker: worker4
status: done
estimate: 45m
depends_on: [w4/m9/t001]
---

## Objective

Make the existing dashboard login (and sign-up) pages forward Hydra's
`login_challenge` into the Kratos flow they create — the one change the native
integration needs from the UI. Everything else about first-party login stays
byte-identical (Kratos session cookie; no tokens in the browser).

## Context

- Routes: `dashboard/src/routes/auth.login.tsx`, `auth.sign-up.tsx`
  (`validateSearch` currently passes `next`/`flow`); flow creation:
  `dashboard/src/common/hooks/use-ory-flow.ts`.
- When a Kratos login/registration flow is created with `login_challenge`,
  Kratos links it to Hydra's request and accepts it on success (t001); an
  OAuth-initiated visit with an existing session is accepted without UI.
- A stale/absent challenge must degrade to the normal login page — the
  challenge is advisory, never load-bearing for first-party use.

## Steps

1. Accept `login_challenge` in `validateSearch` on the login + sign-up routes.
2. Thread it into flow creation in `use-ory-flow` (`createBrowserLoginFlow`/`createBrowserRegistrationFlow` params).
3. Verify the no-challenge path renders exactly today's pages (no behavior change without the param).

## Files

- `dashboard/src/routes/auth.login.tsx`, `dashboard/src/routes/auth.sign-up.tsx`
- `dashboard/src/common/hooks/use-ory-flow.ts`

## Acceptance criteria

- [x] A visit with `?login_challenge=` creates a Kratos flow linked to the Hydra request.
- [x] Without the param, login/sign-up behavior and markup are unchanged (existing tests still pass).
- [x] No OAuth tokens are stored browser-side (guardrail).

## Out of scope

- Consent (t003); any styling/UX changes to the auth pages.
