zitadel/internal/api/ui/login/auth_request.go
Livio Spring d058a2bc8a
fix(login): ensure auth request (#8004)
# Which Problems Are Solved

Potential nil pointers leading to a panic in the login UI.

# How the Problems Are Solved

As of now the login UI did not always check if the authRequest was
actually retrieved form the database, which is ok for some endpoints
which can also be called outside of an auth request.
There are now methods added to ensure the request is loaded.

# Additional Changes

None

# Additional Context

Closes https://github.com/zitadel/DevOps/issues/55
2024-05-24 14:58:45 +00:00

76 lines
2.4 KiB
Go

package login
import (
"net/http"
"github.com/zitadel/logging"
http_mw "github.com/zitadel/zitadel/internal/api/http/middleware"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/zerrors"
)
const (
QueryAuthRequestID = "authRequestID"
queryUserAgentID = "userAgentID"
)
func (l *Login) getAuthRequest(r *http.Request) (*domain.AuthRequest, error) {
authRequestID := r.FormValue(QueryAuthRequestID)
if authRequestID == "" {
return nil, nil
}
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
return l.authRepo.AuthRequestByID(r.Context(), authRequestID, userAgentID)
}
func (l *Login) ensureAuthRequest(r *http.Request) (*domain.AuthRequest, error) {
authRequest, err := l.getAuthRequest(r)
if authRequest != nil || err != nil {
return authRequest, err
}
return nil, zerrors.ThrowInvalidArgument(nil, "LOGIN-OLah9", "invalid or missing auth request")
}
func (l *Login) getAuthRequestAndParseData(r *http.Request, data interface{}) (*domain.AuthRequest, error) {
authReq, err := l.getAuthRequest(r)
if err != nil {
return authReq, err
}
err = l.parser.Parse(r, data)
return authReq, err
}
func (l *Login) ensureAuthRequestAndParseData(r *http.Request, data interface{}) (*domain.AuthRequest, error) {
authReq, err := l.ensureAuthRequest(r)
if err != nil {
return authReq, err
}
err = l.parser.Parse(r, data)
return authReq, err
}
func (l *Login) getParseData(r *http.Request, data interface{}) error {
return l.parser.Parse(r, data)
}
// checkOptionalAuthRequestOfEmailLinks tries to get the [domain.AuthRequest] from the request.
// In case any error occurs, e.g. if the user agent does not correspond, the `authRequestID` query parameter will be
// removed from the request URL and form to ensure subsequent functions and pages do not use it.
// This function is used for handling links in emails, which could possibly be opened on another device than the
// auth request was initiated.
func (l *Login) checkOptionalAuthRequestOfEmailLinks(r *http.Request) *domain.AuthRequest {
authReq, err := l.getAuthRequest(r)
if err == nil {
return authReq
}
logging.WithError(err).Infof("authrequest could not be found for email link on path %s", r.URL.RequestURI())
queries := r.URL.Query()
queries.Del(QueryAuthRequestID)
r.URL.RawQuery = queries.Encode()
r.RequestURI = r.URL.RequestURI()
r.Form.Del(QueryAuthRequestID)
r.PostForm.Del(QueryAuthRequestID)
return nil
}