Skip to content
This repository has been archived by the owner on Jan 24, 2019. It is now read-only.

Add support for returning authenticated user #173

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func main() {
flagSet.String("tls-key", "", "path to private key file")
flagSet.String("redirect-url", "", "the OAuth Redirect URL. ie: \"https://internalapp.yourcompany.com/oauth2/callback\"")
flagSet.Var(&upstreams, "upstream", "the http url(s) of the upstream endpoint or file:// paths for static files. Routing is based on the path")
flagSet.Bool("return-authenticated-email", false, "return X-Authorized-Email header (useful when used as authenticator only)")
flagSet.Bool("pass-basic-auth", true, "pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream")
flagSet.String("basic-auth-password", "", "the password to set when passing the HTTP Basic Auth header")
flagSet.Bool("pass-access-token", false, "pass OAuth access_token to upstream via X-Forwarded-Access-Token header")
Expand Down
55 changes: 30 additions & 25 deletions oauthproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,21 @@ type OAuthProxy struct {
OAuthCallbackPath string
AuthOnlyPath string

redirectURL *url.URL // the url to receive requests at
provider providers.Provider
ProxyPrefix string
SignInMessage string
HtpasswdFile *HtpasswdFile
DisplayHtpasswdForm bool
serveMux http.Handler
PassBasicAuth bool
BasicAuthPassword string
PassAccessToken bool
CookieCipher *cookie.Cipher
skipAuthRegex []string
compiledRegex []*regexp.Regexp
templates *template.Template
redirectURL *url.URL // the url to receive requests at
provider providers.Provider
ProxyPrefix string
SignInMessage string
HtpasswdFile *HtpasswdFile
DisplayHtpasswdForm bool
serveMux http.Handler
PassBasicAuth bool
ReturnAuthenticatedEmail bool
BasicAuthPassword string
PassAccessToken bool
CookieCipher *cookie.Cipher
skipAuthRegex []string
compiledRegex []*regexp.Regexp
templates *template.Template
}

type UpstreamProxy struct {
Expand Down Expand Up @@ -186,17 +187,18 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
OAuthCallbackPath: fmt.Sprintf("%s/callback", opts.ProxyPrefix),
AuthOnlyPath: fmt.Sprintf("%s/auth", opts.ProxyPrefix),

ProxyPrefix: opts.ProxyPrefix,
provider: opts.provider,
serveMux: serveMux,
redirectURL: redirectURL,
skipAuthRegex: opts.SkipAuthRegex,
compiledRegex: opts.CompiledRegex,
PassBasicAuth: opts.PassBasicAuth,
BasicAuthPassword: opts.BasicAuthPassword,
PassAccessToken: opts.PassAccessToken,
CookieCipher: cipher,
templates: loadTemplates(opts.CustomTemplatesDir),
ProxyPrefix: opts.ProxyPrefix,
provider: opts.provider,
serveMux: serveMux,
redirectURL: redirectURL,
skipAuthRegex: opts.SkipAuthRegex,
compiledRegex: opts.CompiledRegex,
PassBasicAuth: opts.PassBasicAuth,
ReturnAuthenticatedEmail: opts.ReturnAuthenticatedEmail,
BasicAuthPassword: opts.BasicAuthPassword,
PassAccessToken: opts.PassAccessToken,
CookieCipher: cipher,
templates: loadTemplates(opts.CustomTemplatesDir),
}
}

Expand Down Expand Up @@ -593,6 +595,9 @@ func (p *OAuthProxy) Authenticate(rw http.ResponseWriter, req *http.Request) int
req.Header["X-Forwarded-Email"] = []string{session.Email}
}
}
if p.ReturnAuthenticatedEmail {
rw.Header().Set("X-Authenticated-Email", session.Email)
}
if p.PassAccessToken && session.AccessToken != "" {
req.Header["X-Forwarded-Access-Token"] = []string{session.AccessToken}
}
Expand Down
29 changes: 29 additions & 0 deletions oauthproxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,35 @@ func TestAuthOnlyEndpointUnauthorizedOnEmailValidationFailure(t *testing.T) {
assert.Equal(t, "unauthorized request\n", string(bodyBytes))
}

