2020-03-07 11:06:57 +00:00
|
|
|
package auth
|
|
|
|
|
|
|
|
import (
|
2020-03-17 20:04:16 +00:00
|
|
|
"fmt"
|
2020-03-07 11:06:57 +00:00
|
|
|
"net/http"
|
2020-03-17 20:04:16 +00:00
|
|
|
"net/url"
|
2020-03-07 11:06:57 +00:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/micro/go-micro/v2/auth"
|
|
|
|
)
|
|
|
|
|
2020-03-17 16:03:49 +00:00
|
|
|
var (
|
|
|
|
// DefaultExcludes is the paths which are allowed by default
|
|
|
|
DefaultExcludes = []string{"/favicon.ico"}
|
|
|
|
)
|
|
|
|
|
2020-03-07 11:06:57 +00:00
|
|
|
// CombinedAuthHandler wraps a server and authenticates requests
|
|
|
|
func CombinedAuthHandler(h http.Handler) http.Handler {
|
|
|
|
return authHandler{
|
|
|
|
handler: h,
|
|
|
|
auth: auth.DefaultAuth,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type authHandler struct {
|
|
|
|
handler http.Handler
|
|
|
|
auth auth.Auth
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
// BearerScheme is the prefix in the auth header
|
|
|
|
BearerScheme = "Bearer "
|
|
|
|
)
|
|
|
|
|
|
|
|
func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
2020-03-17 19:24:10 +00:00
|
|
|
// Extract the token from the request
|
|
|
|
var token string
|
|
|
|
if header := req.Header.Get("Authorization"); len(header) > 0 {
|
|
|
|
// Extract the auth token from the request
|
|
|
|
if strings.HasPrefix(header, BearerScheme) {
|
|
|
|
token = header[len(BearerScheme):]
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Get the token out the cookies if not provided in headers
|
|
|
|
if c, err := req.Cookie("micro-token"); err == nil && c != nil {
|
|
|
|
token = strings.TrimPrefix(c.Value, auth.CookieName+"=")
|
|
|
|
req.Header.Set("Authorization", BearerScheme+token)
|
|
|
|
}
|
|
|
|
}
|
2020-03-07 11:06:57 +00:00
|
|
|
|
|
|
|
// Return if the user disabled auth on this endpoint
|
|
|
|
excludes := h.auth.Options().Exclude
|
2020-03-17 16:03:49 +00:00
|
|
|
excludes = append(excludes, DefaultExcludes...)
|
2020-03-17 19:24:10 +00:00
|
|
|
|
|
|
|
loginURL := h.auth.Options().LoginURL
|
2020-03-07 11:06:57 +00:00
|
|
|
if len(loginURL) > 0 {
|
|
|
|
excludes = append(excludes, loginURL)
|
|
|
|
}
|
2020-03-17 16:03:49 +00:00
|
|
|
|
2020-03-07 11:06:57 +00:00
|
|
|
for _, e := range excludes {
|
2020-03-17 16:03:49 +00:00
|
|
|
// is a standard exclude, e.g. /rpc
|
2020-03-07 11:06:57 +00:00
|
|
|
if e == req.URL.Path {
|
|
|
|
h.handler.ServeHTTP(w, req)
|
|
|
|
return
|
|
|
|
}
|
2020-03-17 16:03:49 +00:00
|
|
|
|
|
|
|
// is a wildcard exclude, e.g. /services/*
|
|
|
|
wildcard := strings.Replace(e, "*", "", 1)
|
|
|
|
if strings.HasSuffix(e, "*") && strings.HasPrefix(req.URL.Path, wildcard) {
|
|
|
|
h.handler.ServeHTTP(w, req)
|
|
|
|
return
|
|
|
|
}
|
2020-03-07 11:06:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If the token is valid, allow the request
|
|
|
|
if _, err := h.auth.Verify(token); err == nil {
|
|
|
|
h.handler.ServeHTTP(w, req)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there is no auth login url set, 401
|
|
|
|
if loginURL == "" {
|
|
|
|
w.WriteHeader(401)
|
2020-03-16 10:30:56 +00:00
|
|
|
return
|
2020-03-07 11:06:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Redirect to the login path
|
2020-03-17 20:04:16 +00:00
|
|
|
params := url.Values{"redirect_to": {req.URL.Path}}
|
|
|
|
loginWithRedirect := fmt.Sprintf("%v?%v", loginURL, params.Encode())
|
|
|
|
http.Redirect(w, req, loginWithRedirect, http.StatusTemporaryRedirect)
|
2020-03-07 11:06:57 +00:00
|
|
|
}
|