diff --git a/pkg/lib/oauth/handler/handler_authz.go b/pkg/lib/oauth/handler/handler_authz.go index 9885694929d..0564b8eeeac 100644 --- a/pkg/lib/oauth/handler/handler_authz.go +++ b/pkg/lib/oauth/handler/handler_authz.go @@ -188,7 +188,8 @@ func (h *AuthorizationHandler) HandleConsentWithUserCancel(req *http.Request) ht RedirectURI: nil, } if errors.As(err, &oauthError) { - resultErr.Response = oauthError.Response + resultErr := h.prepareErrInvalidOAuthResponse(req, *oauthError) + return resultErr } else { h.Logger.WithError(err).Error("authz handler failed") resultErr.Response = protocol.NewErrorResponse("server_error", "internal server error") @@ -241,7 +242,8 @@ func (h *AuthorizationHandler) doHandleConsent(req *http.Request, withUserConsen RedirectURI: nil, } if errors.As(err, &oauthError) { - resultErr.Response = oauthError.Response + resultErr := h.prepareErrInvalidOAuthResponse(req, *oauthError) + return resultErr, nil } else { h.Logger.WithError(err).Error("authz handler failed") resultErr.Response = protocol.NewErrorResponse("server_error", "internal server error") @@ -668,3 +670,35 @@ func (h *AuthorizationHandler) generateSettingsActionResponse( resp.Code(code) return nil } + +func (h *AuthorizationHandler) prepareErrInvalidOAuthResponse(req *http.Request, oauthError protocol.OAuthProtocolError) httputil.Result { + resultErr := authorizationResultError{ + Response: oauthError.Response, + RedirectURI: nil, + } + + // Only redirect if oauth session is expired / not found + // It mostly happens when user refresh the page or go back to the page after authenication + if oauthError.Type() != "invalid_request" { + return resultErr + } + + redirectURI, err := url.Parse(req.URL.Query().Get("redirect_uri")) + if err != nil { + return resultErr + } + + client := h.ClientResolver.ResolveClient(req.URL.Query().Get("client_id")) + if client == nil { + return resultErr + } + + err = validateRedirectURI(client, h.HTTPProto, h.HTTPOrigin, h.AppDomains, redirectURI) + if err != nil { + return resultErr + } + + resultErr.RedirectURI = redirectURI + + return resultErr +} diff --git a/pkg/lib/oauth/oidc/ui.go b/pkg/lib/oauth/oidc/ui.go index 2314c7aaac7..735662ba3ca 100644 --- a/pkg/lib/oauth/oidc/ui.go +++ b/pkg/lib/oauth/oidc/ui.go @@ -101,21 +101,27 @@ type UIInfoResolver struct { } func (r *UIInfoResolver) SetAuthenticationInfoInQuery(redirectURI string, e *authenticationinfo.Entry) string { - consentURI := r.EndpointsProvider.ConsentEndpointURL().String() + consentURL := r.EndpointsProvider.ConsentEndpointURL() + + url, err := url.Parse(redirectURI) + if err != nil { + panic(err) + } + // Not redirecting to the consent endpoint. // Do not set anything. - if redirectURI != consentURI { + if SameEndpoint(url, consentURL) { return redirectURI } - u, err := url.Parse(redirectURI) - if err != nil { - panic(err) - } - q := u.Query() + q := url.Query() q.Set("code", e.ID) - u.RawQuery = q.Encode() - return u.String() + url.RawQuery = q.Encode() + return url.String() +} + +func SameEndpoint(urlA *url.URL, urlB *url.URL) bool { + return urlA.Scheme == urlB.Scheme && urlA.Host == urlB.Host && urlA.Path == urlB.Path } func (r *UIInfoResolver) GetAuthenticationInfoID(req *http.Request) (string, bool) { @@ -186,7 +192,13 @@ func (r *UIInfoResolver) ResolveForAuthorizationEndpoint( client *config.OAuthClientConfig, req protocol.AuthorizationRequest, ) (*UIInfo, *UIInfoByProduct, error) { - redirectURI := r.EndpointsProvider.ConsentEndpointURL().String() + redirectURI := r.EndpointsProvider.ConsentEndpointURL() + + // Add client_id and redirect_uri to URL as hint when oauth session expires / not found + q := redirectURI.Query() + q.Add("client_id", req.ClientID()) + q.Add("redirect_uri", req.RedirectURI()) + redirectURI.RawQuery = q.Encode() idToken, sidSession, err := r.IDTokenHintResolver.ResolveIDTokenHint(client, req) if err != nil { @@ -228,7 +240,7 @@ func (r *UIInfoResolver) ResolveForAuthorizationEndpoint( info := &UIInfo{ ClientID: req.ClientID(), - RedirectURI: redirectURI, + RedirectURI: redirectURI.String(), Prompt: prompt, UserIDHint: userIDHint, CanUseIntentReauthenticate: canUseIntentReauthenticate, diff --git a/pkg/lib/oauth/protocol/error.go b/pkg/lib/oauth/protocol/error.go index a20d8f6400f..728859c0190 100644 --- a/pkg/lib/oauth/protocol/error.go +++ b/pkg/lib/oauth/protocol/error.go @@ -62,3 +62,4 @@ func NewErrorWithErrorResponse(resp ErrorResponse) error { } func (e *OAuthProtocolError) Error() string { return e.Response["error_description"] } +func (e *OAuthProtocolError) Type() string { return e.Response["error"] }