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

Commit

Permalink
Sign Upstream requests with HMAC. closes #147
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike Bland authored and jehiah committed Nov 16, 2015
1 parent 7c241ec commit e4626c1
Show file tree
Hide file tree
Showing 7 changed files with 298 additions and 69 deletions.
1 change: 1 addition & 0 deletions Godeps
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
github.com/18F/hmacauth 1.0.1
github.com/BurntSushi/toml 3883ac1ce943878302255f538fce319d23226223
github.com/bitly/go-simplejson 3378bdcb5cebedcbf8b5750edee28010f128fe24
github.com/mreiferson/go-options ee94b57f2fbf116075426f853e5abbcdfeca8b3d
Expand Down
29 changes: 23 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,16 @@ An example [oauth2_proxy.cfg](contrib/oauth2_proxy.cfg.example) config file is i

```
Usage of oauth2_proxy:
-approval_prompt="force": Oauth approval_prompt
-approval-prompt="force": Oauth approval_prompt
-authenticated-emails-file="": authenticate against emails via file (one per line)
-basic-auth-password="": the password to set when passing the HTTP Basic Auth header
-client-id="": the OAuth Client ID: ie: "123456.apps.googleusercontent.com"
-client-secret="": the OAuth Client Secret
-config="": path to config file
-cookie-domain="": an optional cookie domain to force cookies to (ie: .yourcompany.com)*
-cookie-expire=168h0m0s: expire timeframe for cookie
-cookie-httponly=true: set HttpOnly cookie flag
-cookie-key="_oauth2_proxy": the name of the cookie that the oauth_proxy creates
-cookie-name="_oauth2_proxy": the name of the cookie that the oauth_proxy creates
-cookie-refresh=0: refresh the cookie after this duration; 0 to disable
-cookie-secret="": the seed string for secure cookies
-cookie-secure=true: set secure (HTTPS) cookie flag
Expand All @@ -130,17 +131,15 @@ Usage of oauth2_proxy:
-email-domain=: authenticate emails with the specified domain (may be given multiple times). Use * to authenticate any email
-github-org="": restrict logins to members of this organisation
-github-team="": restrict logins to members of this team
-google-group="": restrict logins to members of this google group
-google-admin-email="": the google admin to impersonate for api calls
-google-group=: restrict logins to members of this google group (may be given multiple times).
-google-service-account-json="": the path to the service account json credentials
-htpasswd-file="": additionally authenticate against a htpasswd file. Entries must be created with "htpasswd -s" for SHA encryption
-http-address="127.0.0.1:4180": [http://]<addr>:<port> or unix://<path> to listen on for HTTP clients
-https-address=":443": <addr>:<port> to listen on for HTTPS clients
-login-url="": Authentication endpoint
-pass-access-token=false: pass OAuth access_token to upstream via X-Forwarded-Access-Token header
-pass-basic-auth=true: pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream
-basic-auth-password="": the password to set when passing the HTTP Basic Auth header
-pass-host-header=true: pass the request Host Header to upstream
-profile-url="": Profile access endpoint
-provider="google": OAuth provider
Expand All @@ -149,6 +148,7 @@ Usage of oauth2_proxy:
-redirect-url="": the OAuth Redirect URL. ie: "https://internalapp.yourcompany.com/oauth2/callback"
-request-logging=true: Log requests to stdout
-scope="": Oauth scope specification
-signature-key="": GAP-Signature request signature key (algorithm:secretkey)
-skip-auth-regex=: bypass authentication for requests path's that match (may be given multiple times)
-tls-cert="": path to certificate file
-tls-key="": path to private key file
Expand Down Expand Up @@ -250,6 +250,24 @@ OAuth2 Proxy responds directly to the following endpoints. All other endpoints w
* /oauth2/callback - the URL used at the end of the OAuth cycle. The oauth app will be configured with this as the callback url.
* /oauth2/auth - only returns a 202 Accepted response or a 401 Unauthorized response; for use with the [Nginx `auth_request` directive](#nginx-auth-request)

## Request signatures

If `signature_key` is defined, proxied requests will be signed with the
`GAP-Signature` header, which is a [Hash-based Message Authentication Code
(HMAC)](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code)
of selected request information and the request body [see `SIGNATURE_HEADERS`
in `oauthproxy.go`](./oauthproxy.go).

`signature_key` must be of the form `algorithm:secretkey`, (ie: `signature_key = "sha1:secret0"`)

For more information about HMAC request signature validation, read the
following:

* [Amazon Web Services: Signing and Authenticating REST
Requests](https://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html)
* [rc3.org: Using HMAC to authenticate Web service
requests](http://rc3.org/2011/12/02/using-hmac-to-authenticate-web-service-requests/)

## Logging Format

OAuth2 Proxy logs requests to stdout in a format similar to Apache Combined Log.
Expand All @@ -258,7 +276,6 @@ OAuth2 Proxy logs requests to stdout in a format similar to Apache Combined Log.
<REMOTE_ADDRESS> - <[email protected]> [19/Mar/2015:17:20:19 -0400] <HOST_HEADER> GET <UPSTREAM_HOST> "/path/" HTTP/1.1 "<USER_AGENT>" <RESPONSE_CODE> <RESPONSE_BYTES> <REQUEST_DURATION>
```


## Adding a new Provider

Follow the examples in the [`providers` package](providers/) to define a new
Expand Down
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ func main() {
flagSet.String("scope", "", "OAuth scope specification")
flagSet.String("approval-prompt", "force", "OAuth approval_prompt")

flagSet.String("signature-key", "", "GAP-Signature request signature key (algorithm:secretkey)")

flagSet.Parse(os.Args[1:])

if *showVersion {
Expand Down
31 changes: 29 additions & 2 deletions oauthproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,26 @@ import (
"strings"
"time"

"github.com/18F/hmacauth"
"github.com/bitly/oauth2_proxy/cookie"
"github.com/bitly/oauth2_proxy/providers"
)

const SignatureHeader = "GAP-Signature"

var SignatureHeaders []string = []string{
"Content-Length",
"Content-Md5",
"Content-Type",
"Date",
"Authorization",
"X-Forwarded-User",
"X-Forwarded-Email",
"X-Forwarded-Access-Token",
"Cookie",
"Gap-Auth",
}

type OAuthProxy struct {
CookieSeed string
CookieName string
Expand Down Expand Up @@ -54,10 +70,15 @@ type OAuthProxy struct {
type UpstreamProxy struct {
upstream string
handler http.Handler
auth hmacauth.HmacAuth
}

func (u *UpstreamProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("GAP-Upstream-Address", u.upstream)
if u.auth != nil {
r.Header.Set("GAP-Auth", w.Header().Get("GAP-Auth"))
u.auth.SignRequest(r)
}
u.handler.ServeHTTP(w, r)
}

Expand Down Expand Up @@ -89,6 +110,11 @@ func NewFileServer(path string, filesystemPath string) (proxy http.Handler) {

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 {
Expand All @@ -101,14 +127,15 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
} else {
setProxyDirector(proxy)
}
serveMux.Handle(path, &UpstreamProxy{u.Host, 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})
serveMux.Handle(path, &UpstreamProxy{path, proxy, nil})
default:
panic(fmt.Sprintf("unknown upstream protocol %s", u.Scheme))
}
Expand Down
Loading

0 comments on commit e4626c1

Please sign in to comment.