swagger:route GET /oauth2/device/verify oAuth2 performOAuth2DeviceVerificationFlow # OAuth 2.0 Device Verification Endpoint This is the device user verification endpoint. The user is redirected here when trying to log in using the device flow. Consumes: - application/x-www-form-urlencoded Sch
(w http.ResponseWriter, r *http.Request)
| 744 | // Extensions: |
| 745 | // x-ory-ratelimit-bucket: hydra-admin-low |
| 746 | func (h *Handler) performOAuth2DeviceVerificationFlow(w http.ResponseWriter, r *http.Request) { |
| 747 | var ( |
| 748 | ctx = r.Context() |
| 749 | err error |
| 750 | ) |
| 751 | |
| 752 | ctx, span := h.r.Tracer(ctx).Tracer().Start(ctx, "oauth2.handler.performOAuth2DeviceVerificationFlow") |
| 753 | defer otelx.End(span, &err) |
| 754 | |
| 755 | // When this endpoint is called with a valid consent_verifier (meaning that the login flow completed successfully) |
| 756 | // there are 3 writes happening to the database: |
| 757 | // - The flow is created |
| 758 | // - The device auth session is updated (user_code is marked as accepted) |
| 759 | // - The OpenID session is created |
| 760 | // If there were multiple flows created for the same user_code then we may end up with multiple flow objects |
| 761 | // persisted to the database, while only one of them was actually used to validate the user_code |
| 762 | // (see https://github.com/ory/hydra/pull/3851#discussion_r1843678761) |
| 763 | f, err := h.r.ConsentStrategy().HandleOAuth2DeviceAuthorizationRequest(ctx, w, r) |
| 764 | if errors.Is(err, consent.ErrAbortOAuth2Request) { |
| 765 | x.LogError(r, err, h.r.Logger()) |
| 766 | return |
| 767 | } else if e := &(fosite.RFC6749Error{}); errors.As(err, &e) { |
| 768 | x.LogError(r, err, h.r.Logger()) |
| 769 | h.r.Writer().WriteError(w, r, err) |
| 770 | return |
| 771 | } else if err != nil { |
| 772 | x.LogError(r, err, h.r.Logger()) |
| 773 | h.r.Writer().WriteError(w, r, err) |
| 774 | return |
| 775 | } |
| 776 | |
| 777 | req, sig, err := h.r.OAuth2Storage().GetDeviceCodeSessionByRequestID(ctx, f.DeviceCodeRequestID.String(), &Session{}) |
| 778 | if err != nil { |
| 779 | x.LogError(r, err, h.r.Logger()) |
| 780 | h.r.Writer().WriteError(w, r, err) |
| 781 | return |
| 782 | } |
| 783 | |
| 784 | req.SetUserCodeState(fosite.UserCodeAccepted) |
| 785 | session, err := h.updateSessionWithRequest(ctx, f, r, req, req.GetSession().(*Session)) |
| 786 | if err != nil { |
| 787 | x.LogError(r, err, h.r.Logger()) |
| 788 | h.r.Writer().WriteError(w, r, err) |
| 789 | return |
| 790 | } |
| 791 | |
| 792 | req.SetSession(session) |
| 793 | if err := h.r.Transaction(ctx, func(ctx context.Context) error { |
| 794 | // Update the device code session with |
| 795 | // - the claims for which the user gave consent |
| 796 | // - the granted scopes |
| 797 | // - the granted audiences |
| 798 | // - the user_code_state set to `accepted` |
| 799 | // This marks it as ready to be used for the token exchange endpoint. |
| 800 | if err = h.r.OAuth2Storage().UpdateDeviceCodeSessionBySignature(ctx, sig, req); err != nil { |
| 801 | return err |
| 802 | } |
| 803 |
nothing calls this directly
no test coverage detected