func TestAuthOnlyEndpointReturnAuthenticatedEmail(t *testing.T) {
var pc_test ProcessCookieTest

pc_test.opts = NewOptions()
pc_test.opts.ReturnAuthenticatedEmail = true
pc_test.opts.Validate()

pc_test.proxy = NewOAuthProxy(pc_test.opts, func(email string) bool {
return pc_test.validate_user
})
pc_test.proxy.provider = &TestProvider{
ValidToken: true,
}

pc_test.validate_user = true

pc_test.rw = httptest.NewRecorder()
pc_test.req, _ = http.NewRequest("GET",
pc_test.opts.ProxyPrefix+"/auth", nil)

startSession := &providers.SessionState{
Email: "[email protected]", AccessToken: "my_access_token"}
pc_test.SaveSession(startSession, time.Now())

pc_test.proxy.ServeHTTP(pc_test.rw, pc_test.req)
assert.Equal(t, http.StatusAccepted, pc_test.rw.Code)
assert.Equal(t, "[email protected]", pc_test.rw.HeaderMap["X-Authenticated-Email"][0])
}

type SignatureAuthenticator struct {
auth hmacauth.HmacAuth
}
Expand Down
42 changes: 22 additions & 20 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ type Options struct {
CookieSecure bool `flag:"cookie-secure" cfg:"cookie_secure"`
CookieHttpOnly bool `flag:"cookie-httponly" cfg:"cookie_httponly"`

Upstreams []string `flag:"upstream" cfg:"upstreams"`
SkipAuthRegex []string `flag:"skip-auth-regex" cfg:"skip_auth_regex"`
PassBasicAuth bool `flag:"pass-basic-auth" cfg:"pass_basic_auth"`
BasicAuthPassword string `flag:"basic-auth-password" cfg:"basic_auth_password"`
PassAccessToken bool `flag:"pass-access-token" cfg:"pass_access_token"`
PassHostHeader bool `flag:"pass-host-header" cfg:"pass_host_header"`
Upstreams []string `flag:"upstream" cfg:"upstreams"`
SkipAuthRegex []string `flag:"skip-auth-regex" cfg:"skip_auth_regex"`
ReturnAuthenticatedEmail bool `flag:"return-authenticated-email" cfg:"return_authenticated_email"`
PassBasicAuth bool `flag:"pass-basic-auth" cfg:"pass_basic_auth"`
BasicAuthPassword string `flag:"basic-auth-password" cfg:"basic_auth_password"`
PassAccessToken bool `flag:"pass-access-token" cfg:"pass_access_token"`
PassHostHeader bool `flag:"pass-host-header" cfg:"pass_host_header"`

// These options allow for other providers besides Google, with
// potential overrides.
Expand Down Expand Up @@ -79,20 +80,21 @@ type SignatureData struct {

func NewOptions() *Options {
return &Options{
ProxyPrefix: "/oauth2",
HttpAddress: "127.0.0.1:4180",
HttpsAddress: ":443",
DisplayHtpasswdForm: true,
CookieName: "_oauth2_proxy",
CookieSecure: true,
CookieHttpOnly: true,
CookieExpire: time.Duration(168) * time.Hour,
CookieRefresh: time.Duration(0),
PassBasicAuth: true,
PassAccessToken: false,
PassHostHeader: true,
ApprovalPrompt: "force",
RequestLogging: true,
ProxyPrefix: "/oauth2",
HttpAddress: "127.0.0.1:4180",
HttpsAddress: ":443",
DisplayHtpasswdForm: true,
CookieName: "_oauth2_proxy",
CookieSecure: true,
CookieHttpOnly: true,
CookieExpire: time.Duration(168) * time.Hour,
CookieRefresh: time.Duration(0),
ReturnAuthenticatedEmail: false,
PassBasicAuth: true,
PassAccessToken: false,
PassHostHeader: true,
ApprovalPrompt: "force",
RequestLogging: true,
}
}

Expand Down