forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 1
/
redirector.go
72 lines (64 loc) · 3.29 KB
/
redirector.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package redirector
import (
"net/http"
"net/url"
"strings"
"github.com/openshift/origin/pkg/oauthserver/authenticator/tokens"
oauthhandlers "github.com/openshift/origin/pkg/oauthserver/oauth/handlers"
)
// NewRedirector returns an oauthhandlers.AuthenticationRedirector that redirects to the specified redirectURL.
// Request URLs missing scheme/host, or with relative paths are resolved relative to the baseRequestURL, if specified.
// The following tokens are replaceable in the query of the redirectURL:
// ${url} is replaced with the current request URL, escaped as a query parameter. Example: https://www.example.com/login?then=${url}
// ${query} is replaced with the current request query, unescaped. Example: https://www.example.com/sso/oauth/authorize?${query}
func NewRedirector(baseRequestURL *url.URL, redirectURL string) oauthhandlers.AuthenticationRedirector {
return &redirector{BaseRequestURL: baseRequestURL, RedirectURL: redirectURL}
}
// NewChallenger returns an oauthhandlers.AuthenticationChallenger that returns a Location header to the specified redirectURL.
// Request URLs missing scheme/host, or with relative paths are resolved relative to the baseRequestURL, if specified.
// The following tokens are replaceable in the query of the redirectURL:
// ${url} is replaced with the current request URL, escaped as a query parameter. Example: https://www.example.com/login?then=${url}
// ${query} is replaced with the current request query, unescaped. Example: https://www.example.com/sso/oauth/authorize?${query}
func NewChallenger(baseRequestURL *url.URL, redirectURL string) oauthhandlers.AuthenticationChallenger {
return &redirector{BaseRequestURL: baseRequestURL, RedirectURL: redirectURL}
}
type redirector struct {
BaseRequestURL *url.URL
RedirectURL string
}
// AuthenticationChallenge returns a Location header to the configured RedirectURL (which should return a challenge)
func (r *redirector) AuthenticationChallenge(req *http.Request) (http.Header, error) {
redirectURL, err := buildRedirectURL(r.RedirectURL, r.BaseRequestURL, req.URL)
if err != nil {
return nil, err
}
headers := http.Header{}
headers.Add("Location", redirectURL.String())
return headers, nil
}
// AuthenticationRedirect redirects to the configured RedirectURL
func (r *redirector) AuthenticationRedirect(w http.ResponseWriter, req *http.Request) error {
redirectURL, err := buildRedirectURL(r.RedirectURL, r.BaseRequestURL, req.URL)
if err != nil {
return nil
}
http.Redirect(w, req, redirectURL.String(), http.StatusFound)
return nil
}
func buildRedirectURL(redirectTemplate string, baseRequestURL, requestURL *url.URL) (*url.URL, error) {
if baseRequestURL != nil {
requestURL = baseRequestURL.ResolveReference(requestURL)
}
redirectURL, err := url.Parse(redirectTemplate)
if err != nil {
return nil, err
}
serverRelativeRequestURL := &url.URL{
Path: requestURL.Path,
RawQuery: requestURL.RawQuery,
}
redirectURL.RawQuery = strings.Replace(redirectURL.RawQuery, tokens.QueryToken, requestURL.RawQuery, -1)
redirectURL.RawQuery = strings.Replace(redirectURL.RawQuery, tokens.URLToken, url.QueryEscape(requestURL.String()), -1)
redirectURL.RawQuery = strings.Replace(redirectURL.RawQuery, tokens.ServerRelativeURLToken, url.QueryEscape(serverRelativeRequestURL.String()), -1)
return redirectURL, nil
}