Envoy Oauth2 Filter
A simple sample demonstrating Envoy's Oauth2 Filter.
Basically, this filter will handle all the details for OAuth 2.0 for Web Server Applications and once a user is validated, it will forward the user to the backend application.
Web applications can certainly handle the oauth2 flow (see flask plugin) but this filter manages the sessions for you and after a successful login, provides an HMAC
confirmation that a login happened and optionally the raw access_token
for the user that logged in.
As with the nature of envoy, this configuration will act to do all the legwork for you and present a backend service you run with the user's oauth2 authentication token (i.,e envoy does the whole oauth2 flow for you).
At a high level, its basically
- user access a url handled by envoy
- envoy presents user with oauth2 flow and redirects to google
- user logs into google and is redirected back to envoy
- envoy completes the oauth2 flow and acquires the user's
access_token
. - envoy signs an hmac cookie and sends that to the user along with a redirect to the url requested in
1
- user requests the URL and provides the hmac cookies forward
- envoy verifies the cookies and forwards the requests to the backend server
- backend server verifies the hmac values match and extracts optionally the
access_token
Note, part of this tutorial is inspired by veehaitch@. The enhancement i added is to do hmac validation.
Setup
This tutorial runs envoy and backend server locally for testing. Envoy will run on port :8081
while the backend server on :8082
, both over TLS.
Configure client_id/secret
The first step is to configure an oauth2 client_id
and client_secret
. For google cloud, configure one here.
For this tutorial, you can set the Authorized Redirect Uri
value to https://envoy.esodemoapp2.com:8081
.
Note, I've setup DNS resolution on that domain to point back to "localhost" (which is where this tutorial takes place and where envoy and backend servers run)
$ nslookup envoy.esodemoapp2.com 8.8.8.8
Name: envoy.esodemoapp2.com
Address: 127.0.0.1
$ nslookup backend.esodemoapp2.com 8.8.8.8
Name: backend.esodemoapp2.com
Address: 127.0.0.1
Once you have the client_id
and secret
,
for the client_id
, edit proxy.yaml
and set the value:
credentials:
client_id: "248066739582-h498t6035hm9lvp5u9jelm8i67rp43vq.apps.googleusercontent.com"
for the client_secret
, edit token-secret.yaml
file and enter it in there
also note, the HMAC secret is also specified in a file appropriately named hmac-secret.yaml
The token-secret
, client_id
and client_secret
are now all set
Start Envoy
First get the latest envoy binary:
docker cp `docker create envoyproxy/envoy-dev:latest`:/usr/local/bin/envoy .
Then just run envoy
./envoy --base-id 0 -c envoy.yaml
Start backend service
Now run the backend service webserver
go run main.go --validateUser
In an incognito browser, goto
This will redirect you back to google oauth2 login screens where you can login.
Once logged in, you'll get redirected back though envoy and ultimately to the backend service.
THe backend service will receive the following
OauthExpires
: when this cookie expiresHost
: the standard host headerBearerToken
: this is the raw oauth2access_token
. This value is optionally enabled using theforward_bearer_token: true
flag inproxy.yaml
OauthHMAC
: the hmac ofhmac(OauthExpiresHostBearerToken)
The backend service will verify the HMAC cookies sent by envoy using the shared secret value that envoy was setup with. In other words, the backend service should extract the cookies and host header and perform the same HMAC and check the authenticity of the provided cookie.
The provided backend service does one optional flow as well: it uses oauth2 tokeninfo endpoint to determine who the user is
You can also terminate envoy's session by invoking the /signout
url at anytime. This will invalidate all the cookies.
One more thing to note, while users can use any system to perform oauth2 flows, Scopes are restricted or sensitive. In other words, you can't just ask a user for their cloud-platform
enabled access_token
and start doing stuff.