mirror of
https://github.com/wahyd4/loginsrv.git
synced 2026-08-09 04:46:29 +10:00
preliminary implemntation of redirect logic
This commit is contained in:
+42
-32
@@ -23,20 +23,23 @@ func init() {
|
||||
// DefaultConfig for the loginsrv handler
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
Host: "localhost",
|
||||
Port: "6789",
|
||||
LogLevel: "info",
|
||||
JwtSecret: jwtDefaultSecret,
|
||||
JwtExpiry: 24 * time.Hour,
|
||||
JwtRefreshes: 0,
|
||||
SuccessURL: "/",
|
||||
LogoutURL: "",
|
||||
LoginPath: "/login",
|
||||
CookieName: "jwt_token",
|
||||
CookieHTTPOnly: true,
|
||||
Backends: Options{},
|
||||
Oauth: Options{},
|
||||
GracePeriod: 5 * time.Second,
|
||||
Host: "localhost",
|
||||
Port: "6789",
|
||||
LogLevel: "info",
|
||||
JwtSecret: jwtDefaultSecret,
|
||||
JwtExpiry: 24 * time.Hour,
|
||||
JwtRefreshes: 0,
|
||||
SuccessURL: "/",
|
||||
AllowRedirects: true,
|
||||
PreventExternalRedirects: true,
|
||||
CheckRefererOnRedirects: true,
|
||||
LogoutURL: "",
|
||||
LoginPath: "/login",
|
||||
CookieName: "jwt_token",
|
||||
CookieHTTPOnly: true,
|
||||
Backends: Options{},
|
||||
Oauth: Options{},
|
||||
GracePeriod: 5 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,24 +47,27 @@ const envPrefix = "LOGINSRV_"
|
||||
|
||||
// Config for the loginsrv handler
|
||||
type Config struct {
|
||||
Host string
|
||||
Port string
|
||||
LogLevel string
|
||||
TextLogging bool
|
||||
JwtSecret string
|
||||
JwtExpiry time.Duration
|
||||
JwtRefreshes int
|
||||
SuccessURL string
|
||||
LogoutURL string
|
||||
Template string
|
||||
LoginPath string
|
||||
CookieName string
|
||||
CookieExpiry time.Duration
|
||||
CookieDomain string
|
||||
CookieHTTPOnly bool
|
||||
Backends Options
|
||||
Oauth Options
|
||||
GracePeriod time.Duration
|
||||
Host string
|
||||
Port string
|
||||
LogLevel string
|
||||
TextLogging bool
|
||||
JwtSecret string
|
||||
JwtExpiry time.Duration
|
||||
JwtRefreshes int
|
||||
SuccessURL string
|
||||
AllowRedirects bool
|
||||
PreventExternalRedirects bool
|
||||
CheckRefererOnRedirects bool
|
||||
LogoutURL string
|
||||
Template string
|
||||
LoginPath string
|
||||
CookieName string
|
||||
CookieExpiry time.Duration
|
||||
CookieDomain string
|
||||
CookieHTTPOnly bool
|
||||
Backends Options
|
||||
Oauth Options
|
||||
GracePeriod time.Duration
|
||||
}
|
||||
|
||||
// Options is the configuration structure for oauth and backend provider
|
||||
@@ -104,6 +110,10 @@ func (c *Config) ConfigureFlagSet(f *flag.FlagSet) {
|
||||
f.DurationVar(&c.CookieExpiry, "cookie-expiry", c.CookieExpiry, "The expiry duration for the cookie, e.g. 2h or 3h30m. Default is browser session")
|
||||
f.StringVar(&c.CookieDomain, "cookie-domain", c.CookieDomain, "The optional domain parameter for the cookie")
|
||||
f.StringVar(&c.SuccessURL, "success-url", c.SuccessURL, "The url to redirect after login")
|
||||
f.BoolVar(&c.AllowRedirects, "allow-redirects", c.AllowRedirects, "Allow dynamic redirects by parameter")
|
||||
f.BoolVar(&c.PreventExternalRedirects, "prevent-external-redirects", c.PreventExternalRedirects, "Prevent dynamic redirects from redirecting to an external domain")
|
||||
f.BoolVar(&c.CheckRefererOnRedirects, "check-referer-on-redirects", c.CheckRefererOnRedirects, "When redirecting check that the referer is the same domain")
|
||||
|
||||
f.StringVar(&c.LogoutURL, "logout-url", c.LogoutURL, "The url or path to redirect after logout")
|
||||
f.StringVar(&c.Template, "template", c.Template, "An alternative template for the login form")
|
||||
f.StringVar(&c.LoginPath, "login-path", c.LoginPath, "The path of the login resource")
|
||||
|
||||
+91
-5
@@ -4,14 +4,17 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/tarent/loginsrv/logging"
|
||||
"github.com/tarent/loginsrv/model"
|
||||
"github.com/tarent/loginsrv/oauth2"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const contentTypeHTML = "text/html; charset=utf-8"
|
||||
@@ -71,11 +74,34 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
h.handleOauth(w, r)
|
||||
return
|
||||
}
|
||||
if h.shouldSetCookie(r) {
|
||||
queries, _ := url.ParseQuery(r.URL.RawQuery)
|
||||
cookie := http.Cookie{Name: "redirect_url", Value: queries.Get("backTo")}
|
||||
http.SetCookie(w, &cookie)
|
||||
}
|
||||
|
||||
h.handleLogin(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
func (h *Handler) shouldSetCookie(r *http.Request) bool {
|
||||
if h.config.AllowRedirects {
|
||||
if h.config.CheckRefererOnRedirects {
|
||||
referer, _ := url.Parse(r.Header.Get("Referer"))
|
||||
if referer.Host != r.Host {
|
||||
logging.Application(r.Header).Warnf(
|
||||
"Referer domain: '%s' does not match current domain '%s'",
|
||||
referer.Host,
|
||||
r.Host,
|
||||
)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *Handler) handleOauth(w http.ResponseWriter, r *http.Request) {
|
||||
startedFlow, authenticated, userInfo, err := h.oauth.Handle(w, r)
|
||||
|
||||
@@ -231,7 +257,10 @@ func (h *Handler) respondAuthenticated(w http.ResponseWriter, r *http.Request, u
|
||||
|
||||
http.SetCookie(w, cookie)
|
||||
|
||||
w.Header().Set("Location", h.config.SuccessURL)
|
||||
//redirectURL := h.config.SuccessURL
|
||||
//fmt.Printf("redirectURL is: %s\n", h.redirectURL(r))
|
||||
|
||||
w.Header().Set("Location", h.redirectURL(r))
|
||||
w.WriteHeader(303)
|
||||
return
|
||||
}
|
||||
@@ -241,6 +270,63 @@ func (h *Handler) respondAuthenticated(w http.ResponseWriter, r *http.Request, u
|
||||
fmt.Fprintf(w, "%s", token)
|
||||
}
|
||||
|
||||
func (h *Handler) redirectURL(r *http.Request) string {
|
||||
origin, _ := url.Parse(r.Header.Get("Origin"))
|
||||
originScheme := origin.Scheme
|
||||
originHost := origin.Host
|
||||
redirectURL := fmt.Sprintf("%s://%s%s", originScheme, originHost, h.config.SuccessURL)
|
||||
if h.config.AllowRedirects {
|
||||
cookie, _ := r.Cookie("redirect_url")
|
||||
parsedURL, err := url.Parse(cookie.Value)
|
||||
if err != nil {
|
||||
spew.Dump("oops can't parse that url")
|
||||
}
|
||||
scheme := parsedURL.Scheme
|
||||
host := parsedURL.Host
|
||||
path := parsedURL.Path
|
||||
//spew.Dump(scheme)
|
||||
//spew.Dump(host)
|
||||
//spew.Dump(path)
|
||||
|
||||
if scheme == "" {
|
||||
scheme = originScheme
|
||||
}
|
||||
|
||||
if host == "" {
|
||||
host = originHost
|
||||
} else {
|
||||
if h.config.PreventExternalRedirects {
|
||||
if host != originHost {
|
||||
logging.Application(r.Header).Warnf(
|
||||
"Redirect attempt to '%s' but -prevent-external-redirects is set to true",
|
||||
host,
|
||||
)
|
||||
return redirectURL
|
||||
} else {
|
||||
host = originHost
|
||||
}
|
||||
} else {
|
||||
//TODO read domains from file
|
||||
domains := "2google.com"
|
||||
if host != domains {
|
||||
logging.Application(r.Header).Warnf(
|
||||
"Redirect attempt to '%s' but it is not in domain whitelist",
|
||||
host,
|
||||
)
|
||||
return redirectURL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if path == "" {
|
||||
path = h.config.SuccessURL
|
||||
}
|
||||
|
||||
redirectURL = fmt.Sprintf("%s://%s%s", scheme, host, path)
|
||||
}
|
||||
return redirectURL
|
||||
}
|
||||
|
||||
func (h *Handler) createToken(userInfo jwt.Claims) (string, error) {
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS512, userInfo)
|
||||
return token.SignedString([]byte(h.config.JwtSecret))
|
||||
|
||||
Reference in New Issue
Block a user