int128 / kubelogin

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

Should have the option to use `access_token` instead of `id_token` #1083

Open adkafka opened 2 months ago

adkafka commented 2 months ago

Purpose of the feature (why)

It should be possible to configure this tool to use an access_token instead of an id_token. Many identity providers expose extra claims in access_tokens that are not available in id_tokens. One concrete example is the scp claim in Azure AD that can be used to identify which scopes were requested. In my case, I'm using additional scopes to force the ID provider to trigger MFA, and I'd like to use --oidc-required-claim server-side to verify that the tokens issued have the necessary extra scope. Similiarly, AzureAD also only exposes the amr claim on the access token which more directly indicates if the user used MFA, however the values of that are an array, not a string, so I cannot simply use --oidc-required-claim with that.

The kubernetes docs indicate that we should be using the id_token, not the access_token, but there is more nuance to that. As an example, see this thread: Why use id tokens instead of access tokens for authorization. I can also share anecdotal data that there are other use cases that have come up in my work where we've had to resort to using the access_token instead of the id_token in an OIDC flow in order to access the necessary claims. Lastly, the Azure based kubelogin tool also uses the access_token, not the id_token. See logic here.

I believe the user of this tool should be able to choose to use access_tokens instead, assuming they understand these nuances, even though it is not the suggested path according to the official kubernetes docs.

Your idea (how)

I suggest adding a new CLI flag to the get-token command: --oidc-use-access-token. This will then return the access_token instead of the id_token in this method: https://github.com/int128/kubelogin/blob/fdcdcc3a60561d26957a43872f0bd997b160c424/pkg/oidc/client/client.go#L195. We will add this additional flag as a parameter to the OIDC client (pkg/oidc/client/client.go). See https://github.com/int128/kubelogin/pull/1084 for the PR.

The default behavior will be unchanged (using id_token), this new behavior must be opted into.

jsphpl commented 1 month ago

Another problem with the ID token is that, by definition the aud is the client that requested the token, which implies that kubectl has to impersonate the cluster.

In my opinion this is an incorrect use of OAuth2/OIDC. Actually kubectl is the Client, which requests a token on behalf of the User to access the cluster. The cluster, in OAuth2/OIDC terms, is the Resource Server. The id_token is only meant for the Client. The access_token is meant for the Resource Server.

If using OIDC correctly, a cluster will reject the id_token because it doesn't state the cluster's client ID as the audience.

Or am I wrong?