Skipper: Support OAuth2 Authorization Code Grant Flow

Created on 26 Jul 2019  路  14Comments  路  Source: zalando/skipper

It would be great if Skipper could support OAuth2 Authorization Code Grant Flow with a new filter (name TBD). It would be ideal to support reading the OAuth2 client credentials from a given Kubernetes secret (if Skipper is running on Kubernetes).

Having this in Skipper Ingress would reduce the work load necessary for frontend applications to expose their UI behind OAuth 2 login. This would for example make it very easy to expose some standard nginx pods behind Ingress+OAuth2.

enhancement

All 14 comments

@hjacobs yes I agree, but I would rather integrate with files, such that the filter config can pass a file and we have one volume that mounts all the relevant secrets. The good thing with files is that we already have a secrets package that can read and rotate secrets and we can integrate this with projected volumes https://kubernetes.io/docs/concepts/storage/volumes/#projected .
Needs to be tested, but sounds like the best plan to support all dataclients and rotate secrets.

@hjacobs I have a basic implementation for the implicit flow... intend to take this forward to build a out-of-the-box plugin for skipper for implicit & code auth flows:
https://chat.google.com/room/AAAAGhZzIdU/h8RbfCADNpI

    zalando.org/skipper-filter: flowId("reuse") -> lua("function request(c, p); c.request.header['authorization']=string.match(c.request.header['cookie'],
      '[Aa]uthorization=([Bb]earer [%w%-%.%_%~%+%/]+);*'); end") -> oauthTokeninfoAnyScope("uid")
      -> forwardToken("X-TokenInfo-Forward")
    zalando.org/skipper-predicate: Cookie("authorization", /^[Bb]earer [\w\-\.\_\~\+\/]+$/)
    zalando.org/skipper-routes: "triggerAuthFlow: Path(\"/oauth2/authorize\") -> redirectTo(302,\n\
      \ \"https://sandbox.identity.zalando.com/oauth2/authorize?business_partner_id=810d1d00-4312-43e5-bd31-d8373fdd24c7&client_id=credprov-pyconstrictor-pyconstrictor&response_type=token\"\
      )\n  -> <shunt>;\npersistAuthorization: Path(\"/oauth2/authorized\") -> inlineContent(\"\
      <script>document.cookie='authorization=Bearer ' + (/access_token=(?<access_token>[\\\
      w\\-\\.\\_\\~\\+\\/]+)&*/.exec(window.location.hash).groups.access_token) +\
      \ '; max-age=' + /expires_in=(?<expires_in>[\\d]+)&*/.exec(window.location.hash).groups.expires_in\
      \ + '; path=/'</script>\") -> <shunt>;\n redirectToAuth: * -> redirectTo(302,\
      \ \"/oauth2/authorize\") -> <shunt>;\nrejectAuthHeader: HeaderRegexp(\"authorization\"\
      , /^[Bb]earer [\\w\\-\\.\\_\\~\\+\\/]+$/) -> <shunt>;\n"

following :)

@ancelotpinto provided lua code for https://github.com/zalando/skipper/issues/624

Trying to pretty format the snippet WIP, there are too many escape chars need to test. Draft version:

zalando.org/skipper-filter: |-
  flowId("reuse") 
  -> lua("function request(c, p); c.request.header['authorization']=string.match(c.request.header['cookie'],
      '[Aa]uthorization=([Bb]earer [%w%-%.%_%~%+%/]+);*'); end") 
  -> oauthTokeninfoAnyScope("uid")
  -> forwardToken("X-TokenInfo-Forward")

zalando.org/skipper-predicate: |-
  Cookie("authorization", /^[Bb]earer [\w\-\.\_\~\+\/]+$/)

zalando.org/skipper-routes: |
  triggerAuthFlow: Path("/oauth2/authorize")
                   -> redirectTo(302, "https://sandbox.identity.zalando.com/oauth2/authorize?business_partner_id=810d1d00-4312-43e5-bd31-d8373fdd24c7&client_id=<CLIENT-ID>&response_type=token")
                   -> <shunt>;
  persistAuthorization: Path("/oauth2/authorized") 
                        -> inlineContent("<script>document.cookie='authorization=Bearer ' + (/access_token=(?<access_token>[\w\-\.\_\~\+\/]+)&*/.exec(window.location.hash).groups.access_token) +\
      \ '; max-age=' + /expires_in=(?<expires_in>[\\d]+)&*/.exec(window.location.hash).groups.expires_in\
      \ + '; path=/'</script>\")
                        -> <shunt>;
  redirectToAuth: *
                  -> redirectTo(302, "/oauth2/authorize")
                  -> <shunt>;

  rejectAuthHeader: HeaderRegexp("authorization", /^[Bb]earer [\w\-\.\_\~\+\/]+$/)
                    -> <shunt>;

@ancelotpinto
you can use use "Set-Cookie" to avoid javascript code.

Yes it's possible, I was hoping to write it again in Go to avoid the penalty of Lua.

Should be started with it soon.

@AlexanderYastrebov this is public GH, don鈥檛 leak internal URLs, please.
The other thing is that implicit flow is another issue tracked there https://github.com/zalando/skipper/issues/624

@gchudnov
According to https://tools.ietf.org/html/rfc6749#section-10.3

When using the implicit grant type, the access token is transmitted
in the URI fragment, which can expose it to unauthorized parties.

therefore javascript is required to pull it from location hash as skipper never sees location hash returned by auth server

yes, got it.
thank you for the information.

I see some work went in to this in #1387 - any chance you might come back to it soon @aryszka ?

@soceanainn thanks for asking! I would like to pick it up as soon as possible, but unfortunately, I currently cannot tell when, yet.

Was this page helpful?
0 / 5 - 0 ratings