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

Add Authorization: Bearer <jwt> as an optional header from OIDC style providers #530

Closed
JoelSpeed opened this issue Jan 24, 2018 · 10 comments

Comments

@JoelSpeed
Copy link
Contributor

I've come across several applications/apis Authorization: Bearer <jwt> as a header for authentication, a major one of these being Kubernetes and the Kubernetes Dashboard.

I have my own copy of this repo where the OIDC provider returns the raw IdToken instead of the Access token to put in front of Kubernetes, but I did this quickly and in a hacky way. I'd like to make it proper and provide the functionality upstream.

I would like to propose the addition of pass-authorization-header and set-authorization-header flags to the OAuth Proxy. The effect of which would be similar to the pass-access-token and set-x-auth-request flags respectively.

The effect of this would be, that for certain providers, where the login process generates an IdToken (can see this in the OIDC provider and Google providers for instance), then the proxy would add a header to the proxied requests/auth requests of Authorization: Bearer <IdToken>.

To do this, you could add an IdToken field to the SessionState object.

type SessionState struct {
AccessToken string

Then providers such as the OIDC provider and the Google provider could set this field during the Redeem method and then the proxy could set the headers in a very similar way to the below snippet

oauth2_proxy/oauthproxy.go

Lines 698 to 700 in ae49c7d

if p.PassAccessToken && session.AccessToken != "" {
req.Header["X-Forwarded-Access-Token"] = []string{session.AccessToken}
}

I don't know too much about how the other providers work, but they may well also be able to set Authorization headers in a similar way.

If you think this is a worthwhile and a reasonable approach, I will start working on a PR.

@mmerrill3
Copy link

mmerrill3 commented Jan 25, 2018

We too have extended oauth2_proxy to do the same function for the dashboard. It would be nice to have this in the upstream version of oauth2_proxy. In addition, we implemented an endpoint inside the oauth2_proxy called exchangeCookie, which takes the cookie presented, authorizes it, and returns the oidc id token, access_token, refresh_token (if there), and expire_in field as part of a json response.
What this allows us to do is to tie kubectl into the same oidc issuer that the dashboard uses. We've extended another project (k8s-oidc-helper) to call the new oauth2_proxy exchangeCookie endpoint to get the oidc id_token to set in the local kube configuration for kubectl.

@JoelSpeed
Copy link
Contributor Author

@mmerrill3 Have you got a link to your branch with this implementation?

I've also created an internal tool similar to the k8s-oidc-helper, but that doesn't use the oauthproxy at all, it hooks straight to the upstream OIDC provider which for us is Dex.

There is a PR open in the core Kubernetes codebase you might be interested in following, they're trying to make kubectl perform the OIDC login's directly.

kubernetes/kubernetes#55514

@mmerrill3
Copy link

Hi @JoelSpeed , thanks for the link. Here is where I implemented the new endpoint for oauth2_proxy:

https://github.com/mmerrill3/oauth2_proxy/tree/feature/id_token

@JoelSpeed
Copy link
Contributor Author

I'll try and raise a PR over the weekend

@JoelSpeed
Copy link
Contributor Author

@mmerrill3 @gtaylor I've raised a PR #534 which includes this work. It also includes an attempt at a fix for overflowing the 4kb limit of a single cookie.

Used Azure as my OIDC provider and it turns out the JWTs they issue are massive compared to what Google or Dex provide. It is unlikely, however possible, that the tokens will ever get that big from a normal OIDC provider, but I've added the support anyway. Stops someone later on wondering why their cookies are being silently dropped (The go http library drops them without an error if they overflow the 4kb limit)

@mmerrill3 Did you ever see any cookie size issues with your implementation?

@gtaylor
Copy link

gtaylor commented Jan 29, 2018

Awesome! Thanks, @JoelSpeed!

@hafe
Copy link

hafe commented Jan 31, 2018

I also have the same type of changes locally and would love to see this

@mmerrill3
Copy link

@JoelSpeed , I didn't see any issues with the cookie size when using google as my oidc provider. Thanks for the pull request!

@yveszoundi
Copy link

One question, is oauth2-proxy also able to identify externally obtained tokens and let requests pass/go through (Authorization header)?

For a "simple" realistic scenario, let's assume Github as provider and a Kubernetes deployed app.

  1. I login to Github via curl and I get an access token (Authorization: token xxxxxxx" -> for Github) -> More likely from an Angular facing client app

  2. I decide to protect one ingress resource via external authentication with oauth2-proxy with the relevant bits below

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: veryimportant-confidential-data-ingress
  namespace: extraordinary-financial-data-ns
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/auth-url: "https://api.com/oauth2/auth"
   ....................blablalblala omitted.........................

Let's assume that oauth2-proxy has no redirect bugs, all good when I hit a protected url in the browser

  1. Let's try to hit the same URL from another application (web, curl, console app, etc.)
    Is some kind of authorization header recognized by oauth2-proxy as valid?
    GET http://api.com/veryimportant/users/1/accounts/1
    Authorization: token xxxxxxxx

I'm getting some 403 errors here with the following relevant oauth2-proxy settings (valid github token).

pass-access-token=true
pass-user-headers=true
set-authorization-header=true
pass-authorization-header=true

Is it a scenario that you've used or tested yourself, with oauth2-proxy? I was conducting initial experiments with Github prior trying couple of things with Azure AD.

In my particular use case if oauth2-proxy block/allow unauthorized requests upfront that's better. the individual "secured apps" would just do "whatever" they need to do with the token itself to extract more info.

@yveszoundi
Copy link

Just answering my own question, it's apparently not supported by oauth2-proxy:

  • I wrote (copy/paste really) a simple java app (oauth client) in order to obtain a Bearer token "externally"
  • I then used a browser extension to present the "Bearer" authorization header in chrome.
  • All the entry points protected by oauth2-proxy don't really seem to care about the HTTP authorization header

My java application is more or less a much smaller oauth2-proxy with a barebone UI to initiate the authentication workflows. I could probably tweak it to do more and become aware of the "Authorization" header

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

Successfully merging a pull request may close this issue.

5 participants