mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2025-01-10 04:18:14 +02:00
Add support for setting groups on session when using basic auth (#1064)
* Add support for setting groups on session when using basic auth * Refactoring based on feedback * Attribution
This commit is contained in:
parent
d3147c3ab2
commit
220b3708fc
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
## Changes since v7.0.1
|
## Changes since v7.0.1
|
||||||
|
|
||||||
|
- [#1064](https://github.com/oauth2-proxy/oauth2-proxy/pull/1064) Add support for setting groups on session when using basic auth (@stefansedich)
|
||||||
- [#1056](https://github.com/oauth2-proxy/oauth2-proxy/pull/1056) Add option for custom logos on the sign in page (@JoelSpeed)
|
- [#1056](https://github.com/oauth2-proxy/oauth2-proxy/pull/1056) Add option for custom logos on the sign in page (@JoelSpeed)
|
||||||
- [#1054](https://github.com/oauth2-proxy/oauth2-proxy/pull/1054) Update to Go 1.16 (@JoelSpeed)
|
- [#1054](https://github.com/oauth2-proxy/oauth2-proxy/pull/1054) Update to Go 1.16 (@JoelSpeed)
|
||||||
- [#1052](https://github.com/oauth2-proxy/oauth2-proxy/pull/1052) Update golangci-lint to latest version (v1.36.0) (@JoelSpeed)
|
- [#1052](https://github.com/oauth2-proxy/oauth2-proxy/pull/1052) Update golangci-lint to latest version (v1.36.0) (@JoelSpeed)
|
||||||
|
@ -62,6 +62,7 @@ An example [oauth2-proxy.cfg](https://github.com/oauth2-proxy/oauth2-proxy/blob/
|
|||||||
| `--google-group` | string | restrict logins to members of this google group (may be given multiple times). | |
|
| `--google-group` | string | restrict logins to members of this google group (may be given multiple times). | |
|
||||||
| `--google-service-account-json` | string | the path to the service account json credentials | |
|
| `--google-service-account-json` | string | the path to the service account json credentials | |
|
||||||
| `--htpasswd-file` | string | additionally authenticate against a htpasswd file. Entries must be created with `htpasswd -B` for bcrypt encryption | |
|
| `--htpasswd-file` | string | additionally authenticate against a htpasswd file. Entries must be created with `htpasswd -B` for bcrypt encryption | |
|
||||||
|
| `--htpasswd-user-group` | string \| list | the groups to be set on sessions for htpasswd users | |
|
||||||
| `--http-address` | string | `[http://]<addr>:<port>` or `unix://<path>` to listen on for HTTP clients | `"127.0.0.1:4180"` |
|
| `--http-address` | string | `[http://]<addr>:<port>` or `unix://<path>` to listen on for HTTP clients | `"127.0.0.1:4180"` |
|
||||||
| `--https-address` | string | `<addr>:<port>` to listen on for HTTPS clients | `":443"` |
|
| `--https-address` | string | `<addr>:<port>` to listen on for HTTPS clients | `":443"` |
|
||||||
| `--logging-compress` | bool | Should rotated log files be compressed using gzip | false |
|
| `--logging-compress` | bool | Should rotated log files be compressed using gzip | false |
|
||||||
|
@ -277,7 +277,7 @@ func buildSessionChain(opts *options.Options, sessionStore sessionsapi.SessionSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
if validator != nil {
|
if validator != nil {
|
||||||
chain = chain.Append(middleware.NewBasicAuthSessionLoader(validator))
|
chain = chain.Append(middleware.NewBasicAuthSessionLoader(validator, opts.HtpasswdUserGroups))
|
||||||
}
|
}
|
||||||
|
|
||||||
chain = chain.Append(middleware.NewStoredSessionLoader(&middleware.StoredSessionLoaderOptions{
|
chain = chain.Append(middleware.NewStoredSessionLoader(&middleware.StoredSessionLoaderOptions{
|
||||||
|
@ -54,6 +54,7 @@ type Options struct {
|
|||||||
GoogleAdminEmail string `flag:"google-admin-email" cfg:"google_admin_email"`
|
GoogleAdminEmail string `flag:"google-admin-email" cfg:"google_admin_email"`
|
||||||
GoogleServiceAccountJSON string `flag:"google-service-account-json" cfg:"google_service_account_json"`
|
GoogleServiceAccountJSON string `flag:"google-service-account-json" cfg:"google_service_account_json"`
|
||||||
HtpasswdFile string `flag:"htpasswd-file" cfg:"htpasswd_file"`
|
HtpasswdFile string `flag:"htpasswd-file" cfg:"htpasswd_file"`
|
||||||
|
HtpasswdUserGroups []string `flag:"htpasswd-user-group" cfg:"htpasswd_user_groups"`
|
||||||
|
|
||||||
Cookie Cookie `cfg:",squash"`
|
Cookie Cookie `cfg:",squash"`
|
||||||
Session SessionOptions `cfg:",squash"`
|
Session SessionOptions `cfg:",squash"`
|
||||||
@ -199,6 +200,7 @@ func NewFlagSet() *pflag.FlagSet {
|
|||||||
flagSet.String("client-secret-file", "", "the file with OAuth Client Secret")
|
flagSet.String("client-secret-file", "", "the file with OAuth Client Secret")
|
||||||
flagSet.String("authenticated-emails-file", "", "authenticate against emails via file (one per line)")
|
flagSet.String("authenticated-emails-file", "", "authenticate against emails via file (one per line)")
|
||||||
flagSet.String("htpasswd-file", "", "additionally authenticate against a htpasswd file. Entries must be created with \"htpasswd -B\" for bcrypt encryption")
|
flagSet.String("htpasswd-file", "", "additionally authenticate against a htpasswd file. Entries must be created with \"htpasswd -B\" for bcrypt encryption")
|
||||||
|
flagSet.StringSlice("htpasswd-user-group", []string{}, "the groups to be set on sessions for htpasswd users (may be given multiple times)")
|
||||||
flagSet.String("proxy-prefix", "/oauth2", "the url root path that this proxy should be nested under (e.g. /<oauth2>/sign_in)")
|
flagSet.String("proxy-prefix", "/oauth2", "the url root path that this proxy should be nested under (e.g. /<oauth2>/sign_in)")
|
||||||
flagSet.String("ping-path", "/ping", "the ping endpoint that can be used for basic health checks")
|
flagSet.String("ping-path", "/ping", "the ping endpoint that can be used for basic health checks")
|
||||||
flagSet.String("ping-user-agent", "", "special User-Agent that will be used for basic health checks")
|
flagSet.String("ping-user-agent", "", "special User-Agent that will be used for basic health checks")
|
||||||
|
@ -11,9 +11,9 @@ import (
|
|||||||
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
|
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewBasicAuthSessionLoader(validator basic.Validator) alice.Constructor {
|
func NewBasicAuthSessionLoader(validator basic.Validator, sessionGroups []string) alice.Constructor {
|
||||||
return func(next http.Handler) http.Handler {
|
return func(next http.Handler) http.Handler {
|
||||||
return loadBasicAuthSession(validator, next)
|
return loadBasicAuthSession(validator, sessionGroups, next)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ func NewBasicAuthSessionLoader(validator basic.Validator) alice.Constructor {
|
|||||||
// If no authorization header is found, or the header is invalid, no session
|
// If no authorization header is found, or the header is invalid, no session
|
||||||
// will be loaded and the request will be passed to the next handler.
|
// will be loaded and the request will be passed to the next handler.
|
||||||
// If a session was loaded by a previous handler, it will not be replaced.
|
// If a session was loaded by a previous handler, it will not be replaced.
|
||||||
func loadBasicAuthSession(validator basic.Validator, next http.Handler) http.Handler {
|
func loadBasicAuthSession(validator basic.Validator, sessionGroups []string, next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
scope := middlewareapi.GetRequestScope(req)
|
scope := middlewareapi.GetRequestScope(req)
|
||||||
// If scope is nil, this will panic.
|
// If scope is nil, this will panic.
|
||||||
@ -33,7 +33,7 @@ func loadBasicAuthSession(validator basic.Validator, next http.Handler) http.Han
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
session, err := getBasicSession(validator, req)
|
session, err := getBasicSession(validator, sessionGroups, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Error retrieving session from token in Authorization header: %v", err)
|
logger.Errorf("Error retrieving session from token in Authorization header: %v", err)
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ func loadBasicAuthSession(validator basic.Validator, next http.Handler) http.Han
|
|||||||
// getBasicSession attempts to load a basic session from the request.
|
// getBasicSession attempts to load a basic session from the request.
|
||||||
// If the credentials in the request exist within the htpasswdMap,
|
// If the credentials in the request exist within the htpasswdMap,
|
||||||
// a new session will be created.
|
// a new session will be created.
|
||||||
func getBasicSession(validator basic.Validator, req *http.Request) (*sessionsapi.SessionState, error) {
|
func getBasicSession(validator basic.Validator, sessionGroups []string, req *http.Request) (*sessionsapi.SessionState, error) {
|
||||||
auth := req.Header.Get("Authorization")
|
auth := req.Header.Get("Authorization")
|
||||||
if auth == "" {
|
if auth == "" {
|
||||||
// No auth header provided, so don't attempt to load a session
|
// No auth header provided, so don't attempt to load a session
|
||||||
@ -61,7 +61,8 @@ func getBasicSession(validator basic.Validator, req *http.Request) (*sessionsapi
|
|||||||
|
|
||||||
if validator.Validate(user, password) {
|
if validator.Validate(user, password) {
|
||||||
logger.PrintAuthf(user, req, logger.AuthSuccess, "Authenticated via basic auth and HTpasswd File")
|
logger.PrintAuthf(user, req, logger.AuthSuccess, "Authenticated via basic auth and HTpasswd File")
|
||||||
return &sessionsapi.SessionState{User: user}, nil
|
|
||||||
|
return &sessionsapi.SessionState{User: user, Groups: sessionGroups}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.PrintAuthf(user, req, logger.AuthFailure, "Invalid authentication via basic auth: not in Htpasswd File")
|
logger.PrintAuthf(user, req, logger.AuthFailure, "Invalid authentication via basic auth: not in Htpasswd File")
|
||||||
|
@ -26,6 +26,7 @@ var _ = Describe("Basic Auth Session Suite", func() {
|
|||||||
|
|
||||||
type basicAuthSessionLoaderTableInput struct {
|
type basicAuthSessionLoaderTableInput struct {
|
||||||
authorizationHeader string
|
authorizationHeader string
|
||||||
|
sessionGroups []string
|
||||||
existingSession *sessionsapi.SessionState
|
existingSession *sessionsapi.SessionState
|
||||||
expectedSession *sessionsapi.SessionState
|
expectedSession *sessionsapi.SessionState
|
||||||
}
|
}
|
||||||
@ -54,7 +55,7 @@ var _ = Describe("Basic Auth Session Suite", func() {
|
|||||||
// Create the handler with a next handler that will capture the session
|
// Create the handler with a next handler that will capture the session
|
||||||
// from the scope
|
// from the scope
|
||||||
var gotSession *sessionsapi.SessionState
|
var gotSession *sessionsapi.SessionState
|
||||||
handler := NewBasicAuthSessionLoader(validator)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
handler := NewBasicAuthSessionLoader(validator, in.sessionGroups)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
gotSession = middlewareapi.GetRequestScope(r).Session
|
gotSession = middlewareapi.GetRequestScope(r).Session
|
||||||
}))
|
}))
|
||||||
handler.ServeHTTP(rw, req)
|
handler.ServeHTTP(rw, req)
|
||||||
@ -111,6 +112,12 @@ var _ = Describe("Basic Auth Session Suite", func() {
|
|||||||
existingSession: nil,
|
existingSession: nil,
|
||||||
expectedSession: &sessionsapi.SessionState{User: "admin"},
|
expectedSession: &sessionsapi.SessionState{User: "admin"},
|
||||||
}),
|
}),
|
||||||
|
Entry("Basic with groups", basicAuthSessionLoaderTableInput{
|
||||||
|
authorizationHeader: "Basic YWRtaW46QWRtMW4xc3RyJHQwcg==",
|
||||||
|
sessionGroups: []string{"a", "b"},
|
||||||
|
existingSession: nil,
|
||||||
|
expectedSession: &sessionsapi.SessionState{User: "admin", Groups: []string{"a", "b"}},
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user