diff --git a/oauthproxy.go b/oauthproxy.go index 7526d641..c56eb004 100644 --- a/oauthproxy.go +++ b/oauthproxy.go @@ -124,7 +124,12 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr } var basicAuthValidator basic.Validator - if opts.HtpasswdFile != "" { + if opts.RedirectSignUrl != "" { + basicAuthValidator = &basic.AppLoginValidator{ + LoginURL: opts.RedirectSignUrl, + Timeout: 60 * time.Second, + } + } else if opts.HtpasswdFile != "" { logger.Printf("using htpasswd file: %s", opts.HtpasswdFile) var err error basicAuthValidator, err = basic.NewHTPasswdValidator(opts.HtpasswdFile) diff --git a/pkg/apis/options/options.go b/pkg/apis/options/options.go index 8fa72c7c..3048c67a 100644 --- a/pkg/apis/options/options.go +++ b/pkg/apis/options/options.go @@ -33,6 +33,7 @@ type Options struct { EmailDomains []string `flag:"email-domain" cfg:"email_domains"` WhitelistDomains []string `flag:"whitelist-domain" cfg:"whitelist_domains"` HtpasswdFile string `flag:"htpasswd-file" cfg:"htpasswd_file"` + RedirectSignUrl string `flag:"redirect-sign-url" cfg:"redirect-sign-url"` HtpasswdUserGroups []string `flag:"htpasswd-user-group" cfg:"htpasswd_user_groups"` Cookie Cookie `cfg:",squash"` @@ -140,6 +141,7 @@ func NewFlagSet() *pflag.FlagSet { flagSet.StringSlice("whitelist-domain", []string{}, "allowed domains for redirection after authentication. Prefix domain with a . or a *. to allow subdomains (eg .example.com, *.example.com)") 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("redirect-sign-url", "", "additionally sign url using http") 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. //sign_in)") flagSet.String("ping-path", "/ping", "the ping endpoint that can be used for basic health checks") diff --git a/pkg/authentication/basic/http_login.go b/pkg/authentication/basic/http_login.go new file mode 100644 index 00000000..955d0a05 --- /dev/null +++ b/pkg/authentication/basic/http_login.go @@ -0,0 +1,51 @@ +package basic + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "time" +) + +// AppLoginValidator +type AppLoginValidator struct { + LoginURL string + Timeout time.Duration +} + +type loginRequest struct { + Username string `json:"username"` + Password string `json:"password"` +} + +// Validate implement Validator interface +func (v *AppLoginValidator) Validate(user, password string) bool { + reqBody := loginRequest{ + Username: user, + Password: password, + } + data, _ := json.Marshal(reqBody) + + client := &http.Client{Timeout: v.Timeout} + resp, err := client.Post(v.LoginURL, "application/json", bytes.NewReader(data)) + if err != nil { + println(err.Error()) + return false + } + defer resp.Body.Close() + + if resp.StatusCode != 200 { + body, err := io.ReadAll(resp.Body) + if err != nil { + fmt.Printf("ReadAll error: %v\n", err) + return false + } + + fmt.Printf("Response body: %s\n", string(body)) + return false + } + + return true +}