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

Forwarding Google OAuth user information through nginx #420

Open
patrickfuller opened this issue Jul 12, 2017 · 7 comments
Open

Forwarding Google OAuth user information through nginx #420

patrickfuller opened this issue Jul 12, 2017 · 7 comments

Comments

@patrickfuller
Copy link

patrickfuller commented Jul 12, 2017

I'm running oauth2_proxy and nginx in two docker containers, and it's working great as an authentication layer. However, I don't know how to reliably forward google user information (full name, profile picture) through to the endpoint.

In my oauth2_proxy config file, I have:

pass_user_headers = true
pass_host_header = true
pass_access_token = true
set_xauthrequest = true

In nginx, I have:

auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
proxy_set_header Host $host;
proxy_set_header X-Email $email;
proxy_set_header X-Real-IP $remote_addr;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;

The user headers help, but are not all the information I'm looking for.

I could GET the desired info with an access token, but the pass_access_token doesn't work as is. Likely because I'm not forwarding it through nginx, but I can't find any documentation on appending the X-Forwarded-Access-Token.

What am I missing?

Thanks,
Pat

@patrickfuller
Copy link
Author

I spent some time looking at this, but haven't gotten anywhere yet. Following the pattern, this should work:

auth_request_set $token $upstream_http_x_forwarded_access_token; 
add_header X-Access-Token $token;

However, it doesn't. The code that sets headers is here, and it looks like it sets differently than X-Auth-Request-*. Is there a reason for this?

@ploxiln
Copy link
Contributor

ploxiln commented Jul 14, 2017

There are two modes in which oauth2_proxy works: original "proxy" mode, and nginx "auth_request" mode. For "proxy" mode, any extra info headers need to be included in the request made to the application, not in the response to the user's browser. In "auth_request" mode, no further request is made, and any extra info headers need to be included in the response to nginx. The option --set-xauthrequest only works for "auth_request" mode while the other --pass-* options only work for "proxy" mode.

In the short term, you could use oauth2_proxy in the original proxy mode.

New options, or new meanings for the existing options, would be needed to pass more information in the response for "auth_request" mode. Perhaps if --set-xauthrequest is enabled, then --pass-access-token should add a response header too. (The other --pass-* appear to be either redundant or inapplicable.)

@patrickfuller
Copy link
Author

Thanks for getting back to me. Could you clarify what's involved with running in original proxy mode? If I have to move away from nginx, then it seems like a lot of config.

However, it seems that I could get around it by patching rw.Header().Set("X-Forwarded-Access-Token", session.AccessToken) here.

More generally, it looks like the proxy already fetches user info from google. Maybe I could grab that and store as a header or cookie?

@ploxiln
Copy link
Contributor

ploxiln commented Jul 15, 2017

"original proxy mode" is often used with nginx as well, and that's even shown in the first diagram: https://github.com/bitly/oauth2_proxy#architecture

These are like lego pieces. You can put either one in front or behind. It's easy.

You could certainly add whatever information you want to response headers. Those changes would just not be likely to be accepted upstream.

@patrickfuller
Copy link
Author

patrickfuller commented Jul 16, 2017

It's likely my own ignorance, but re-ordering the legos seemed like it would be a headache (SSL termination, multiple endpoints, etc.). At least for now, I went the patch route. See below.

Regarding getting accepted upstream, do you think the diff below would be a viable pull request? It's a non-breaking change, and (in my opinion) makes the pass_access_token = true; set_xauthrequest = true config act as expected.

oauth_token.patch

diff --git a/oauthproxy.go b/oauthproxy.go
index dd2b58e..19ed0e3 100644
--- a/oauthproxy.go
+++ b/oauthproxy.go
@@ -680,6 +680,9 @@ func (p *OAuthProxy) Authenticate(rw http.ResponseWriter, req *http.Request) int
 		if session.Email != "" {
 			rw.Header().Set("X-Auth-Request-Email", session.Email)
 		}
+		if p.PassAccessToken && session.AccessToken != "" {
+			rw.Header().Set("X-Auth-Request-Access-Token", session.AccessToken)
+		}
 	}
 	if p.PassAccessToken && session.AccessToken != "" {
 		req.Header["X-Forwarded-Access-Token"] = []string{session.AccessToken}

Dockerfile

FROM golang:latest

# Download oauth2_proxy source
RUN go get -d github.com/bitly/oauth2_proxy
WORKDIR /go/src/github.com/bitly/oauth2_proxy

# Copy over config and patch files
RUN mkdir -p /opt/oauth2-proxy/etc
COPY oauth_token.patch /opt/oauth2-proxy/etc/
COPY oauth2_proxy.conf /opt/oauth2-proxy/etc/

# Patch and build oauth2_proxy
RUN git apply /opt/oauth2-proxy/etc/oauth_token.patch
RUN go install github.com/bitly/oauth2_proxy

# Run the server
CMD oauth2_proxy -config=/opt/oauth2-proxy/etc/oauth2_proxy.conf

nginx.conf

# One of these for each authenticated endpoint
# If you have >3 endpoints, I recommend a pre-processing script
location /$YOUR_ENDPOINT/ {
    # Forwards to authentication proxy
    auth_request /oauth2/auth;
    error_page 401 = /oauth2/sign_in;
    # Once authenticated, sets cookies and headers for upstream parsing
    auth_request_set $email $upstream_http_x_auth_request_email;
    auth_request_set $token $upstream_http_x_auth_request_access_token;
    add_header X-Email $email;
    proxy_set_header X-Access-Token $token;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    auth_request_set $auth_cookie $upstream_http_set_cookie;
    add_header Set-Cookie $auth_cookie;
    # Websocket upgrading
    proxy_http_version 1.1;
    proxy_pass_request_headers on;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_pass http://$FORWARD_ADDRESS;
}

@ploxiln
Copy link
Contributor

ploxiln commented Jul 16, 2017

I think those three lines, to make --set-xauthrequest and --pass-access-token work together if both are enabled, are reasonable. But note that I am not a maintainer of oauth2_proxy.

@patrickfuller
Copy link
Author

I'll make the PR and let the maintainers figure it out. Thanks for the help!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

No branches or pull requests

2 participants