nokia / kong-oidc

OIDC plugin for Kong
Apache License 2.0
454 stars 321 forks source link

Few Q's for yah on OIDC #53

Closed jeremyjpj0916 closed 6 years ago

jeremyjpj0916 commented 6 years ago

@Trojan295 Hey, we have chatted in the past and I felt like circling back to this plugin to discuss a few points with your OIDC implementation vs our current implementations. I may end up using this plugin in a few circumstances for sure! Our current code base for reference: https://github.com/Optum/kong-oidc-auth

Now onto some q's:

  1. So when that first transaction comes through, user in browser hits gateway, then gateway recognizes no session/cookie. Next steps is to redirect over to your authorize url provided by the IDP(ping federate) in our case. Do the dance, and then userInfo comes back to the gateway. gateway preps that info to send to backend api service. Now in the response DUE to the redirect that occurred to the IDP the raw data payload from that back-end would be spat out to a users browser rather than to the SPA(Single Page Application) that initiated the call in the first place. Now our fix to get around that was after that first authentication takes place with a user we do a redirect back to a users "dashboard" page with their application. Then at this point subsequent calls will have the users cookie attached on calls and no redirection occurs and its a simple proxy transaction to the back-end so the SPA gets the data back and opposed to the users browser getting redirected around.

Our param for this was:

app_login_redirect_url

Did you solve this situation in a similar manner?

I am also just wondering what other flows/use cases there are besides SPA applications, is there ever a circumstance where the application won't need that redirect_url on the first proxy since OIDC is always a user browser driven event?

  1. I see you have a few varieties of cache mechanisms on the readme, how are these configured?

    shared-memory|memcache|redis.

    I did not see anything in the plugin schema to pick between them? In our implementation we enable caching to the Kong singletons shm I am sure you have familiarized yourself with :) . Where we just do a key-> value of cookie->userInfo returned from the IDP for lookup on subsequent proxy calls.

  2. Does your implementation call out to the IDP frequently to get that userInfo back or is it a one time thing generally where you cache the userInfo as well for a set ___ amount of time? I feel caching the info is important as it would be inefficient to call the userInfo endpoint every time.

  3. I have been pondering a neat idea for OIDC with Kong, not sure if Nokia has this use case but consider a proxy that could be fronted by multiple OIDC IDP's. We for instance have a requirement that a special header value is passed then we need to use a different oidc provider, any chance you can point me to the meat of the code(file/line number) where I could add that if header = ___ value check use this IDP /.well-known/... endpoint?

Overall just circling back to this plugin the more I understand Kong + OIDC this Nokia plugin is impressive! I like the idea of just passing the /.well-known/... endpoint to resolve all these other details. For the longest time our IDP internally didn't mention they had such an endpoint so our code base requires explicitly setting those hah. We also went the route of not having a library dependency mainly because we have to explicitly set a few things our IDP requires such as "pfidpadapterid" for environment staging, and there are some weird query params we have been provided to play with such as "&prompt=none" which will look into if there is already another session established from other internal IDPs it auto-logs users in without requiring user action.

Thanks! -Jeremy

Trojan295 commented 6 years ago
  1. In case of SPA's we implemented the introspection feature, but it's not really a SSO solution. You can set the config introspection_endpoint and authenticate your application directly with the IDP using the Implicit grant and put the JWT token in the Authorization header. You loose a bit of the SSO, though. You can check #54, for support of other grant types.

  2. To be honest I don't know who put that information there... The only mechanism we have here is storing the tokens in an encrypted cookie on the browser side. The underlying plugin support the other ones (https://github.com/zmartzone/lua-resty-openidc), but we don't have in the plugin option to configure them. I believe you could change it, by modifying the nginx.conf, but... what's the point of using API configured Kong then. :P

  3. You would check how the https://github.com/zmartzone/lua-resty-openidc library handles it. I took a quite look and it caches also the Userinfo in the session and refreshes it only after the tokens expire.

  4. The IDP are identified by the discovery document and the URL for that is passed as an argument to a function in the lua-resty-openidc library (https://github.com/nokia/kong-oidc/blob/master/kong/plugins/oidc/handler.lua#L50). You would need to change it dynamically based on your headers. Remember also that other parameters would need to be changed as well (i.e. client_id, client_secret).

jeremyjpj0916 commented 6 years ago

@Trojan295 Thanks for the prompt response! Yeah on #4 I will make sure the client_id/_secret are the same too or if not will recode the plugin to accept a list in some sort of Fork(since this is specialized and not really a feature many would want). The 3. point makes sense, if it caches it and updates only as often as the token expires is a performant method as well(our plugin caches for 8 hours internally the same userInfo as long as the user is active and proxying within a 30 min window), I never cared to implement refresh token logic so this plugin has the edge on me there with a proper refresh implementation 👍 . Take care man.

jeremyjpj0916 commented 5 years ago

@Trojan295 Any reason you decided to base64 encode the header recently? Had issues leaving as raw json or just felt it to be best practice? Also we noticed this plugin returns 502 bad gateway when the idp throws a 400 with errors on the token endpoint with things like invalid grant type. we ended up actually modifying the underlying dependency code like so to account for that and to throw something more like 401 and error from the IDP(using kongs responses dependency):

-- parse the JSON result from a call to the OP
local function openidc_parse_json_response(response)

  local err
  local res

  -- check the response from the OP
  if response.status ~= 200 then
    err = "response indicates failure, status="..response.status..", body="..response.body    
    --End the plugin now returning known issue to client
    oidc_error = {status = ngx.HTTP_UNAUTHORIZED, message = err}
responses.send(oidc_error.status, oidc_error.message)

We had to do so because some reason we were seeing connection reset in our logs coming after from the client call to ping fed even though we got the 400 response with error. and some how that connection reset was triggering the gateway to return a 502 bad gateway to the client.

now returns like: image