Skip to content
This repository has been archived by the owner on May 17, 2024. It is now read-only.

Commit

Permalink
add trust_current_user to auth middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
ArthurHlt committed Feb 10, 2019
1 parent 5db7b8f commit 6e3e8cb
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 39 deletions.
7 changes: 7 additions & 0 deletions authpubtkt/auth_pubtkt.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ type AuthPubTktOptions struct {
// If true and TKTCheckIpEnabled is true it will check ip from header X-Forwarded-For instead client remote ip
// default: false
CheckXForwardedIp bool `mapstructure:"check_xforwarded_ip" json:"check_xforwarded_ip" yaml:"check_xforwarded_ip"`
// Passthrough if a previous middleware already set user context
// This is helpful when you want add user with basic auth middleware
TrustCurrentUser bool `mapstructure:"trust_current_user" json:"trust_current_user" yaml:"trust_current_user"`
}

type AuthPubTkt struct{}
Expand All @@ -91,6 +94,10 @@ func (AuthPubTkt) Handler(proxyRoute gobis.ProxyRoute, params interface{}, next
return next, nil
}
hijackHandler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if options.TrustCurrentUser && gobis.Username(req) != "" {
next.ServeHTTP(w, req)
return
}
ticket := pubtkt.TicketRequest(req)
if ticket == nil {
return
Expand Down
7 changes: 7 additions & 0 deletions basic2token/basic2token.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ type Basic2TokenOptions struct {
TokenType string `mapstructure:"token_type" json:"token_type" yaml:"token_type"`
// By default request token is sent by post form, set to true to send as json
ParamsAsJson bool `mapstructure:"params_as_json" json:"params_as_json" yaml:"params_as_json"`
// Passthrough if a previous middleware already set user context
// This is helpful when you want add user with basic auth middleware
TrustCurrentUser bool `mapstructure:"trust_current_user" json:"trust_current_user" yaml:"trust_current_user"`
}
type AccessTokenResponse struct {
AccessToken string `json:"access_token"`
Expand Down Expand Up @@ -152,6 +155,10 @@ func (h Basic2Token) Handler(proxyRoute gobis.ProxyRoute, params interface{}, ha
client := utils.CreateClient(options.ClientRouteOption, proxyRoute)
basic2TokenAuth := NewBasic2TokenAuth(client, *options)
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if options.TrustCurrentUser && gobis.Username(req) != "" {
handler.ServeHTTP(w, req)
return
}
// if token already passed, the handler go to next handler without try to do oauth
authHeader := strings.ToLower(req.Header.Get("Authorization"))
if strings.HasPrefix(authHeader, strings.ToLower(options.TokenType)) {
Expand Down
2 changes: 1 addition & 1 deletion default.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ func DefaultHandlers() []gobis.MiddlewareHandler {
return []gobis.MiddlewareHandler{
cors.NewCors(),
secure.NewSecure(),
ldap.NewLdap(),
basicauth.NewBasicAuth(),
ldap.NewLdap(),
basic2token.NewBasic2Token(),
oauth2.NewOauth2(),
authpubtkt.NewAuthPubTkt(),
Expand Down
46 changes: 27 additions & 19 deletions jwt/jwt.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,42 @@
package jwt

import (
"github.com/orange-cloudfoundry/gobis"
"net/http"
"crypto/subtle"
"fmt"
"github.com/auth0/go-jwt-middleware"
"github.com/dgrijalva/jwt-go"
"fmt"
"github.com/orange-cloudfoundry/gobis"
"github.com/orange-cloudfoundry/gobis-middlewares/utils"
log "github.com/sirupsen/logrus"
"net/http"
"regexp"
"strings"
"crypto/subtle"
log "github.com/sirupsen/logrus"
"github.com/orange-cloudfoundry/gobis-middlewares/utils"
)

type JwtConfig struct {
Jwt *JwtOptions `mapstructure:"jwt" json:"jwt" yaml:"jwt"`
}
type JwtOptions struct {
// enable jwt middleware
Enabled bool `mapstructure:"enabled" json:"enabled" yaml:"enabled"`
Enabled bool `mapstructure:"enabled" json:"enabled" yaml:"enabled"`
// Algorithm to use to validate the token
// This is mandatory due to a security issue (see: https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries)
Alg string `mapstructure:"alg" json:"alg" yaml:"alg"`
Alg string `mapstructure:"alg" json:"alg" yaml:"alg"`
// Secret or private key to verify the jwt
// This is required
Secret string `mapstructure:"secret" json:"secret" yaml:"secret"`
Secret string `mapstructure:"secret" json:"secret" yaml:"secret"`
// When set, all requests with the OPTIONS method will use authentication
// Default: false
EnableAuthOnOptions bool `mapstructure:"enable_auth_on_options" json:"enable_auth_on_options" yaml:"enable_auth_on_options"`
// If not empty, it will validate that the jwt contains this audience
Audience string `mapstructure:"audience" json:"audience" yaml:"audience"`
Audience string `mapstructure:"audience" json:"audience" yaml:"audience"`
// If not empty, it will validate that the jwt contains this issuer
Issuer string `mapstructure:"issuer" json:"issuer" yaml:"issuer"`
Issuer string `mapstructure:"issuer" json:"issuer" yaml:"issuer"`
// Add custom check to verify that the jwt contains those specified claims with specified value
CustomVerify map[string]string `mapstructure:"custom_verify" json:"custom_verify" yaml:"custom_verify"`
CustomVerify map[string]string `mapstructure:"custom_verify" json:"custom_verify" yaml:"custom_verify"`
// Passthrough if a previous middleware already set user context
// This is helpful when you want add user with basic auth middleware
TrustCurrentUser bool `mapstructure:"trust_current_user" json:"trust_current_user" yaml:"trust_current_user"`
}

type Jwt struct{}
Expand Down Expand Up @@ -73,23 +76,28 @@ func (Jwt) Handler(proxyRoute gobis.ProxyRoute, params interface{}, handler http
http.Error(w, msg, 403)
},
EnableAuthOnOptions: options.EnableAuthOnOptions,
Debug: log.GetLevel() == log.DebugLevel,
Debug: log.GetLevel() == log.DebugLevel,
})
return NewJwtHandler(jwtMiddleware, handler), nil
return NewJwtHandler(jwtMiddleware, handler, options.TrustCurrentUser), nil
}
func (Jwt) Schema() interface{} {
return JwtConfig{}
}

type JwtHandler struct {
jwtMiddleware *jwtmiddleware.JWTMiddleware
next http.Handler
jwtMiddleware *jwtmiddleware.JWTMiddleware
next http.Handler
trustCurrentUser bool
}

func NewJwtHandler(jwtMiddleware *jwtmiddleware.JWTMiddleware, next http.Handler) http.Handler {
return &JwtHandler{jwtMiddleware, next}
func NewJwtHandler(jwtMiddleware *jwtmiddleware.JWTMiddleware, next http.Handler, trustCurrentUser bool) http.Handler {
return &JwtHandler{jwtMiddleware, next, trustCurrentUser}
}
func (h JwtHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if h.trustCurrentUser && gobis.Username(req) != "" {
h.next.ServeHTTP(w, req)
return
}
err := h.jwtMiddleware.CheckJWT(w, req)
if err != nil {
return
Expand Down Expand Up @@ -181,4 +189,4 @@ func getSecretEncoded(secret string, signingMethod jwt.SigningMethod) (interface
return encSecret, nil
}
return jwt.ParseRSAPrivateKeyFromPEM(bSecret)
}
}
44 changes: 25 additions & 19 deletions ldap/ldap.go
Original file line number Diff line number Diff line change
@@ -1,50 +1,53 @@
package ldap

import (
"gopkg.in/ldap.v2"
"net/http"
"fmt"
"crypto/tls"
"github.com/orange-cloudfoundry/gobis"
"os"
"fmt"
"github.com/goji/httpauth"
"github.com/orange-cloudfoundry/gobis"
"github.com/orange-cloudfoundry/gobis-middlewares/utils"
"gopkg.in/ldap.v2"
"net/http"
"os"
)

const (
LDAP_BIND_DN_KEY = "LDAP_BIND_DN"
LDAP_BIND_DN_KEY = "LDAP_BIND_DN"
LDAP_BIND_PASSWORD_KEY = "LDAP_BIND_PASSWORD"
LDAP_BIND_ADDRESS = "LDAP_BIND_ADDRESS"
LDAP_BIND_ADDRESS = "LDAP_BIND_ADDRESS"
)

type LdapConfig struct {
Ldap *LdapOptions `mapstructure:"ldap" json:"ldap" yaml:"ldap"`
}
type LdapOptions struct {
// enable ldap basic auth middleware
Enabled bool `mapstructure:"enabled" json:"enabled" yaml:"enabled"`
Enabled bool `mapstructure:"enabled" json:"enabled" yaml:"enabled"`
// Search user bind dn (Can be set by env var `LDAP_BIND_DN`)
BindDn string `mapstructure:"bind_dn" json:"bind_dn" yaml:"bind_dn"`
BindDn string `mapstructure:"bind_dn" json:"bind_dn" yaml:"bind_dn"`
// Search user bind password (Can be set by env var `LDAP_BIND_PASSWORD`)
BindPassword string `mapstructure:"bind_password" json:"bind_password" yaml:"bind_password"`
BindPassword string `mapstructure:"bind_password" json:"bind_password" yaml:"bind_password"`
// Ldap server address in the form of host:port (Can be set by env var `LDAP_BIND_ADDRESS`)
Address string `mapstructure:"address" json:"address" yaml:"address"`
Address string `mapstructure:"address" json:"address" yaml:"address"`
// Set to true if ldap server supports TLS
UseSsl bool `mapstructure:"use_ssl" json:"use_ssl" yaml:"use_ssl"`
UseSsl bool `mapstructure:"use_ssl" json:"use_ssl" yaml:"use_ssl"`
// Set to true to skip certificate check (NOT RECOMMENDED)
InsecureSkipVerify bool `mapstructure:"insecure_skip_verify" json:"insecure_skip_verify" yaml:"insecure_skip_verify"`
// base dns to search through (Default: `dc=com`)
SearchBaseDns string `mapstructure:"search_base_dns" json:"search_base_dns" yaml:"search_base_dns"`
SearchBaseDns string `mapstructure:"search_base_dns" json:"search_base_dns" yaml:"search_base_dns"`
// User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)" (default: `(objectClass=organizationalPerson)&(uid=%s)`)
SearchFilter string `mapstructure:"search_filter" json:"search_filter" yaml:"search_filter"`
SearchFilter string `mapstructure:"search_filter" json:"search_filter" yaml:"search_filter"`
// Group search filter, to retrieve the groups of which the user is a member
// Groups will be passed in request context as a list of strings, how to retrieve: ctx.Groups(*http.Request)
// if GroupSearchFilter or GroupSearchBaseDns or MemberOf are empty it will not search for groups
GroupSearchFilter string `mapstructure:"group_search_filter" json:"group_search_filter" yaml:"group_search_filter"`
GroupSearchFilter string `mapstructure:"group_search_filter" json:"group_search_filter" yaml:"group_search_filter"`
// base DNs to search through for groups
GroupSearchBaseDns string `mapstructure:"group_search_base_dns" json:"group_search_base_dns" yaml:"group_search_base_dns"`
// Search group name by this value (default: `memberOf`)
MemberOf string `mapstructure:"member_of" json:"member_of" yaml:"member_of"`
MemberOf string `mapstructure:"member_of" json:"member_of" yaml:"member_of"`
// Passthrough if a previous middleware already set user context
// This is helpful when you want add user with basic auth middleware
TrustCurrentUser bool `mapstructure:"trust_current_user" json:"trust_current_user" yaml:"trust_current_user"`
}
type LdapAuth struct {
LdapOptions
Expand All @@ -69,6 +72,9 @@ func (l LdapAuth) CreateConn() (conn *ldap.Conn, err error) {
return
}
func (l LdapAuth) LdapAuth(user, password string, req *http.Request) bool {
if l.LdapOptions.TrustCurrentUser && gobis.Username(req) != "" {
return true
}
gobis.DirtHeader(req, "Authorization")
conn, err := l.CreateConn()
if err != nil {
Expand All @@ -79,7 +85,7 @@ func (l LdapAuth) LdapAuth(user, password string, req *http.Request) bool {
searchRequest := ldap.NewSearchRequest(
l.SearchBaseDns,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
fmt.Sprintf("(&" + l.SearchFilter + ")", user),
fmt.Sprintf("(&"+l.SearchFilter+")", user),
[]string{"dn"},
nil,
)
Expand Down Expand Up @@ -116,7 +122,7 @@ func (l LdapAuth) LoadLdapGroup(user string, conn *ldap.Conn, req *http.Request)
searchRequest := ldap.NewSearchRequest(
l.GroupSearchBaseDns,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
fmt.Sprintf("(&" + l.GroupSearchFilter + ")", user),
fmt.Sprintf("(&"+l.GroupSearchFilter+")", user),
[]string{l.MemberOf},
nil,
)
Expand Down Expand Up @@ -177,4 +183,4 @@ func (Ldap) Handler(proxyRoute gobis.ProxyRoute, params interface{}, handler htt
}
func (Ldap) Schema() interface{} {
return LdapConfig{}
}
}
4 changes: 4 additions & 0 deletions oauth2/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ func (h Oauth2Handler) getSession(req *http.Request) (*sessions.Session, error)
}

func (h Oauth2Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if h.options.TrustCurrentUser && gobis.Username(req) != "" {
h.next.ServeHTTP(w, req)
return
}
if h.options.PassToken {
gobis.UndirtHeader(req, "Authorization")
} else {
Expand Down
3 changes: 3 additions & 0 deletions oauth2/oauth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ type Oauth2Options struct {
// Set to true to pass the oauth2 token to upstream through authorization header
// This is false by default
PassToken bool `mapstructure:"pass_token" json:"pass_token" yaml:"pass_token"`
// Passthrough if a previous middleware already set user context
// This is helpful when you want add user with basic auth middleware
TrustCurrentUser bool `mapstructure:"trust_current_user" json:"trust_current_user" yaml:"trust_current_user"`
}
type Oauth2 struct{}

Expand Down

0 comments on commit 6e3e8cb

Please sign in to comment.