commit
						e6e2dbe459
					
				
							
								
								
									
										6
									
								
								main.go
								
								
								
								
							
							
						
						
									
										6
									
								
								main.go
								
								
								
								
							|  | @ -66,8 +66,8 @@ func main() { | ||||||
| 	flagSet.String("redeem-url", "", "Token redemption endpoint") | 	flagSet.String("redeem-url", "", "Token redemption endpoint") | ||||||
| 	flagSet.String("profile-url", "", "Profile access endpoint") | 	flagSet.String("profile-url", "", "Profile access endpoint") | ||||||
| 	flagSet.String("validate-url", "", "Access token validation endpoint") | 	flagSet.String("validate-url", "", "Access token validation endpoint") | ||||||
| 	flagSet.String("scope", "", "Oauth scope specification") | 	flagSet.String("scope", "", "OAuth scope specification") | ||||||
| 	flagSet.String("approval-prompt", "force", "Oauth approval_prompt") | 	flagSet.String("approval-prompt", "force", "OAuth approval_prompt") | ||||||
| 
 | 
 | ||||||
| 	flagSet.Parse(os.Args[1:]) | 	flagSet.Parse(os.Args[1:]) | ||||||
| 
 | 
 | ||||||
|  | @ -95,7 +95,7 @@ func main() { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	validator := NewValidator(opts.EmailDomains, opts.AuthenticatedEmailsFile) | 	validator := NewValidator(opts.EmailDomains, opts.AuthenticatedEmailsFile) | ||||||
| 	oauthproxy := NewOauthProxy(opts, validator) | 	oauthproxy := NewOAuthProxy(opts, validator) | ||||||
| 
 | 
 | ||||||
| 	if len(opts.EmailDomains) != 0 && opts.AuthenticatedEmailsFile == "" { | 	if len(opts.EmailDomains) != 0 && opts.AuthenticatedEmailsFile == "" { | ||||||
| 		if len(opts.EmailDomains) > 1 { | 		if len(opts.EmailDomains) > 1 { | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ import ( | ||||||
| 	"github.com/bitly/oauth2_proxy/providers" | 	"github.com/bitly/oauth2_proxy/providers" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type OauthProxy struct { | type OAuthProxy struct { | ||||||
| 	CookieSeed     string | 	CookieSeed     string | ||||||
| 	CookieName     string | 	CookieName     string | ||||||
| 	CookieDomain   string | 	CookieDomain   string | ||||||
|  | @ -31,10 +31,10 @@ type OauthProxy struct { | ||||||
| 	RobotsPath        string | 	RobotsPath        string | ||||||
| 	PingPath          string | 	PingPath          string | ||||||
| 	SignInPath        string | 	SignInPath        string | ||||||
| 	OauthStartPath    string | 	OAuthStartPath    string | ||||||
| 	OauthCallbackPath string | 	OAuthCallbackPath string | ||||||
| 
 | 
 | ||||||
| 	redirectUrl         *url.URL // the url to receive requests at
 | 	redirectURL         *url.URL // the url to receive requests at
 | ||||||
| 	provider            providers.Provider | 	provider            providers.Provider | ||||||
| 	ProxyPrefix         string | 	ProxyPrefix         string | ||||||
| 	SignInMessage       string | 	SignInMessage       string | ||||||
|  | @ -86,9 +86,9 @@ func NewFileServer(path string, filesystemPath string) (proxy http.Handler) { | ||||||
| 	return http.StripPrefix(path, http.FileServer(http.Dir(filesystemPath))) | 	return http.StripPrefix(path, http.FileServer(http.Dir(filesystemPath))) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func NewOauthProxy(opts *Options, validator func(string) bool) *OauthProxy { | func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy { | ||||||
| 	serveMux := http.NewServeMux() | 	serveMux := http.NewServeMux() | ||||||
| 	for _, u := range opts.proxyUrls { | 	for _, u := range opts.proxyURLs { | ||||||
| 		path := u.Path | 		path := u.Path | ||||||
| 		switch u.Scheme { | 		switch u.Scheme { | ||||||
| 		case "http", "https": | 		case "http", "https": | ||||||
|  | @ -116,10 +116,10 @@ func NewOauthProxy(opts *Options, validator func(string) bool) *OauthProxy { | ||||||
| 		log.Printf("compiled skip-auth-regex => %q", u) | 		log.Printf("compiled skip-auth-regex => %q", u) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	redirectUrl := opts.redirectUrl | 	redirectURL := opts.redirectURL | ||||||
| 	redirectUrl.Path = fmt.Sprintf("%s/callback", opts.ProxyPrefix) | 	redirectURL.Path = fmt.Sprintf("%s/callback", opts.ProxyPrefix) | ||||||
| 
 | 
 | ||||||
| 	log.Printf("OauthProxy configured for %s Client ID: %s", opts.provider.Data().ProviderName, opts.ClientID) | 	log.Printf("OAuthProxy configured for %s Client ID: %s", opts.provider.Data().ProviderName, opts.ClientID) | ||||||
| 	domain := opts.CookieDomain | 	domain := opts.CookieDomain | ||||||
| 	if domain == "" { | 	if domain == "" { | ||||||
| 		domain = "<default>" | 		domain = "<default>" | ||||||
|  | @ -141,7 +141,7 @@ func NewOauthProxy(opts *Options, validator func(string) bool) *OauthProxy { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return &OauthProxy{ | 	return &OAuthProxy{ | ||||||
| 		CookieName:     opts.CookieName, | 		CookieName:     opts.CookieName, | ||||||
| 		CookieSeed:     opts.CookieSecret, | 		CookieSeed:     opts.CookieSecret, | ||||||
| 		CookieDomain:   opts.CookieDomain, | 		CookieDomain:   opts.CookieDomain, | ||||||
|  | @ -154,13 +154,13 @@ func NewOauthProxy(opts *Options, validator func(string) bool) *OauthProxy { | ||||||
| 		RobotsPath:        "/robots.txt", | 		RobotsPath:        "/robots.txt", | ||||||
| 		PingPath:          "/ping", | 		PingPath:          "/ping", | ||||||
| 		SignInPath:        fmt.Sprintf("%s/sign_in", opts.ProxyPrefix), | 		SignInPath:        fmt.Sprintf("%s/sign_in", opts.ProxyPrefix), | ||||||
| 		OauthStartPath:    fmt.Sprintf("%s/start", opts.ProxyPrefix), | 		OAuthStartPath:    fmt.Sprintf("%s/start", opts.ProxyPrefix), | ||||||
| 		OauthCallbackPath: fmt.Sprintf("%s/callback", opts.ProxyPrefix), | 		OAuthCallbackPath: fmt.Sprintf("%s/callback", opts.ProxyPrefix), | ||||||
| 
 | 
 | ||||||
| 		ProxyPrefix:       opts.ProxyPrefix, | 		ProxyPrefix:       opts.ProxyPrefix, | ||||||
| 		provider:          opts.provider, | 		provider:          opts.provider, | ||||||
| 		serveMux:          serveMux, | 		serveMux:          serveMux, | ||||||
| 		redirectUrl:       redirectUrl, | 		redirectURL:       redirectURL, | ||||||
| 		skipAuthRegex:     opts.SkipAuthRegex, | 		skipAuthRegex:     opts.SkipAuthRegex, | ||||||
| 		compiledRegex:     opts.CompiledRegex, | 		compiledRegex:     opts.CompiledRegex, | ||||||
| 		PassBasicAuth:     opts.PassBasicAuth, | 		PassBasicAuth:     opts.PassBasicAuth, | ||||||
|  | @ -171,13 +171,13 @@ func NewOauthProxy(opts *Options, validator func(string) bool) *OauthProxy { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) GetRedirectURI(host string) string { | func (p *OAuthProxy) GetRedirectURI(host string) string { | ||||||
| 	// default to the request Host if not set
 | 	// default to the request Host if not set
 | ||||||
| 	if p.redirectUrl.Host != "" { | 	if p.redirectURL.Host != "" { | ||||||
| 		return p.redirectUrl.String() | 		return p.redirectURL.String() | ||||||
| 	} | 	} | ||||||
| 	var u url.URL | 	var u url.URL | ||||||
| 	u = *p.redirectUrl | 	u = *p.redirectURL | ||||||
| 	if u.Scheme == "" { | 	if u.Scheme == "" { | ||||||
| 		if p.CookieSecure { | 		if p.CookieSecure { | ||||||
| 			u.Scheme = "https" | 			u.Scheme = "https" | ||||||
|  | @ -189,16 +189,16 @@ func (p *OauthProxy) GetRedirectURI(host string) string { | ||||||
| 	return u.String() | 	return u.String() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) displayCustomLoginForm() bool { | func (p *OAuthProxy) displayCustomLoginForm() bool { | ||||||
| 	return p.HtpasswdFile != nil && p.DisplayHtpasswdForm | 	return p.HtpasswdFile != nil && p.DisplayHtpasswdForm | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) redeemCode(host, code string) (s *providers.SessionState, err error) { | func (p *OAuthProxy) redeemCode(host, code string) (s *providers.SessionState, err error) { | ||||||
| 	if code == "" { | 	if code == "" { | ||||||
| 		return nil, errors.New("missing code") | 		return nil, errors.New("missing code") | ||||||
| 	} | 	} | ||||||
| 	redirectUri := p.GetRedirectURI(host) | 	redirectURI := p.GetRedirectURI(host) | ||||||
| 	s, err = p.provider.Redeem(redirectUri, code) | 	s, err = p.provider.Redeem(redirectURI, code) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | @ -209,7 +209,7 @@ func (p *OauthProxy) redeemCode(host, code string) (s *providers.SessionState, e | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) MakeCookie(req *http.Request, value string, expiration time.Duration, now time.Time) *http.Cookie { | func (p *OAuthProxy) MakeCookie(req *http.Request, value string, expiration time.Duration, now time.Time) *http.Cookie { | ||||||
| 	domain := req.Host | 	domain := req.Host | ||||||
| 	if h, _, err := net.SplitHostPort(domain); err == nil { | 	if h, _, err := net.SplitHostPort(domain); err == nil { | ||||||
| 		domain = h | 		domain = h | ||||||
|  | @ -235,15 +235,15 @@ func (p *OauthProxy) MakeCookie(req *http.Request, value string, expiration time | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) ClearCookie(rw http.ResponseWriter, req *http.Request) { | func (p *OAuthProxy) ClearCookie(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	http.SetCookie(rw, p.MakeCookie(req, "", time.Hour*-1, time.Now())) | 	http.SetCookie(rw, p.MakeCookie(req, "", time.Hour*-1, time.Now())) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) SetCookie(rw http.ResponseWriter, req *http.Request, val string) { | func (p *OAuthProxy) SetCookie(rw http.ResponseWriter, req *http.Request, val string) { | ||||||
| 	http.SetCookie(rw, p.MakeCookie(req, val, p.CookieExpire, time.Now())) | 	http.SetCookie(rw, p.MakeCookie(req, val, p.CookieExpire, time.Now())) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) LoadCookiedSession(req *http.Request) (*providers.SessionState, time.Duration, error) { | func (p *OAuthProxy) LoadCookiedSession(req *http.Request) (*providers.SessionState, time.Duration, error) { | ||||||
| 	var age time.Duration | 	var age time.Duration | ||||||
| 	c, err := req.Cookie(p.CookieName) | 	c, err := req.Cookie(p.CookieName) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | @ -264,7 +264,7 @@ func (p *OauthProxy) LoadCookiedSession(req *http.Request) (*providers.SessionSt | ||||||
| 	return session, age, nil | 	return session, age, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) SaveSession(rw http.ResponseWriter, req *http.Request, s *providers.SessionState) error { | func (p *OAuthProxy) SaveSession(rw http.ResponseWriter, req *http.Request, s *providers.SessionState) error { | ||||||
| 	value, err := p.provider.CookieForSession(s, p.CookieCipher) | 	value, err := p.provider.CookieForSession(s, p.CookieCipher) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
|  | @ -273,17 +273,17 @@ func (p *OauthProxy) SaveSession(rw http.ResponseWriter, req *http.Request, s *p | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) RobotsTxt(rw http.ResponseWriter) { | func (p *OAuthProxy) RobotsTxt(rw http.ResponseWriter) { | ||||||
| 	rw.WriteHeader(http.StatusOK) | 	rw.WriteHeader(http.StatusOK) | ||||||
| 	fmt.Fprintf(rw, "User-agent: *\nDisallow: /") | 	fmt.Fprintf(rw, "User-agent: *\nDisallow: /") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) PingPage(rw http.ResponseWriter) { | func (p *OAuthProxy) PingPage(rw http.ResponseWriter) { | ||||||
| 	rw.WriteHeader(http.StatusOK) | 	rw.WriteHeader(http.StatusOK) | ||||||
| 	fmt.Fprintf(rw, "OK") | 	fmt.Fprintf(rw, "OK") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) ErrorPage(rw http.ResponseWriter, code int, title string, message string) { | func (p *OAuthProxy) ErrorPage(rw http.ResponseWriter, code int, title string, message string) { | ||||||
| 	log.Printf("ErrorPage %d %s %s", code, title, message) | 	log.Printf("ErrorPage %d %s %s", code, title, message) | ||||||
| 	rw.WriteHeader(code) | 	rw.WriteHeader(code) | ||||||
| 	t := struct { | 	t := struct { | ||||||
|  | @ -298,7 +298,7 @@ func (p *OauthProxy) ErrorPage(rw http.ResponseWriter, code int, title string, m | ||||||
| 	p.templates.ExecuteTemplate(rw, "error.html", t) | 	p.templates.ExecuteTemplate(rw, "error.html", t) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code int) { | func (p *OAuthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code int) { | ||||||
| 	p.ClearCookie(rw, req) | 	p.ClearCookie(rw, req) | ||||||
| 	rw.WriteHeader(code) | 	rw.WriteHeader(code) | ||||||
| 
 | 
 | ||||||
|  | @ -325,7 +325,7 @@ func (p *OauthProxy) SignInPage(rw http.ResponseWriter, req *http.Request, code | ||||||
| 	p.templates.ExecuteTemplate(rw, "sign_in.html", t) | 	p.templates.ExecuteTemplate(rw, "sign_in.html", t) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) ManualSignIn(rw http.ResponseWriter, req *http.Request) (string, bool) { | func (p *OAuthProxy) ManualSignIn(rw http.ResponseWriter, req *http.Request) (string, bool) { | ||||||
| 	if req.Method != "POST" || p.HtpasswdFile == nil { | 	if req.Method != "POST" || p.HtpasswdFile == nil { | ||||||
| 		return "", false | 		return "", false | ||||||
| 	} | 	} | ||||||
|  | @ -342,7 +342,7 @@ func (p *OauthProxy) ManualSignIn(rw http.ResponseWriter, req *http.Request) (st | ||||||
| 	return "", false | 	return "", false | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) GetRedirect(req *http.Request) (string, error) { | func (p *OAuthProxy) GetRedirect(req *http.Request) (string, error) { | ||||||
| 	err := req.ParseForm() | 	err := req.ParseForm() | ||||||
| 
 | 
 | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | @ -358,7 +358,7 @@ func (p *OauthProxy) GetRedirect(req *http.Request) (string, error) { | ||||||
| 	return redirect, err | 	return redirect, err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) IsWhitelistedPath(path string) (ok bool) { | func (p *OAuthProxy) IsWhitelistedPath(path string) (ok bool) { | ||||||
| 	for _, u := range p.compiledRegex { | 	for _, u := range p.compiledRegex { | ||||||
| 		ok = u.MatchString(path) | 		ok = u.MatchString(path) | ||||||
| 		if ok { | 		if ok { | ||||||
|  | @ -376,7 +376,7 @@ func getRemoteAddr(req *http.Request) (s string) { | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { | func (p *OAuthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	switch path := req.URL.Path; { | 	switch path := req.URL.Path; { | ||||||
| 	case path == p.RobotsPath: | 	case path == p.RobotsPath: | ||||||
| 		p.RobotsTxt(rw) | 		p.RobotsTxt(rw) | ||||||
|  | @ -386,16 +386,16 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { | ||||||
| 		p.serveMux.ServeHTTP(rw, req) | 		p.serveMux.ServeHTTP(rw, req) | ||||||
| 	case path == p.SignInPath: | 	case path == p.SignInPath: | ||||||
| 		p.SignIn(rw, req) | 		p.SignIn(rw, req) | ||||||
| 	case path == p.OauthStartPath: | 	case path == p.OAuthStartPath: | ||||||
| 		p.OauthStart(rw, req) | 		p.OAuthStart(rw, req) | ||||||
| 	case path == p.OauthCallbackPath: | 	case path == p.OAuthCallbackPath: | ||||||
| 		p.OauthCallback(rw, req) | 		p.OAuthCallback(rw, req) | ||||||
| 	default: | 	default: | ||||||
| 		p.Proxy(rw, req) | 		p.Proxy(rw, req) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) SignIn(rw http.ResponseWriter, req *http.Request) { | func (p *OAuthProxy) SignIn(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	redirect, err := p.GetRedirect(req) | 	redirect, err := p.GetRedirect(req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		p.ErrorPage(rw, 500, "Internal Error", err.Error()) | 		p.ErrorPage(rw, 500, "Internal Error", err.Error()) | ||||||
|  | @ -412,7 +412,7 @@ func (p *OauthProxy) SignIn(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) OauthStart(rw http.ResponseWriter, req *http.Request) { | func (p *OAuthProxy) OAuthStart(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	redirect, err := p.GetRedirect(req) | 	redirect, err := p.GetRedirect(req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		p.ErrorPage(rw, 500, "Internal Error", err.Error()) | 		p.ErrorPage(rw, 500, "Internal Error", err.Error()) | ||||||
|  | @ -422,7 +422,7 @@ func (p *OauthProxy) OauthStart(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	http.Redirect(rw, req, p.provider.GetLoginURL(redirectURI, redirect), 302) | 	http.Redirect(rw, req, p.provider.GetLoginURL(redirectURI, redirect), 302) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) OauthCallback(rw http.ResponseWriter, req *http.Request) { | func (p *OAuthProxy) OAuthCallback(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	remoteAddr := getRemoteAddr(req) | 	remoteAddr := getRemoteAddr(req) | ||||||
| 
 | 
 | ||||||
| 	// finish the oauth cycle
 | 	// finish the oauth cycle
 | ||||||
|  | @ -465,7 +465,7 @@ func (p *OauthProxy) OauthCallback(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) Proxy(rw http.ResponseWriter, req *http.Request) { | func (p *OAuthProxy) Proxy(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	var saveSession, clearSession, revalidated bool | 	var saveSession, clearSession, revalidated bool | ||||||
| 	remoteAddr := getRemoteAddr(req) | 	remoteAddr := getRemoteAddr(req) | ||||||
| 
 | 
 | ||||||
|  | @ -555,7 +555,7 @@ func (p *OauthProxy) Proxy(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	p.serveMux.ServeHTTP(rw, req) | 	p.serveMux.ServeHTTP(rw, req) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *OauthProxy) CheckBasicAuth(req *http.Request) (*providers.SessionState, error) { | func (p *OAuthProxy) CheckBasicAuth(req *http.Request) (*providers.SessionState, error) { | ||||||
| 	if p.HtpasswdFile == nil { | 	if p.HtpasswdFile == nil { | ||||||
| 		return nil, nil | 		return nil, nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -80,7 +80,7 @@ func TestRobotsTxt(t *testing.T) { | ||||||
| 	opts.CookieSecret = "xyzzyplugh" | 	opts.CookieSecret = "xyzzyplugh" | ||||||
| 	opts.Validate() | 	opts.Validate() | ||||||
| 
 | 
 | ||||||
| 	proxy := NewOauthProxy(opts, func(string) bool { return true }) | 	proxy := NewOAuthProxy(opts, func(string) bool { return true }) | ||||||
| 	rw := httptest.NewRecorder() | 	rw := httptest.NewRecorder() | ||||||
| 	req, _ := http.NewRequest("GET", "/robots.txt", nil) | 	req, _ := http.NewRequest("GET", "/robots.txt", nil) | ||||||
| 	proxy.ServeHTTP(rw, req) | 	proxy.ServeHTTP(rw, req) | ||||||
|  | @ -124,17 +124,17 @@ func TestBasicAuthPassword(t *testing.T) { | ||||||
| 	opts.provider = &TestProvider{ | 	opts.provider = &TestProvider{ | ||||||
| 		ProviderData: &providers.ProviderData{ | 		ProviderData: &providers.ProviderData{ | ||||||
| 			ProviderName: "Test Provider", | 			ProviderName: "Test Provider", | ||||||
| 			LoginUrl: &url.URL{ | 			LoginURL: &url.URL{ | ||||||
| 				Scheme: "http", | 				Scheme: "http", | ||||||
| 				Host:   provider_url.Host, | 				Host:   provider_url.Host, | ||||||
| 				Path:   "/oauth/authorize", | 				Path:   "/oauth/authorize", | ||||||
| 			}, | 			}, | ||||||
| 			RedeemUrl: &url.URL{ | 			RedeemURL: &url.URL{ | ||||||
| 				Scheme: "http", | 				Scheme: "http", | ||||||
| 				Host:   provider_url.Host, | 				Host:   provider_url.Host, | ||||||
| 				Path:   "/oauth/token", | 				Path:   "/oauth/token", | ||||||
| 			}, | 			}, | ||||||
| 			ProfileUrl: &url.URL{ | 			ProfileURL: &url.URL{ | ||||||
| 				Scheme: "http", | 				Scheme: "http", | ||||||
| 				Host:   provider_url.Host, | 				Host:   provider_url.Host, | ||||||
| 				Path:   "/api/v1/profile", | 				Path:   "/api/v1/profile", | ||||||
|  | @ -144,7 +144,7 @@ func TestBasicAuthPassword(t *testing.T) { | ||||||
| 		EmailAddress: email_address, | 		EmailAddress: email_address, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	proxy := NewOauthProxy(opts, func(email string) bool { | 	proxy := NewOAuthProxy(opts, func(email string) bool { | ||||||
| 		return email == email_address | 		return email == email_address | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
|  | @ -199,7 +199,7 @@ func (tp *TestProvider) ValidateSessionState(session *providers.SessionState) bo | ||||||
| 
 | 
 | ||||||
| type PassAccessTokenTest struct { | type PassAccessTokenTest struct { | ||||||
| 	provider_server *httptest.Server | 	provider_server *httptest.Server | ||||||
| 	proxy           *OauthProxy | 	proxy           *OAuthProxy | ||||||
| 	opts            *Options | 	opts            *Options | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -245,17 +245,17 @@ func NewPassAccessTokenTest(opts PassAccessTokenTestOptions) *PassAccessTokenTes | ||||||
| 	t.opts.provider = &TestProvider{ | 	t.opts.provider = &TestProvider{ | ||||||
| 		ProviderData: &providers.ProviderData{ | 		ProviderData: &providers.ProviderData{ | ||||||
| 			ProviderName: "Test Provider", | 			ProviderName: "Test Provider", | ||||||
| 			LoginUrl: &url.URL{ | 			LoginURL: &url.URL{ | ||||||
| 				Scheme: "http", | 				Scheme: "http", | ||||||
| 				Host:   provider_url.Host, | 				Host:   provider_url.Host, | ||||||
| 				Path:   "/oauth/authorize", | 				Path:   "/oauth/authorize", | ||||||
| 			}, | 			}, | ||||||
| 			RedeemUrl: &url.URL{ | 			RedeemURL: &url.URL{ | ||||||
| 				Scheme: "http", | 				Scheme: "http", | ||||||
| 				Host:   provider_url.Host, | 				Host:   provider_url.Host, | ||||||
| 				Path:   "/oauth/token", | 				Path:   "/oauth/token", | ||||||
| 			}, | 			}, | ||||||
| 			ProfileUrl: &url.URL{ | 			ProfileURL: &url.URL{ | ||||||
| 				Scheme: "http", | 				Scheme: "http", | ||||||
| 				Host:   provider_url.Host, | 				Host:   provider_url.Host, | ||||||
| 				Path:   "/api/v1/profile", | 				Path:   "/api/v1/profile", | ||||||
|  | @ -265,7 +265,7 @@ func NewPassAccessTokenTest(opts PassAccessTokenTestOptions) *PassAccessTokenTes | ||||||
| 		EmailAddress: email_address, | 		EmailAddress: email_address, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	t.proxy = NewOauthProxy(t.opts, func(email string) bool { | 	t.proxy = NewOAuthProxy(t.opts, func(email string) bool { | ||||||
| 		return email == email_address | 		return email == email_address | ||||||
| 	}) | 	}) | ||||||
| 	return t | 	return t | ||||||
|  | @ -360,7 +360,7 @@ func TestDoNotForwardAccessTokenUpstream(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| type SignInPageTest struct { | type SignInPageTest struct { | ||||||
| 	opts           *Options | 	opts           *Options | ||||||
| 	proxy          *OauthProxy | 	proxy          *OAuthProxy | ||||||
| 	sign_in_regexp *regexp.Regexp | 	sign_in_regexp *regexp.Regexp | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -375,7 +375,7 @@ func NewSignInPageTest() *SignInPageTest { | ||||||
| 	sip_test.opts.ClientSecret = "xyzzyplugh" | 	sip_test.opts.ClientSecret = "xyzzyplugh" | ||||||
| 	sip_test.opts.Validate() | 	sip_test.opts.Validate() | ||||||
| 
 | 
 | ||||||
| 	sip_test.proxy = NewOauthProxy(sip_test.opts, func(email string) bool { | 	sip_test.proxy = NewOAuthProxy(sip_test.opts, func(email string) bool { | ||||||
| 		return true | 		return true | ||||||
| 	}) | 	}) | ||||||
| 	sip_test.sign_in_regexp = regexp.MustCompile(signInRedirectPattern) | 	sip_test.sign_in_regexp = regexp.MustCompile(signInRedirectPattern) | ||||||
|  | @ -425,7 +425,7 @@ func TestSignInPageDirectAccessRedirectsToRoot(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| type ProcessCookieTest struct { | type ProcessCookieTest struct { | ||||||
| 	opts          *Options | 	opts          *Options | ||||||
| 	proxy         *OauthProxy | 	proxy         *OAuthProxy | ||||||
| 	rw            *httptest.ResponseRecorder | 	rw            *httptest.ResponseRecorder | ||||||
| 	req           *http.Request | 	req           *http.Request | ||||||
| 	provider      TestProvider | 	provider      TestProvider | ||||||
|  | @ -449,7 +449,7 @@ func NewProcessCookieTest(opts ProcessCookieTestOpts) *ProcessCookieTest { | ||||||
| 	pc_test.opts.CookieRefresh = time.Hour | 	pc_test.opts.CookieRefresh = time.Hour | ||||||
| 	pc_test.opts.Validate() | 	pc_test.opts.Validate() | ||||||
| 
 | 
 | ||||||
| 	pc_test.proxy = NewOauthProxy(pc_test.opts, func(email string) bool { | 	pc_test.proxy = NewOAuthProxy(pc_test.opts, func(email string) bool { | ||||||
| 		return pc_test.validate_user | 		return pc_test.validate_user | ||||||
| 	}) | 	}) | ||||||
| 	pc_test.proxy.provider = &TestProvider{ | 	pc_test.proxy.provider = &TestProvider{ | ||||||
|  |  | ||||||
							
								
								
									
										36
									
								
								options.go
								
								
								
								
							
							
						
						
									
										36
									
								
								options.go
								
								
								
								
							|  | @ -16,7 +16,7 @@ type Options struct { | ||||||
| 	ProxyPrefix  string `flag:"proxy-prefix" cfg:"proxy-prefix"` | 	ProxyPrefix  string `flag:"proxy-prefix" cfg:"proxy-prefix"` | ||||||
| 	HttpAddress  string `flag:"http-address" cfg:"http_address"` | 	HttpAddress  string `flag:"http-address" cfg:"http_address"` | ||||||
| 	HttpsAddress string `flag:"https-address" cfg:"https_address"` | 	HttpsAddress string `flag:"https-address" cfg:"https_address"` | ||||||
| 	RedirectUrl  string `flag:"redirect-url" cfg:"redirect_url"` | 	RedirectURL  string `flag:"redirect-url" cfg:"redirect_url"` | ||||||
| 	ClientID     string `flag:"client-id" cfg:"client_id" env:"OAUTH2_PROXY_CLIENT_ID"` | 	ClientID     string `flag:"client-id" cfg:"client_id" env:"OAUTH2_PROXY_CLIENT_ID"` | ||||||
| 	ClientSecret string `flag:"client-secret" cfg:"client_secret" env:"OAUTH2_PROXY_CLIENT_SECRET"` | 	ClientSecret string `flag:"client-secret" cfg:"client_secret" env:"OAUTH2_PROXY_CLIENT_SECRET"` | ||||||
| 	TLSCertFile  string `flag:"tls-cert" cfg:"tls_cert_file"` | 	TLSCertFile  string `flag:"tls-cert" cfg:"tls_cert_file"` | ||||||
|  | @ -51,18 +51,18 @@ type Options struct { | ||||||
| 	// These options allow for other providers besides Google, with
 | 	// These options allow for other providers besides Google, with
 | ||||||
| 	// potential overrides.
 | 	// potential overrides.
 | ||||||
| 	Provider       string `flag:"provider" cfg:"provider"` | 	Provider       string `flag:"provider" cfg:"provider"` | ||||||
| 	LoginUrl       string `flag:"login-url" cfg:"login_url"` | 	LoginURL       string `flag:"login-url" cfg:"login_url"` | ||||||
| 	RedeemUrl      string `flag:"redeem-url" cfg:"redeem_url"` | 	RedeemURL      string `flag:"redeem-url" cfg:"redeem_url"` | ||||||
| 	ProfileUrl     string `flag:"profile-url" cfg:"profile_url"` | 	ProfileURL     string `flag:"profile-url" cfg:"profile_url"` | ||||||
| 	ValidateUrl    string `flag:"validate-url" cfg:"validate_url"` | 	ValidateURL    string `flag:"validate-url" cfg:"validate_url"` | ||||||
| 	Scope          string `flag:"scope" cfg:"scope"` | 	Scope          string `flag:"scope" cfg:"scope"` | ||||||
| 	ApprovalPrompt string `flag:"approval-prompt" cfg:"approval_prompt"` | 	ApprovalPrompt string `flag:"approval-prompt" cfg:"approval_prompt"` | ||||||
| 
 | 
 | ||||||
| 	RequestLogging bool `flag:"request-logging" cfg:"request_logging"` | 	RequestLogging bool `flag:"request-logging" cfg:"request_logging"` | ||||||
| 
 | 
 | ||||||
| 	// internal values that are set after config validation
 | 	// internal values that are set after config validation
 | ||||||
| 	redirectUrl   *url.URL | 	redirectURL   *url.URL | ||||||
| 	proxyUrls     []*url.URL | 	proxyURLs     []*url.URL | ||||||
| 	CompiledRegex []*regexp.Regexp | 	CompiledRegex []*regexp.Regexp | ||||||
| 	provider      providers.Provider | 	provider      providers.Provider | ||||||
| } | } | ||||||
|  | @ -86,7 +86,7 @@ func NewOptions() *Options { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func parseUrl(to_parse string, urltype string, msgs []string) (*url.URL, []string) { | func parseURL(to_parse string, urltype string, msgs []string) (*url.URL, []string) { | ||||||
| 	parsed, err := url.Parse(to_parse) | 	parsed, err := url.Parse(to_parse) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, append(msgs, fmt.Sprintf( | 		return nil, append(msgs, fmt.Sprintf( | ||||||
|  | @ -113,19 +113,19 @@ func (o *Options) Validate() error { | ||||||
| 		msgs = append(msgs, "missing setting for email validation: email-domain or authenticated-emails-file required.\n      use email-domain=* to authorize all email addresses") | 		msgs = append(msgs, "missing setting for email validation: email-domain or authenticated-emails-file required.\n      use email-domain=* to authorize all email addresses") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	o.redirectUrl, msgs = parseUrl(o.RedirectUrl, "redirect", msgs) | 	o.redirectURL, msgs = parseURL(o.RedirectURL, "redirect", msgs) | ||||||
| 
 | 
 | ||||||
| 	for _, u := range o.Upstreams { | 	for _, u := range o.Upstreams { | ||||||
| 		upstreamUrl, err := url.Parse(u) | 		upstreamURL, err := url.Parse(u) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			msgs = append(msgs, fmt.Sprintf( | 			msgs = append(msgs, fmt.Sprintf( | ||||||
| 				"error parsing upstream=%q %s", | 				"error parsing upstream=%q %s", | ||||||
| 				upstreamUrl, err)) | 				upstreamURL, err)) | ||||||
| 		} | 		} | ||||||
| 		if upstreamUrl.Path == "" { | 		if upstreamURL.Path == "" { | ||||||
| 			upstreamUrl.Path = "/" | 			upstreamURL.Path = "/" | ||||||
| 		} | 		} | ||||||
| 		o.proxyUrls = append(o.proxyUrls, upstreamUrl) | 		o.proxyURLs = append(o.proxyURLs, upstreamURL) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for _, u := range o.SkipAuthRegex { | 	for _, u := range o.SkipAuthRegex { | ||||||
|  | @ -189,10 +189,10 @@ func parseProviderInfo(o *Options, msgs []string) []string { | ||||||
| 		ClientSecret:   o.ClientSecret, | 		ClientSecret:   o.ClientSecret, | ||||||
| 		ApprovalPrompt: o.ApprovalPrompt, | 		ApprovalPrompt: o.ApprovalPrompt, | ||||||
| 	} | 	} | ||||||
| 	p.LoginUrl, msgs = parseUrl(o.LoginUrl, "login", msgs) | 	p.LoginURL, msgs = parseURL(o.LoginURL, "login", msgs) | ||||||
| 	p.RedeemUrl, msgs = parseUrl(o.RedeemUrl, "redeem", msgs) | 	p.RedeemURL, msgs = parseURL(o.RedeemURL, "redeem", msgs) | ||||||
| 	p.ProfileUrl, msgs = parseUrl(o.ProfileUrl, "profile", msgs) | 	p.ProfileURL, msgs = parseURL(o.ProfileURL, "profile", msgs) | ||||||
| 	p.ValidateUrl, msgs = parseUrl(o.ValidateUrl, "validate", msgs) | 	p.ValidateURL, msgs = parseURL(o.ValidateURL, "validate", msgs) | ||||||
| 
 | 
 | ||||||
| 	o.provider = providers.New(o.Provider, p) | 	o.provider = providers.New(o.Provider, p) | ||||||
| 	switch p := o.provider.(type) { | 	switch p := o.provider.(type) { | ||||||
|  |  | ||||||
|  | @ -73,16 +73,16 @@ func TestInitializedOptions(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| // Note that it's not worth testing nonparseable URLs, since url.Parse()
 | // Note that it's not worth testing nonparseable URLs, since url.Parse()
 | ||||||
| // seems to parse damn near anything.
 | // seems to parse damn near anything.
 | ||||||
| func TestRedirectUrl(t *testing.T) { | func TestRedirectURL(t *testing.T) { | ||||||
| 	o := testOptions() | 	o := testOptions() | ||||||
| 	o.RedirectUrl = "https://myhost.com/oauth2/callback" | 	o.RedirectURL = "https://myhost.com/oauth2/callback" | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| 	expected := &url.URL{ | 	expected := &url.URL{ | ||||||
| 		Scheme: "https", Host: "myhost.com", Path: "/oauth2/callback"} | 		Scheme: "https", Host: "myhost.com", Path: "/oauth2/callback"} | ||||||
| 	assert.Equal(t, expected, o.redirectUrl) | 	assert.Equal(t, expected, o.redirectURL) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestProxyUrls(t *testing.T) { | func TestProxyURLs(t *testing.T) { | ||||||
| 	o := testOptions() | 	o := testOptions() | ||||||
| 	o.Upstreams = append(o.Upstreams, "http://127.0.0.1:8081") | 	o.Upstreams = append(o.Upstreams, "http://127.0.0.1:8081") | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
|  | @ -91,7 +91,7 @@ func TestProxyUrls(t *testing.T) { | ||||||
| 		// note the '/' was added
 | 		// note the '/' was added
 | ||||||
| 		&url.URL{Scheme: "http", Host: "127.0.0.1:8081", Path: "/"}, | 		&url.URL{Scheme: "http", Host: "127.0.0.1:8081", Path: "/"}, | ||||||
| 	} | 	} | ||||||
| 	assert.Equal(t, expected, o.proxyUrls) | 	assert.Equal(t, expected, o.proxyURLs) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestCompiledRegex(t *testing.T) { | func TestCompiledRegex(t *testing.T) { | ||||||
|  | @ -125,10 +125,10 @@ func TestDefaultProviderApiSettings(t *testing.T) { | ||||||
| 	assert.Equal(t, nil, o.Validate()) | 	assert.Equal(t, nil, o.Validate()) | ||||||
| 	p := o.provider.Data() | 	p := o.provider.Data() | ||||||
| 	assert.Equal(t, "https://accounts.google.com/o/oauth2/auth?access_type=offline", | 	assert.Equal(t, "https://accounts.google.com/o/oauth2/auth?access_type=offline", | ||||||
| 		p.LoginUrl.String()) | 		p.LoginURL.String()) | ||||||
| 	assert.Equal(t, "https://www.googleapis.com/oauth2/v3/token", | 	assert.Equal(t, "https://www.googleapis.com/oauth2/v3/token", | ||||||
| 		p.RedeemUrl.String()) | 		p.RedeemURL.String()) | ||||||
| 	assert.Equal(t, "", p.ProfileUrl.String()) | 	assert.Equal(t, "", p.ProfileURL.String()) | ||||||
| 	assert.Equal(t, "profile email", p.Scope) | 	assert.Equal(t, "profile email", p.Scope) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -17,22 +17,22 @@ type GitHubProvider struct { | ||||||
| 
 | 
 | ||||||
| func NewGitHubProvider(p *ProviderData) *GitHubProvider { | func NewGitHubProvider(p *ProviderData) *GitHubProvider { | ||||||
| 	p.ProviderName = "GitHub" | 	p.ProviderName = "GitHub" | ||||||
| 	if p.LoginUrl == nil || p.LoginUrl.String() == "" { | 	if p.LoginURL == nil || p.LoginURL.String() == "" { | ||||||
| 		p.LoginUrl = &url.URL{ | 		p.LoginURL = &url.URL{ | ||||||
| 			Scheme: "https", | 			Scheme: "https", | ||||||
| 			Host:   "github.com", | 			Host:   "github.com", | ||||||
| 			Path:   "/login/oauth/authorize", | 			Path:   "/login/oauth/authorize", | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if p.RedeemUrl == nil || p.RedeemUrl.String() == "" { | 	if p.RedeemURL == nil || p.RedeemURL.String() == "" { | ||||||
| 		p.RedeemUrl = &url.URL{ | 		p.RedeemURL = &url.URL{ | ||||||
| 			Scheme: "https", | 			Scheme: "https", | ||||||
| 			Host:   "github.com", | 			Host:   "github.com", | ||||||
| 			Path:   "/login/oauth/access_token", | 			Path:   "/login/oauth/access_token", | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if p.ValidateUrl == nil || p.ValidateUrl.String() == "" { | 	if p.ValidateURL == nil || p.ValidateURL.String() == "" { | ||||||
| 		p.ValidateUrl = &url.URL{ | 		p.ValidateURL = &url.URL{ | ||||||
| 			Scheme: "https", | 			Scheme: "https", | ||||||
| 			Host:   "api.github.com", | 			Host:   "api.github.com", | ||||||
| 			Path:   "/user/emails", | 			Path:   "/user/emails", | ||||||
|  |  | ||||||
|  | @ -21,7 +21,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| type GoogleProvider struct { | type GoogleProvider struct { | ||||||
| 	*ProviderData | 	*ProviderData | ||||||
| 	RedeemRefreshUrl *url.URL | 	RedeemRefreshURL *url.URL | ||||||
| 	// GroupValidator is a function that determines if the passed email is in
 | 	// GroupValidator is a function that determines if the passed email is in
 | ||||||
| 	// the configured Google group.
 | 	// the configured Google group.
 | ||||||
| 	GroupValidator func(string) bool | 	GroupValidator func(string) bool | ||||||
|  | @ -29,21 +29,21 @@ type GoogleProvider struct { | ||||||
| 
 | 
 | ||||||
| func NewGoogleProvider(p *ProviderData) *GoogleProvider { | func NewGoogleProvider(p *ProviderData) *GoogleProvider { | ||||||
| 	p.ProviderName = "Google" | 	p.ProviderName = "Google" | ||||||
| 	if p.LoginUrl.String() == "" { | 	if p.LoginURL.String() == "" { | ||||||
| 		p.LoginUrl = &url.URL{Scheme: "https", | 		p.LoginURL = &url.URL{Scheme: "https", | ||||||
| 			Host: "accounts.google.com", | 			Host: "accounts.google.com", | ||||||
| 			Path: "/o/oauth2/auth", | 			Path: "/o/oauth2/auth", | ||||||
| 			// to get a refresh token. see https://developers.google.com/identity/protocols/OAuth2WebServer#offline
 | 			// to get a refresh token. see https://developers.google.com/identity/protocols/OAuth2WebServer#offline
 | ||||||
| 			RawQuery: "access_type=offline", | 			RawQuery: "access_type=offline", | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if p.RedeemUrl.String() == "" { | 	if p.RedeemURL.String() == "" { | ||||||
| 		p.RedeemUrl = &url.URL{Scheme: "https", | 		p.RedeemURL = &url.URL{Scheme: "https", | ||||||
| 			Host: "www.googleapis.com", | 			Host: "www.googleapis.com", | ||||||
| 			Path: "/oauth2/v3/token"} | 			Path: "/oauth2/v3/token"} | ||||||
| 	} | 	} | ||||||
| 	if p.ValidateUrl.String() == "" { | 	if p.ValidateURL.String() == "" { | ||||||
| 		p.ValidateUrl = &url.URL{Scheme: "https", | 		p.ValidateURL = &url.URL{Scheme: "https", | ||||||
| 			Host: "www.googleapis.com", | 			Host: "www.googleapis.com", | ||||||
| 			Path: "/oauth2/v1/tokeninfo"} | 			Path: "/oauth2/v1/tokeninfo"} | ||||||
| 	} | 	} | ||||||
|  | @ -96,20 +96,20 @@ func jwtDecodeSegment(seg string) ([]byte, error) { | ||||||
| 	return base64.URLEncoding.DecodeString(seg) | 	return base64.URLEncoding.DecodeString(seg) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (p *GoogleProvider) Redeem(redirectUrl, code string) (s *SessionState, err error) { | func (p *GoogleProvider) Redeem(redirectURL, code string) (s *SessionState, err error) { | ||||||
| 	if code == "" { | 	if code == "" { | ||||||
| 		err = errors.New("missing code") | 		err = errors.New("missing code") | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	params := url.Values{} | 	params := url.Values{} | ||||||
| 	params.Add("redirect_uri", redirectUrl) | 	params.Add("redirect_uri", redirectURL) | ||||||
| 	params.Add("client_id", p.ClientID) | 	params.Add("client_id", p.ClientID) | ||||||
| 	params.Add("client_secret", p.ClientSecret) | 	params.Add("client_secret", p.ClientSecret) | ||||||
| 	params.Add("code", code) | 	params.Add("code", code) | ||||||
| 	params.Add("grant_type", "authorization_code") | 	params.Add("grant_type", "authorization_code") | ||||||
| 	var req *http.Request | 	var req *http.Request | ||||||
| 	req, err = http.NewRequest("POST", p.RedeemUrl.String(), bytes.NewBufferString(params.Encode())) | 	req, err = http.NewRequest("POST", p.RedeemURL.String(), bytes.NewBufferString(params.Encode())) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | @ -127,7 +127,7 @@ func (p *GoogleProvider) Redeem(redirectUrl, code string) (s *SessionState, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if resp.StatusCode != 200 { | 	if resp.StatusCode != 200 { | ||||||
| 		err = fmt.Errorf("got %d from %q %s", resp.StatusCode, p.RedeemUrl.String(), body) | 		err = fmt.Errorf("got %d from %q %s", resp.StatusCode, p.RedeemURL.String(), body) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -281,7 +281,7 @@ func (p *GoogleProvider) redeemRefreshToken(refreshToken string) (token string, | ||||||
| 	params.Add("refresh_token", refreshToken) | 	params.Add("refresh_token", refreshToken) | ||||||
| 	params.Add("grant_type", "refresh_token") | 	params.Add("grant_type", "refresh_token") | ||||||
| 	var req *http.Request | 	var req *http.Request | ||||||
| 	req, err = http.NewRequest("POST", p.RedeemUrl.String(), bytes.NewBufferString(params.Encode())) | 	req, err = http.NewRequest("POST", p.RedeemURL.String(), bytes.NewBufferString(params.Encode())) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | @ -299,7 +299,7 @@ func (p *GoogleProvider) redeemRefreshToken(refreshToken string) (token string, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if resp.StatusCode != 200 { | 	if resp.StatusCode != 200 { | ||||||
| 		err = fmt.Errorf("got %d from %q %s", resp.StatusCode, p.RedeemUrl.String(), body) | 		err = fmt.Errorf("got %d from %q %s", resp.StatusCode, p.RedeemURL.String(), body) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -23,10 +23,10 @@ func newGoogleProvider() *GoogleProvider { | ||||||
| 	return NewGoogleProvider( | 	return NewGoogleProvider( | ||||||
| 		&ProviderData{ | 		&ProviderData{ | ||||||
| 			ProviderName: "", | 			ProviderName: "", | ||||||
| 			LoginUrl:     &url.URL{}, | 			LoginURL:     &url.URL{}, | ||||||
| 			RedeemUrl:    &url.URL{}, | 			RedeemURL:    &url.URL{}, | ||||||
| 			ProfileUrl:   &url.URL{}, | 			ProfileURL:   &url.URL{}, | ||||||
| 			ValidateUrl:  &url.URL{}, | 			ValidateURL:  &url.URL{}, | ||||||
| 			Scope:        ""}) | 			Scope:        ""}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -35,31 +35,31 @@ func TestGoogleProviderDefaults(t *testing.T) { | ||||||
| 	assert.NotEqual(t, nil, p) | 	assert.NotEqual(t, nil, p) | ||||||
| 	assert.Equal(t, "Google", p.Data().ProviderName) | 	assert.Equal(t, "Google", p.Data().ProviderName) | ||||||
| 	assert.Equal(t, "https://accounts.google.com/o/oauth2/auth?access_type=offline", | 	assert.Equal(t, "https://accounts.google.com/o/oauth2/auth?access_type=offline", | ||||||
| 		p.Data().LoginUrl.String()) | 		p.Data().LoginURL.String()) | ||||||
| 	assert.Equal(t, "https://www.googleapis.com/oauth2/v3/token", | 	assert.Equal(t, "https://www.googleapis.com/oauth2/v3/token", | ||||||
| 		p.Data().RedeemUrl.String()) | 		p.Data().RedeemURL.String()) | ||||||
| 	assert.Equal(t, "https://www.googleapis.com/oauth2/v1/tokeninfo", | 	assert.Equal(t, "https://www.googleapis.com/oauth2/v1/tokeninfo", | ||||||
| 		p.Data().ValidateUrl.String()) | 		p.Data().ValidateURL.String()) | ||||||
| 	assert.Equal(t, "", p.Data().ProfileUrl.String()) | 	assert.Equal(t, "", p.Data().ProfileURL.String()) | ||||||
| 	assert.Equal(t, "profile email", p.Data().Scope) | 	assert.Equal(t, "profile email", p.Data().Scope) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestGoogleProviderOverrides(t *testing.T) { | func TestGoogleProviderOverrides(t *testing.T) { | ||||||
| 	p := NewGoogleProvider( | 	p := NewGoogleProvider( | ||||||
| 		&ProviderData{ | 		&ProviderData{ | ||||||
| 			LoginUrl: &url.URL{ | 			LoginURL: &url.URL{ | ||||||
| 				Scheme: "https", | 				Scheme: "https", | ||||||
| 				Host:   "example.com", | 				Host:   "example.com", | ||||||
| 				Path:   "/oauth/auth"}, | 				Path:   "/oauth/auth"}, | ||||||
| 			RedeemUrl: &url.URL{ | 			RedeemURL: &url.URL{ | ||||||
| 				Scheme: "https", | 				Scheme: "https", | ||||||
| 				Host:   "example.com", | 				Host:   "example.com", | ||||||
| 				Path:   "/oauth/token"}, | 				Path:   "/oauth/token"}, | ||||||
| 			ProfileUrl: &url.URL{ | 			ProfileURL: &url.URL{ | ||||||
| 				Scheme: "https", | 				Scheme: "https", | ||||||
| 				Host:   "example.com", | 				Host:   "example.com", | ||||||
| 				Path:   "/oauth/profile"}, | 				Path:   "/oauth/profile"}, | ||||||
| 			ValidateUrl: &url.URL{ | 			ValidateURL: &url.URL{ | ||||||
| 				Scheme: "https", | 				Scheme: "https", | ||||||
| 				Host:   "example.com", | 				Host:   "example.com", | ||||||
| 				Path:   "/oauth/tokeninfo"}, | 				Path:   "/oauth/tokeninfo"}, | ||||||
|  | @ -67,13 +67,13 @@ func TestGoogleProviderOverrides(t *testing.T) { | ||||||
| 	assert.NotEqual(t, nil, p) | 	assert.NotEqual(t, nil, p) | ||||||
| 	assert.Equal(t, "Google", p.Data().ProviderName) | 	assert.Equal(t, "Google", p.Data().ProviderName) | ||||||
| 	assert.Equal(t, "https://example.com/oauth/auth", | 	assert.Equal(t, "https://example.com/oauth/auth", | ||||||
| 		p.Data().LoginUrl.String()) | 		p.Data().LoginURL.String()) | ||||||
| 	assert.Equal(t, "https://example.com/oauth/token", | 	assert.Equal(t, "https://example.com/oauth/token", | ||||||
| 		p.Data().RedeemUrl.String()) | 		p.Data().RedeemURL.String()) | ||||||
| 	assert.Equal(t, "https://example.com/oauth/profile", | 	assert.Equal(t, "https://example.com/oauth/profile", | ||||||
| 		p.Data().ProfileUrl.String()) | 		p.Data().ProfileURL.String()) | ||||||
| 	assert.Equal(t, "https://example.com/oauth/tokeninfo", | 	assert.Equal(t, "https://example.com/oauth/tokeninfo", | ||||||
| 		p.Data().ValidateUrl.String()) | 		p.Data().ValidateURL.String()) | ||||||
| 	assert.Equal(t, "profile", p.Data().Scope) | 	assert.Equal(t, "profile", p.Data().Scope) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -94,7 +94,7 @@ func TestGoogleProviderGetEmailAddress(t *testing.T) { | ||||||
| 	}) | 	}) | ||||||
| 	assert.Equal(t, nil, err) | 	assert.Equal(t, nil, err) | ||||||
| 	var server *httptest.Server | 	var server *httptest.Server | ||||||
| 	p.RedeemUrl, server = newRedeemServer(body) | 	p.RedeemURL, server = newRedeemServer(body) | ||||||
| 	defer server.Close() | 	defer server.Close() | ||||||
| 
 | 
 | ||||||
| 	session, err := p.Redeem("http://redirect/", "code1234") | 	session, err := p.Redeem("http://redirect/", "code1234") | ||||||
|  | @ -131,7 +131,7 @@ func TestGoogleProviderGetEmailAddressInvalidEncoding(t *testing.T) { | ||||||
| 	}) | 	}) | ||||||
| 	assert.Equal(t, nil, err) | 	assert.Equal(t, nil, err) | ||||||
| 	var server *httptest.Server | 	var server *httptest.Server | ||||||
| 	p.RedeemUrl, server = newRedeemServer(body) | 	p.RedeemURL, server = newRedeemServer(body) | ||||||
| 	defer server.Close() | 	defer server.Close() | ||||||
| 
 | 
 | ||||||
| 	session, err := p.Redeem("http://redirect/", "code1234") | 	session, err := p.Redeem("http://redirect/", "code1234") | ||||||
|  | @ -150,7 +150,7 @@ func TestGoogleProviderGetEmailAddressInvalidJson(t *testing.T) { | ||||||
| 	}) | 	}) | ||||||
| 	assert.Equal(t, nil, err) | 	assert.Equal(t, nil, err) | ||||||
| 	var server *httptest.Server | 	var server *httptest.Server | ||||||
| 	p.RedeemUrl, server = newRedeemServer(body) | 	p.RedeemURL, server = newRedeemServer(body) | ||||||
| 	defer server.Close() | 	defer server.Close() | ||||||
| 
 | 
 | ||||||
| 	session, err := p.Redeem("http://redirect/", "code1234") | 	session, err := p.Redeem("http://redirect/", "code1234") | ||||||
|  | @ -169,7 +169,7 @@ func TestGoogleProviderGetEmailAddressEmailMissing(t *testing.T) { | ||||||
| 	}) | 	}) | ||||||
| 	assert.Equal(t, nil, err) | 	assert.Equal(t, nil, err) | ||||||
| 	var server *httptest.Server | 	var server *httptest.Server | ||||||
| 	p.RedeemUrl, server = newRedeemServer(body) | 	p.RedeemURL, server = newRedeemServer(body) | ||||||
| 	defer server.Close() | 	defer server.Close() | ||||||
| 
 | 
 | ||||||
| 	session, err := p.Redeem("http://redirect/", "code1234") | 	session, err := p.Redeem("http://redirect/", "code1234") | ||||||
|  |  | ||||||
|  | @ -11,10 +11,10 @@ import ( | ||||||
| 
 | 
 | ||||||
| // validateToken returns true if token is valid
 | // validateToken returns true if token is valid
 | ||||||
| func validateToken(p Provider, access_token string, header http.Header) bool { | func validateToken(p Provider, access_token string, header http.Header) bool { | ||||||
| 	if access_token == "" || p.Data().ValidateUrl == nil { | 	if access_token == "" || p.Data().ValidateURL == nil { | ||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
| 	endpoint := p.Data().ValidateUrl.String() | 	endpoint := p.Data().ValidateURL.String() | ||||||
| 	if len(header) == 0 { | 	if len(header) == 0 { | ||||||
| 		params := url.Values{"access_token": {access_token}} | 		params := url.Values{"access_token": {access_token}} | ||||||
| 		endpoint = endpoint + "?" + params.Encode() | 		endpoint = endpoint + "?" + params.Encode() | ||||||
|  |  | ||||||
|  | @ -63,7 +63,7 @@ func NewValidateSessionStateTest() *ValidateSessionStateTest { | ||||||
| 	backend_url, _ := url.Parse(vt_test.backend.URL) | 	backend_url, _ := url.Parse(vt_test.backend.URL) | ||||||
| 	vt_test.provider = &ValidateSessionStateTestProvider{ | 	vt_test.provider = &ValidateSessionStateTestProvider{ | ||||||
| 		ProviderData: &ProviderData{ | 		ProviderData: &ProviderData{ | ||||||
| 			ValidateUrl: &url.URL{ | 			ValidateURL: &url.URL{ | ||||||
| 				Scheme: "http", | 				Scheme: "http", | ||||||
| 				Host:   backend_url.Host, | 				Host:   backend_url.Host, | ||||||
| 				Path:   "/oauth/tokeninfo", | 				Path:   "/oauth/tokeninfo", | ||||||
|  | @ -99,10 +99,10 @@ func TestValidateSessionStateEmptyToken(t *testing.T) { | ||||||
| 	assert.Equal(t, false, validateToken(vt_test.provider, "", nil)) | 	assert.Equal(t, false, validateToken(vt_test.provider, "", nil)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestValidateSessionStateEmptyValidateUrl(t *testing.T) { | func TestValidateSessionStateEmptyValidateURL(t *testing.T) { | ||||||
| 	vt_test := NewValidateSessionStateTest() | 	vt_test := NewValidateSessionStateTest() | ||||||
| 	defer vt_test.Close() | 	defer vt_test.Close() | ||||||
| 	vt_test.provider.Data().ValidateUrl = nil | 	vt_test.provider.Data().ValidateURL = nil | ||||||
| 	assert.Equal(t, false, validateToken(vt_test.provider, "foobar", nil)) | 	assert.Equal(t, false, validateToken(vt_test.provider, "foobar", nil)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -15,23 +15,23 @@ type LinkedInProvider struct { | ||||||
| 
 | 
 | ||||||
| func NewLinkedInProvider(p *ProviderData) *LinkedInProvider { | func NewLinkedInProvider(p *ProviderData) *LinkedInProvider { | ||||||
| 	p.ProviderName = "LinkedIn" | 	p.ProviderName = "LinkedIn" | ||||||
| 	if p.LoginUrl.String() == "" { | 	if p.LoginURL.String() == "" { | ||||||
| 		p.LoginUrl = &url.URL{Scheme: "https", | 		p.LoginURL = &url.URL{Scheme: "https", | ||||||
| 			Host: "www.linkedin.com", | 			Host: "www.linkedin.com", | ||||||
| 			Path: "/uas/oauth2/authorization"} | 			Path: "/uas/oauth2/authorization"} | ||||||
| 	} | 	} | ||||||
| 	if p.RedeemUrl.String() == "" { | 	if p.RedeemURL.String() == "" { | ||||||
| 		p.RedeemUrl = &url.URL{Scheme: "https", | 		p.RedeemURL = &url.URL{Scheme: "https", | ||||||
| 			Host: "www.linkedin.com", | 			Host: "www.linkedin.com", | ||||||
| 			Path: "/uas/oauth2/accessToken"} | 			Path: "/uas/oauth2/accessToken"} | ||||||
| 	} | 	} | ||||||
| 	if p.ProfileUrl.String() == "" { | 	if p.ProfileURL.String() == "" { | ||||||
| 		p.ProfileUrl = &url.URL{Scheme: "https", | 		p.ProfileURL = &url.URL{Scheme: "https", | ||||||
| 			Host: "www.linkedin.com", | 			Host: "www.linkedin.com", | ||||||
| 			Path: "/v1/people/~/email-address"} | 			Path: "/v1/people/~/email-address"} | ||||||
| 	} | 	} | ||||||
| 	if p.ValidateUrl.String() == "" { | 	if p.ValidateURL.String() == "" { | ||||||
| 		p.ValidateUrl = p.ProfileUrl | 		p.ValidateURL = p.ProfileURL | ||||||
| 	} | 	} | ||||||
| 	if p.Scope == "" { | 	if p.Scope == "" { | ||||||
| 		p.Scope = "r_emailaddress r_basicprofile" | 		p.Scope = "r_emailaddress r_basicprofile" | ||||||
|  | @ -51,7 +51,7 @@ func (p *LinkedInProvider) GetEmailAddress(s *SessionState) (string, error) { | ||||||
| 	if s.AccessToken == "" { | 	if s.AccessToken == "" { | ||||||
| 		return "", errors.New("missing access token") | 		return "", errors.New("missing access token") | ||||||
| 	} | 	} | ||||||
| 	req, err := http.NewRequest("GET", p.ProfileUrl.String()+"?format=json", nil) | 	req, err := http.NewRequest("GET", p.ProfileURL.String()+"?format=json", nil) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -12,15 +12,15 @@ func testLinkedInProvider(hostname string) *LinkedInProvider { | ||||||
| 	p := NewLinkedInProvider( | 	p := NewLinkedInProvider( | ||||||
| 		&ProviderData{ | 		&ProviderData{ | ||||||
| 			ProviderName: "", | 			ProviderName: "", | ||||||
| 			LoginUrl:     &url.URL{}, | 			LoginURL:     &url.URL{}, | ||||||
| 			RedeemUrl:    &url.URL{}, | 			RedeemURL:    &url.URL{}, | ||||||
| 			ProfileUrl:   &url.URL{}, | 			ProfileURL:   &url.URL{}, | ||||||
| 			ValidateUrl:  &url.URL{}, | 			ValidateURL:  &url.URL{}, | ||||||
| 			Scope:        ""}) | 			Scope:        ""}) | ||||||
| 	if hostname != "" { | 	if hostname != "" { | ||||||
| 		updateUrl(p.Data().LoginUrl, hostname) | 		updateURL(p.Data().LoginURL, hostname) | ||||||
| 		updateUrl(p.Data().RedeemUrl, hostname) | 		updateURL(p.Data().RedeemURL, hostname) | ||||||
| 		updateUrl(p.Data().ProfileUrl, hostname) | 		updateURL(p.Data().ProfileURL, hostname) | ||||||
| 	} | 	} | ||||||
| 	return p | 	return p | ||||||
| } | } | ||||||
|  | @ -47,32 +47,32 @@ func TestLinkedInProviderDefaults(t *testing.T) { | ||||||
| 	assert.NotEqual(t, nil, p) | 	assert.NotEqual(t, nil, p) | ||||||
| 	assert.Equal(t, "LinkedIn", p.Data().ProviderName) | 	assert.Equal(t, "LinkedIn", p.Data().ProviderName) | ||||||
| 	assert.Equal(t, "https://www.linkedin.com/uas/oauth2/authorization", | 	assert.Equal(t, "https://www.linkedin.com/uas/oauth2/authorization", | ||||||
| 		p.Data().LoginUrl.String()) | 		p.Data().LoginURL.String()) | ||||||
| 	assert.Equal(t, "https://www.linkedin.com/uas/oauth2/accessToken", | 	assert.Equal(t, "https://www.linkedin.com/uas/oauth2/accessToken", | ||||||
| 		p.Data().RedeemUrl.String()) | 		p.Data().RedeemURL.String()) | ||||||
| 	assert.Equal(t, "https://www.linkedin.com/v1/people/~/email-address", | 	assert.Equal(t, "https://www.linkedin.com/v1/people/~/email-address", | ||||||
| 		p.Data().ProfileUrl.String()) | 		p.Data().ProfileURL.String()) | ||||||
| 	assert.Equal(t, "https://www.linkedin.com/v1/people/~/email-address", | 	assert.Equal(t, "https://www.linkedin.com/v1/people/~/email-address", | ||||||
| 		p.Data().ValidateUrl.String()) | 		p.Data().ValidateURL.String()) | ||||||
| 	assert.Equal(t, "r_emailaddress r_basicprofile", p.Data().Scope) | 	assert.Equal(t, "r_emailaddress r_basicprofile", p.Data().Scope) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestLinkedInProviderOverrides(t *testing.T) { | func TestLinkedInProviderOverrides(t *testing.T) { | ||||||
| 	p := NewLinkedInProvider( | 	p := NewLinkedInProvider( | ||||||
| 		&ProviderData{ | 		&ProviderData{ | ||||||
| 			LoginUrl: &url.URL{ | 			LoginURL: &url.URL{ | ||||||
| 				Scheme: "https", | 				Scheme: "https", | ||||||
| 				Host:   "example.com", | 				Host:   "example.com", | ||||||
| 				Path:   "/oauth/auth"}, | 				Path:   "/oauth/auth"}, | ||||||
| 			RedeemUrl: &url.URL{ | 			RedeemURL: &url.URL{ | ||||||
| 				Scheme: "https", | 				Scheme: "https", | ||||||
| 				Host:   "example.com", | 				Host:   "example.com", | ||||||
| 				Path:   "/oauth/token"}, | 				Path:   "/oauth/token"}, | ||||||
| 			ProfileUrl: &url.URL{ | 			ProfileURL: &url.URL{ | ||||||
| 				Scheme: "https", | 				Scheme: "https", | ||||||
| 				Host:   "example.com", | 				Host:   "example.com", | ||||||
| 				Path:   "/oauth/profile"}, | 				Path:   "/oauth/profile"}, | ||||||
| 			ValidateUrl: &url.URL{ | 			ValidateURL: &url.URL{ | ||||||
| 				Scheme: "https", | 				Scheme: "https", | ||||||
| 				Host:   "example.com", | 				Host:   "example.com", | ||||||
| 				Path:   "/oauth/tokeninfo"}, | 				Path:   "/oauth/tokeninfo"}, | ||||||
|  | @ -80,13 +80,13 @@ func TestLinkedInProviderOverrides(t *testing.T) { | ||||||
| 	assert.NotEqual(t, nil, p) | 	assert.NotEqual(t, nil, p) | ||||||
| 	assert.Equal(t, "LinkedIn", p.Data().ProviderName) | 	assert.Equal(t, "LinkedIn", p.Data().ProviderName) | ||||||
| 	assert.Equal(t, "https://example.com/oauth/auth", | 	assert.Equal(t, "https://example.com/oauth/auth", | ||||||
| 		p.Data().LoginUrl.String()) | 		p.Data().LoginURL.String()) | ||||||
| 	assert.Equal(t, "https://example.com/oauth/token", | 	assert.Equal(t, "https://example.com/oauth/token", | ||||||
| 		p.Data().RedeemUrl.String()) | 		p.Data().RedeemURL.String()) | ||||||
| 	assert.Equal(t, "https://example.com/oauth/profile", | 	assert.Equal(t, "https://example.com/oauth/profile", | ||||||
| 		p.Data().ProfileUrl.String()) | 		p.Data().ProfileURL.String()) | ||||||
| 	assert.Equal(t, "https://example.com/oauth/tokeninfo", | 	assert.Equal(t, "https://example.com/oauth/tokeninfo", | ||||||
| 		p.Data().ValidateUrl.String()) | 		p.Data().ValidateURL.String()) | ||||||
| 	assert.Equal(t, "profile", p.Data().Scope) | 	assert.Equal(t, "profile", p.Data().Scope) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -16,23 +16,23 @@ func NewMyUsaProvider(p *ProviderData) *MyUsaProvider { | ||||||
| 	const myUsaHost string = "alpha.my.usa.gov" | 	const myUsaHost string = "alpha.my.usa.gov" | ||||||
| 
 | 
 | ||||||
| 	p.ProviderName = "MyUSA" | 	p.ProviderName = "MyUSA" | ||||||
| 	if p.LoginUrl.String() == "" { | 	if p.LoginURL.String() == "" { | ||||||
| 		p.LoginUrl = &url.URL{Scheme: "https", | 		p.LoginURL = &url.URL{Scheme: "https", | ||||||
| 			Host: myUsaHost, | 			Host: myUsaHost, | ||||||
| 			Path: "/oauth/authorize"} | 			Path: "/oauth/authorize"} | ||||||
| 	} | 	} | ||||||
| 	if p.RedeemUrl.String() == "" { | 	if p.RedeemURL.String() == "" { | ||||||
| 		p.RedeemUrl = &url.URL{Scheme: "https", | 		p.RedeemURL = &url.URL{Scheme: "https", | ||||||
| 			Host: myUsaHost, | 			Host: myUsaHost, | ||||||
| 			Path: "/oauth/token"} | 			Path: "/oauth/token"} | ||||||
| 	} | 	} | ||||||
| 	if p.ProfileUrl.String() == "" { | 	if p.ProfileURL.String() == "" { | ||||||
| 		p.ProfileUrl = &url.URL{Scheme: "https", | 		p.ProfileURL = &url.URL{Scheme: "https", | ||||||
| 			Host: myUsaHost, | 			Host: myUsaHost, | ||||||
| 			Path: "/api/v1/profile"} | 			Path: "/api/v1/profile"} | ||||||
| 	} | 	} | ||||||
| 	if p.ValidateUrl.String() == "" { | 	if p.ValidateURL.String() == "" { | ||||||
| 		p.ValidateUrl = &url.URL{Scheme: "https", | 		p.ValidateURL = &url.URL{Scheme: "https", | ||||||
| 			Host: myUsaHost, | 			Host: myUsaHost, | ||||||
| 			Path: "/api/v1/tokeninfo"} | 			Path: "/api/v1/tokeninfo"} | ||||||
| 	} | 	} | ||||||
|  | @ -44,7 +44,7 @@ func NewMyUsaProvider(p *ProviderData) *MyUsaProvider { | ||||||
| 
 | 
 | ||||||
| func (p *MyUsaProvider) GetEmailAddress(s *SessionState) (string, error) { | func (p *MyUsaProvider) GetEmailAddress(s *SessionState) (string, error) { | ||||||
| 	req, err := http.NewRequest("GET", | 	req, err := http.NewRequest("GET", | ||||||
| 		p.ProfileUrl.String()+"?access_token="+s.AccessToken, nil) | 		p.ProfileURL.String()+"?access_token="+s.AccessToken, nil) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Printf("failed building request %s", err) | 		log.Printf("failed building request %s", err) | ||||||
| 		return "", err | 		return "", err | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ import ( | ||||||
| 	"github.com/bmizerany/assert" | 	"github.com/bmizerany/assert" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func updateUrl(url *url.URL, hostname string) { | func updateURL(url *url.URL, hostname string) { | ||||||
| 	url.Scheme = "http" | 	url.Scheme = "http" | ||||||
| 	url.Host = hostname | 	url.Host = hostname | ||||||
| } | } | ||||||
|  | @ -18,16 +18,16 @@ func testMyUsaProvider(hostname string) *MyUsaProvider { | ||||||
| 	p := NewMyUsaProvider( | 	p := NewMyUsaProvider( | ||||||
| 		&ProviderData{ | 		&ProviderData{ | ||||||
| 			ProviderName: "", | 			ProviderName: "", | ||||||
| 			LoginUrl:     &url.URL{}, | 			LoginURL:     &url.URL{}, | ||||||
| 			RedeemUrl:    &url.URL{}, | 			RedeemURL:    &url.URL{}, | ||||||
| 			ProfileUrl:   &url.URL{}, | 			ProfileURL:   &url.URL{}, | ||||||
| 			ValidateUrl:  &url.URL{}, | 			ValidateURL:  &url.URL{}, | ||||||
| 			Scope:        ""}) | 			Scope:        ""}) | ||||||
| 	if hostname != "" { | 	if hostname != "" { | ||||||
| 		updateUrl(p.Data().LoginUrl, hostname) | 		updateURL(p.Data().LoginURL, hostname) | ||||||
| 		updateUrl(p.Data().RedeemUrl, hostname) | 		updateURL(p.Data().RedeemURL, hostname) | ||||||
| 		updateUrl(p.Data().ProfileUrl, hostname) | 		updateURL(p.Data().ProfileURL, hostname) | ||||||
| 		updateUrl(p.Data().ValidateUrl, hostname) | 		updateURL(p.Data().ValidateURL, hostname) | ||||||
| 	} | 	} | ||||||
| 	return p | 	return p | ||||||
| } | } | ||||||
|  | @ -53,32 +53,32 @@ func TestMyUsaProviderDefaults(t *testing.T) { | ||||||
| 	assert.NotEqual(t, nil, p) | 	assert.NotEqual(t, nil, p) | ||||||
| 	assert.Equal(t, "MyUSA", p.Data().ProviderName) | 	assert.Equal(t, "MyUSA", p.Data().ProviderName) | ||||||
| 	assert.Equal(t, "https://alpha.my.usa.gov/oauth/authorize", | 	assert.Equal(t, "https://alpha.my.usa.gov/oauth/authorize", | ||||||
| 		p.Data().LoginUrl.String()) | 		p.Data().LoginURL.String()) | ||||||
| 	assert.Equal(t, "https://alpha.my.usa.gov/oauth/token", | 	assert.Equal(t, "https://alpha.my.usa.gov/oauth/token", | ||||||
| 		p.Data().RedeemUrl.String()) | 		p.Data().RedeemURL.String()) | ||||||
| 	assert.Equal(t, "https://alpha.my.usa.gov/api/v1/profile", | 	assert.Equal(t, "https://alpha.my.usa.gov/api/v1/profile", | ||||||
| 		p.Data().ProfileUrl.String()) | 		p.Data().ProfileURL.String()) | ||||||
| 	assert.Equal(t, "https://alpha.my.usa.gov/api/v1/tokeninfo", | 	assert.Equal(t, "https://alpha.my.usa.gov/api/v1/tokeninfo", | ||||||
| 		p.Data().ValidateUrl.String()) | 		p.Data().ValidateURL.String()) | ||||||
| 	assert.Equal(t, "profile.email", p.Data().Scope) | 	assert.Equal(t, "profile.email", p.Data().Scope) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestMyUsaProviderOverrides(t *testing.T) { | func TestMyUsaProviderOverrides(t *testing.T) { | ||||||
| 	p := NewMyUsaProvider( | 	p := NewMyUsaProvider( | ||||||
| 		&ProviderData{ | 		&ProviderData{ | ||||||
| 			LoginUrl: &url.URL{ | 			LoginURL: &url.URL{ | ||||||
| 				Scheme: "https", | 				Scheme: "https", | ||||||
| 				Host:   "example.com", | 				Host:   "example.com", | ||||||
| 				Path:   "/oauth/auth"}, | 				Path:   "/oauth/auth"}, | ||||||
| 			RedeemUrl: &url.URL{ | 			RedeemURL: &url.URL{ | ||||||
| 				Scheme: "https", | 				Scheme: "https", | ||||||
| 				Host:   "example.com", | 				Host:   "example.com", | ||||||
| 				Path:   "/oauth/token"}, | 				Path:   "/oauth/token"}, | ||||||
| 			ProfileUrl: &url.URL{ | 			ProfileURL: &url.URL{ | ||||||
| 				Scheme: "https", | 				Scheme: "https", | ||||||
| 				Host:   "example.com", | 				Host:   "example.com", | ||||||
| 				Path:   "/oauth/profile"}, | 				Path:   "/oauth/profile"}, | ||||||
| 			ValidateUrl: &url.URL{ | 			ValidateURL: &url.URL{ | ||||||
| 				Scheme: "https", | 				Scheme: "https", | ||||||
| 				Host:   "example.com", | 				Host:   "example.com", | ||||||
| 				Path:   "/oauth/tokeninfo"}, | 				Path:   "/oauth/tokeninfo"}, | ||||||
|  | @ -86,13 +86,13 @@ func TestMyUsaProviderOverrides(t *testing.T) { | ||||||
| 	assert.NotEqual(t, nil, p) | 	assert.NotEqual(t, nil, p) | ||||||
| 	assert.Equal(t, "MyUSA", p.Data().ProviderName) | 	assert.Equal(t, "MyUSA", p.Data().ProviderName) | ||||||
| 	assert.Equal(t, "https://example.com/oauth/auth", | 	assert.Equal(t, "https://example.com/oauth/auth", | ||||||
| 		p.Data().LoginUrl.String()) | 		p.Data().LoginURL.String()) | ||||||
| 	assert.Equal(t, "https://example.com/oauth/token", | 	assert.Equal(t, "https://example.com/oauth/token", | ||||||
| 		p.Data().RedeemUrl.String()) | 		p.Data().RedeemURL.String()) | ||||||
| 	assert.Equal(t, "https://example.com/oauth/profile", | 	assert.Equal(t, "https://example.com/oauth/profile", | ||||||
| 		p.Data().ProfileUrl.String()) | 		p.Data().ProfileURL.String()) | ||||||
| 	assert.Equal(t, "https://example.com/oauth/tokeninfo", | 	assert.Equal(t, "https://example.com/oauth/tokeninfo", | ||||||
| 		p.Data().ValidateUrl.String()) | 		p.Data().ValidateURL.String()) | ||||||
| 	assert.Equal(t, "profile", p.Data().Scope) | 	assert.Equal(t, "profile", p.Data().Scope) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,10 +8,10 @@ type ProviderData struct { | ||||||
| 	ProviderName   string | 	ProviderName   string | ||||||
| 	ClientID       string | 	ClientID       string | ||||||
| 	ClientSecret   string | 	ClientSecret   string | ||||||
| 	LoginUrl       *url.URL | 	LoginURL       *url.URL | ||||||
| 	RedeemUrl      *url.URL | 	RedeemURL      *url.URL | ||||||
| 	ProfileUrl     *url.URL | 	ProfileURL     *url.URL | ||||||
| 	ValidateUrl    *url.URL | 	ValidateURL    *url.URL | ||||||
| 	Scope          string | 	Scope          string | ||||||
| 	ApprovalPrompt string | 	ApprovalPrompt string | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -13,20 +13,20 @@ import ( | ||||||
| 	"github.com/bitly/oauth2_proxy/cookie" | 	"github.com/bitly/oauth2_proxy/cookie" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func (p *ProviderData) Redeem(redirectUrl, code string) (s *SessionState, err error) { | func (p *ProviderData) Redeem(redirectURL, code string) (s *SessionState, err error) { | ||||||
| 	if code == "" { | 	if code == "" { | ||||||
| 		err = errors.New("missing code") | 		err = errors.New("missing code") | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	params := url.Values{} | 	params := url.Values{} | ||||||
| 	params.Add("redirect_uri", redirectUrl) | 	params.Add("redirect_uri", redirectURL) | ||||||
| 	params.Add("client_id", p.ClientID) | 	params.Add("client_id", p.ClientID) | ||||||
| 	params.Add("client_secret", p.ClientSecret) | 	params.Add("client_secret", p.ClientSecret) | ||||||
| 	params.Add("code", code) | 	params.Add("code", code) | ||||||
| 	params.Add("grant_type", "authorization_code") | 	params.Add("grant_type", "authorization_code") | ||||||
| 	var req *http.Request | 	var req *http.Request | ||||||
| 	req, err = http.NewRequest("POST", p.RedeemUrl.String(), bytes.NewBufferString(params.Encode())) | 	req, err = http.NewRequest("POST", p.RedeemURL.String(), bytes.NewBufferString(params.Encode())) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | @ -45,7 +45,7 @@ func (p *ProviderData) Redeem(redirectUrl, code string) (s *SessionState, err er | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if resp.StatusCode != 200 { | 	if resp.StatusCode != 200 { | ||||||
| 		err = fmt.Errorf("got %d from %q %s", resp.StatusCode, p.RedeemUrl.String(), body) | 		err = fmt.Errorf("got %d from %q %s", resp.StatusCode, p.RedeemURL.String(), body) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -77,7 +77,7 @@ func (p *ProviderData) Redeem(redirectUrl, code string) (s *SessionState, err er | ||||||
| // GetLoginURL with typical oauth parameters
 | // GetLoginURL with typical oauth parameters
 | ||||||
| func (p *ProviderData) GetLoginURL(redirectURI, finalRedirect string) string { | func (p *ProviderData) GetLoginURL(redirectURI, finalRedirect string) string { | ||||||
| 	var a url.URL | 	var a url.URL | ||||||
| 	a = *p.LoginUrl | 	a = *p.LoginURL | ||||||
| 	params, _ := url.ParseQuery(a.RawQuery) | 	params, _ := url.ParseQuery(a.RawQuery) | ||||||
| 	params.Set("redirect_uri", redirectURI) | 	params.Set("redirect_uri", redirectURI) | ||||||
| 	params.Set("approval_prompt", p.ApprovalPrompt) | 	params.Set("approval_prompt", p.ApprovalPrompt) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue