mirror of
https://github.com/nais/wonderwall.git
synced 2026-05-09 09:56:48 +00:00
95 lines
2.1 KiB
Go
95 lines
2.1 KiB
Go
package url
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"path"
|
|
|
|
mw "github.com/nais/wonderwall/pkg/middleware"
|
|
"github.com/nais/wonderwall/pkg/router/paths"
|
|
)
|
|
|
|
const (
|
|
RedirectURLParameter = "redirect"
|
|
)
|
|
|
|
// CanonicalRedirect constructs a redirect URL that points back to the application.
|
|
func CanonicalRedirect(r *http.Request) string {
|
|
ingressPath, ok := mw.PathFrom(r.Context())
|
|
if len(ingressPath) == 0 || !ok {
|
|
ingressPath = "/"
|
|
}
|
|
|
|
// 1. Default
|
|
redirect := ingressPath
|
|
|
|
// 2. Referer header is set
|
|
referer := r.Referer()
|
|
if len(referer) > 0 {
|
|
redirect = referer
|
|
}
|
|
|
|
// 3. Redirect parameter is set
|
|
redirectParam := r.URL.Query().Get(RedirectURLParameter)
|
|
if len(redirectParam) > 0 {
|
|
redirect = redirectParam
|
|
}
|
|
|
|
parsed, err := url.Parse(redirect)
|
|
if err != nil {
|
|
// Silently fall back to ingress path
|
|
redirect = ingressPath
|
|
}
|
|
|
|
// Strip scheme and host to avoid cross-domain redirects
|
|
parsed.Scheme = ""
|
|
parsed.Host = ""
|
|
|
|
redirect = parsed.String()
|
|
|
|
// Root path without trailing slash is empty
|
|
if len(parsed.Path) == 0 {
|
|
redirect = "/"
|
|
}
|
|
|
|
// Ensure that empty path redirections falls back to the ingress' context path if applicable
|
|
if len(redirect) == 0 {
|
|
redirect = ingressPath
|
|
}
|
|
|
|
return redirect
|
|
}
|
|
|
|
func LoginURL(prefix, redirectTarget string) string {
|
|
loginPath := prefix + paths.OAuth2 + paths.Login
|
|
redirectParam := fmt.Sprintf("?%s=%s", RedirectURLParameter, redirectTarget)
|
|
|
|
return loginPath + redirectParam
|
|
}
|
|
|
|
func LoginCallbackURL(r *http.Request) (string, error) {
|
|
return makeCallbackURL(r, paths.LoginCallback)
|
|
}
|
|
|
|
func LogoutCallbackURL(r *http.Request) (string, error) {
|
|
return makeCallbackURL(r, paths.LogoutCallback)
|
|
}
|
|
|
|
func makeCallbackURL(r *http.Request, callbackPath string) (string, error) {
|
|
match, found := mw.IngressFrom(r.Context())
|
|
if !found {
|
|
return "", fmt.Errorf("request host does not match any configured ingresses")
|
|
}
|
|
|
|
targetPath := path.Join(match.Path(), paths.OAuth2, callbackPath)
|
|
|
|
targetUrl := url.URL{
|
|
Host: match.Host(),
|
|
Path: targetPath,
|
|
Scheme: match.Scheme,
|
|
}
|
|
|
|
return targetUrl.String(), nil
|
|
}
|