@@ -189,8 +189,10 @@ Client RESTHeart Frontend login UI
189189 |-- GET /authorize ------>| |
190190 | (code_challenge, S256)| |
191191 |<-- 302 to login-url ----| |
192- | |<-- user authenticates --|
193- | |-- 302 callback?code=... ->|
192+ | |<-- POST /authorize -----|
193+ | | username+password |
194+ | |--(valid)- 302 callback?code=... ->|
195+ | |--(invalid)- 302 login?error=... ->|
194196 |<----------------------------------------------- code ---|
195197 |-- POST /token ---------->|
196198 | (code, code_verifier) |
@@ -221,8 +223,30 @@ RESTHeart responds with `302` to the configured `login-url`, forwarding all OAut
221223
222224==== Step 2: User authenticates
223225
224- The frontend presents the login form.
225- On success it POSTs to `POST /authorize` with HTTP Basic Auth:
226+ The frontend presents the login form and POSTs the credentials to `POST /authorize`.
227+ The OAuth parameters are forwarded as query string (exactly as received from the `GET /authorize` redirect).
228+
229+ Two credential formats are supported:
230+
231+ **Option A — form body** (recommended for browser login pages):
232+
233+ RESTHeart reads `username` and `password` from the `application/x-www-form-urlencoded` body.
234+ No `Authorization` header is needed — the browser's native form `POST` works as-is.
235+
236+ [source,bash]
237+ ----
238+ http --follow=false POST \
239+ "[RESTHEART-URL]/authorize?response_type=code&client_id=my-app&\
240+ redirect_uri=https://myapp.example.com/callback&\
241+ code_challenge=${CODE_CHALLENGE}&code_challenge_method=S256&state=random-state-value" \
242+ username=admin \
243+ password=secret
244+ ----
245+
246+ On invalid credentials RESTHeart redirects back to `login-url?error=invalid_credentials&<original_query_params>`
247+ so the login page can show an error without losing the OAuth context.
248+
249+ **Option B — HTTP Basic Auth** (for API clients / programmatic use):
226250
227251[source,bash]
228252----
@@ -232,7 +256,9 @@ redirect_uri=https://myapp.example.com/callback&\
232256code_challenge=${CODE_CHALLENGE}&code_challenge_method=S256&state=random-state-value"
233257----
234258
235- RESTHeart responds with `302` to `redirect_uri?code=<authorization_code>&state=random-state-value`.
259+ NOTE: If an `Authorization: Basic` header is present it always takes precedence over form body credentials.
260+
261+ **Response (valid credentials):** `302` to `redirect_uri?code=<authorization_code>&state=<state>`.
236262
237263The authorization code is a short-lived JWT (5-minute TTL) signed with the shared `jwtConfigProvider` key.
238264It is stateless — valid across all nodes in a cluster without shared storage.
0 commit comments