int128 / kubelogin

kubectl plugin for Kubernetes OpenID Connect authentication (kubectl oidc-login)
Apache License 2.0
1.66k stars 191 forks source link

Refresh Token Call Doesn't Request Scopes #798

Open NArnott opened 2 years ago

NArnott commented 2 years ago

Describe the issue

I am using Okta as an IDP, and as such, request both groups and offline_access as additional scopes so I can get the groups included in the Token (as our RBAC is based on groups within the token). This works the first time, and I get a valid token for the lifetime of that token. I also get a refresh token. However, once the initial token expires, and the refresh token grant is requested, the initial scopes used aren't passed in the refresh call and no groups are included in the newly minted token, effectively removing my access to K8s.

Example kube config user:

- name: oidc
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
      args:
      - oidc-login
      - get-token
      - --oidc-issuer-url=https://myorg.okta.com
      - --oidc-client-id=myclientid
      - --oidc-extra-scope=groups
      - --oidc-extra-scope=profile
      - --oidc-extra-scope=offline_access
      command: kubectl
      env: null
      interactiveMode: IfAvailable
      provideClusterInfo: false

Your environment

andy-v-h commented 1 year ago

+1, I'm seeing this issue on multiple OS platforms (MacOS, Linux, and windows). The token refresh is not returning the groups.

andy-v-h commented 1 year ago

After poking for at this for a bit, I found comma delimited list looks like it's working better. so

--oidc-extra-scopes=profile,groups,offline_access
poikilotherm commented 1 month ago

I am affected by this as well with a suboptimal result: I cannot use refresh tokens, I always need to remove the cached token manually and request a new ID token.

Looking at https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokenResponse:

otherwise, the same rules apply as apply when issuing an ID Token at the time of the original authentication.

It's pretty clear here we must include scopes in the refresh requests, otherwise any OIDC compliant provider is free to not include the claims in its response.

As this plugin relies on golang/oauth2 to implement the flows (via oauth2cli), I did a little digging and found numerous issues and PRs about this. The latest is https://github.com/golang/oauth2/pull/621 and from what I read in that description, I am not seeing any upstream support for this anytime soon. OAuth2 does not need this and they are not maintaining an OIDC client. @int128 is there a way out of this dependency nightmare for this project?