func (st *SignatureTest) MakeRequestWithExpectedKey(method, body, key string) { err := st.opts.Validate() if err != nil { panic(err) } proxy := NewOAuthProxy(st.opts, func(email string) bool { return true }) var bodyBuf io.ReadCloser if body != "" { bodyBuf = ioutil.NopCloser(&fakeNetConn{reqBody: body}) } req, err := http.NewRequest(method, "/foo/bar", bodyBuf) if err != nil { panic(err) } req.Header = st.header state := &providers.SessionState{ Email: "*****@*****.**", AccessToken: "my_access_token"} value, err := proxy.provider.CookieForSession(state, proxy.CookieCipher) if err != nil { panic(err) } cookie := proxy.MakeCookie(req, value, proxy.CookieExpire, time.Now()) req.AddCookie(cookie) // This is used by the upstream to validate the signature. st.authenticator.auth = hmacauth.NewHmacAuth( crypto.SHA1, []byte(key), SignatureHeader, SignatureHeaders) proxy.ServeHTTP(st.rw, req) }
// NewHTTPProxyHandler returns a http.Handler and its description based on the // configuration specified in opts. func NewHTTPProxyHandler(opts *HmacProxyOpts) ( handler http.Handler, description string) { auth := hmacauth.NewHmacAuth(opts.Digest.ID, []byte(opts.Secret), opts.SignHeader, opts.Headers) switch opts.Mode { case HandlerSignAndProxy: return signAndProxyHandler(auth, &opts.Upstream) case HandlerAuthAndProxy: return authAndProxyHandler(auth, &opts.Upstream) case HandlerAuthForFiles: return authForFilesHandler(auth, opts.FileRoot) case HandlerAuthOnly: return authenticationOnlyHandler(auth) } log.Fatalf("unknown mode: %d\n", opts.Mode) return }
func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy { serveMux := http.NewServeMux() var auth hmacauth.HmacAuth if sigData := opts.signatureData; sigData != nil { auth = hmacauth.NewHmacAuth(sigData.hash, []byte(sigData.key), SignatureHeader, SignatureHeaders) } for _, u := range opts.proxyURLs { path := u.Path switch u.Scheme { case "http", "https": u.Path = "" log.Printf("mapping path %q => upstream %q", path, u) proxy := NewReverseProxy(u) if !opts.PassHostHeader { setProxyUpstreamHostHeader(proxy, u) } else { setProxyDirector(proxy) } serveMux.Handle(path, &UpstreamProxy{u.Host, proxy, auth}) case "file": if u.Fragment != "" { path = u.Fragment } log.Printf("mapping path %q => file system %q", path, u.Path) proxy := NewFileServer(path, u.Path) serveMux.Handle(path, &UpstreamProxy{path, proxy, nil}) default: panic(fmt.Sprintf("unknown upstream protocol %s", u.Scheme)) } } for _, u := range opts.CompiledRegex { log.Printf("compiled skip-auth-regex => %q", u) } redirectURL := opts.redirectURL redirectURL.Path = fmt.Sprintf("%s/callback", opts.ProxyPrefix) log.Printf("OAuthProxy configured for %s Client ID: %s", opts.provider.Data().ProviderName, opts.ClientID) domain := opts.CookieDomain if domain == "" { domain = "<default>" } refresh := "disabled" if opts.CookieRefresh != time.Duration(0) { refresh = fmt.Sprintf("after %s", opts.CookieRefresh) } log.Printf("Cookie settings: name:%s secure(https):%v httponly:%v expiry:%s domain:%s refresh:%s", opts.CookieName, opts.CookieSecure, opts.CookieHttpOnly, opts.CookieExpire, domain, refresh) var cipher *cookie.Cipher if opts.PassAccessToken || (opts.CookieRefresh != time.Duration(0)) { var err error cipher, err = cookie.NewCipher(opts.CookieSecret) if err != nil { log.Fatal("error creating AES cipher with "+ "cookie-secret ", opts.CookieSecret, ": ", err) } } return &OAuthProxy{ CookieName: opts.CookieName, CookieSeed: opts.CookieSecret, CookieDomain: opts.CookieDomain, CookieSecure: opts.CookieSecure, CookieHttpOnly: opts.CookieHttpOnly, CookieExpire: opts.CookieExpire, CookieRefresh: opts.CookieRefresh, Validator: validator, RobotsPath: "/robots.txt", PingPath: "/ping", SignInPath: fmt.Sprintf("%s/sign_in", opts.ProxyPrefix), OAuthStartPath: fmt.Sprintf("%s/start", opts.ProxyPrefix), 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, PassUserHeaders: opts.PassUserHeaders, BasicAuthPassword: opts.BasicAuthPassword, PassAccessToken: opts.PassAccessToken, CookieCipher: cipher, templates: loadTemplates(opts.CustomTemplatesDir), } }