swagger:route PUT /admin/oauth2/auth/requests/login/accept oAuth2 acceptOAuth2LoginRequest # Accept OAuth 2.0 Login Request When an authorization code, hybrid, or implicit OAuth 2.0 Flow is initiated, Ory asks the login provider to authenticate the subject and then tell the Ory OAuth2 Service abou
(w http.ResponseWriter, r *http.Request)
| 428 | // Extensions: |
| 429 | // x-ory-ratelimit-bucket: hydra-admin-low |
| 430 | func (h *Handler) acceptOAuth2LoginRequest(w http.ResponseWriter, r *http.Request) { |
| 431 | var err error |
| 432 | ctx, span := h.r.Tracer(r.Context()).Tracer().Start(r.Context(), "consent.acceptOAuth2LoginRequest") |
| 433 | defer otelx.End(span, &err) |
| 434 | |
| 435 | challenge := cmp.Or( |
| 436 | r.URL.Query().Get("login_challenge"), |
| 437 | r.URL.Query().Get("challenge"), |
| 438 | ) |
| 439 | if challenge == "" { |
| 440 | h.r.Writer().WriteError(w, r, errors.WithStack(fosite.ErrInvalidRequest.WithHint(`Query parameter 'challenge' is not defined but should have been.`))) |
| 441 | return |
| 442 | } |
| 443 | |
| 444 | var payload flow.HandledLoginRequest |
| 445 | if err := json.NewDecoder(r.Body).Decode(&payload); err != nil { |
| 446 | h.r.Writer().WriteError(w, r, errors.WithStack(fosite.ErrInvalidRequest.WithWrap(err).WithHintf("Unable to decode body because: %s", err))) |
| 447 | return |
| 448 | } |
| 449 | |
| 450 | if payload.Subject == "" { |
| 451 | h.r.Writer().WriteError(w, r, errors.WithStack(fosite.ErrInvalidRequest.WithHint("Field 'subject' must not be empty."))) |
| 452 | return |
| 453 | } |
| 454 | |
| 455 | f, err := flow.DecodeFromLoginChallenge(ctx, h.r, challenge) |
| 456 | if err != nil { |
| 457 | h.r.Writer().WriteError(w, r, err) |
| 458 | return |
| 459 | } else if f.Subject != "" && payload.Subject != f.Subject { |
| 460 | // The subject that was confirmed by the login screen does not match what we |
| 461 | // remembered in the session cookie. We handle this gracefully by redirecting the |
| 462 | // original authorization request URL, but attaching "prompt=login" to the query. |
| 463 | // This forces the user to log in again. |
| 464 | requestURL, err := url.Parse(f.RequestURL) |
| 465 | if err != nil { |
| 466 | h.r.Writer().WriteError(w, r, err) |
| 467 | return |
| 468 | } |
| 469 | h.r.Writer().Write(w, r, &flow.OAuth2RedirectTo{ |
| 470 | RedirectTo: urlx.SetQuery(requestURL, url.Values{"prompt": {"login"}}).String(), |
| 471 | }) |
| 472 | return |
| 473 | } |
| 474 | |
| 475 | if f.LoginSkip { |
| 476 | payload.Remember = true // If skip is true remember is also true to allow consecutive calls as the same user! |
| 477 | } else { |
| 478 | f.LoginAuthenticatedAt = sqlxx.NullTime(time.Now().UTC(). |
| 479 | // Rounding is important to avoid SQL time synchronization issues in e.g. MySQL! |
| 480 | Truncate(time.Second)) |
| 481 | } |
| 482 | |
| 483 | if err := f.HandleLoginRequest(&payload); err != nil { |
| 484 | h.r.Writer().WriteError(w, r, errors.WithStack(err)) |
| 485 | return |
| 486 | } |
| 487 |
nothing calls this directly
no test coverage detected