Skip to content

Support Client Credentials Flow #1231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

cbaenziger
Copy link
Contributor

This provides support for the OAuth 2.0 Client Credentials authentication login flow.

The Client Credentials flow has been asked about in #931. I have been working with a piece of software which only accepts a K8s configuration for connection setup and authentication, so client credentials works great for me for machine-to-machine communications. I've used this code against a private IdP successfully.

@cbaenziger
Copy link
Contributor Author

It looks like the docker tests are expected to fail? I see the following which seems reasonable:

#25 ERROR: failed to push ghcr.io/int128/kubelogin:pr-1231: unexpected status from POST request to https://ghcr.io/v2/int128/kubelogin/blobs/uploads/: 403 Forbidden

@int128
Copy link
Owner

int128 commented Jan 12, 2025

docker/build-push-action was failing on forked pull request. I have fixed the problem as #1233.

Comment on lines 193 to 186
return &oidc.TokenSet{
IDToken: token.AccessToken,
RefreshToken: token.RefreshToken,
}, nil
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it needs to verify the retrieved token.
For example,

return c.verifyToken(ctx, token, "")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I've implemented this now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately in my extended testing, verifyToken fails to accept my valid OAuth 2.0 token. Perhaps you can advise which path you prefer for me to follow?

Per the OAuth2 RFC, where the Client Credential flow is defined, it looks like access_token is a required response per the RFC8693 Successful Response definition but no longer is id_token mentioned. (Similarly Auth0 and Okta have diagrams pointing out an access_token is returned for Client Credentials.)

Meanwhile, I do see in the OIDC Core Spec, id_token is required it its Token Response section.

Using verifyToken my exchange works but I fail to accept the token:

./kubelogin get-token \
    --grant-type=client-credentials \
    --oidc-issuer-url=https://<elided> \
    --oidc-client-id=<elided> \
    --oidc-client-secret=<elided> \
    --no-keyring
error: get-token: authentication error: client-credentials error: authorization error: id_token is missing in the token response: &oauth2.Token{AccessToken:"... elided ...", TokenType:"Bearer", RefreshToken:"", Expiry:time.Date(2025, time.January, 16, 23, 31, 55, 191375292, time.Local), ExpiresIn:0, raw:map[string]interface {}{"access_token":"... elided ...", "expires_in":59, "token_type":"Bearer"}, expiryDelta:0}

The code does work for me, as originally implemented, returning the access_token in my client.authentication.k8s.io/v1beta1 JSON payload as token which my API server accepts.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using this feature with --use-access-token flag? It will use the access_token as the token response for Kubernetes API server. See also #1083.

Copy link
Contributor Author

@cbaenziger cbaenziger Jan 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, the structure of the token is different than what VerifyToken is expecting.

The Client Credentials RFC token specification does not return an OIDC IDToken? (Specifically the response specification in RFC 6749 does not include even an optional IDToken field.)

As such, at least as configured by my IdP, there is no IDToken envelope to pull the AccessToken out of; the AccessToken is all I receive:

&oauth2.Token{AccessToken:"[...]", TokenType:"Bearer", RefreshToken:"", Expiry:time.Date(2025, time.January, 26, 9, 43, 35, 530935198, time.Local)

Questions to confirm:

  1. I don't think it will be possible to use --grant-type=client-credentials without --use-access-token as I've implemented?
  2. VerifyToken would need to parse a different token type to still be used but I also do not believe we would have the need for verification like with the other grant types (the token could be fully opaque per the specification)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@int128 I think I understand questions 1 and 2 now. I think this code should be good.

Does it look okay to you?

@cbaenziger

This comment was marked as resolved.

@cbaenziger cbaenziger force-pushed the clientcredentials branch 2 times, most recently from c58369d to c6d31d7 Compare February 21, 2025 08:40
@kheraud
Copy link

kheraud commented May 14, 2025

Is there any progress on this feature ? How can we move forward ?

@cbaenziger cbaenziger force-pushed the clientcredentials branch from c6d31d7 to 51e754a Compare May 19, 2025 22:43
@cbaenziger cbaenziger force-pushed the clientcredentials branch from 51e754a to 86c2934 Compare May 19, 2025 22:54
@cbaenziger
Copy link
Contributor Author

I just now confirmed yesterday's rebase onto the current codebase in my environment.

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

Successfully merging this pull request may close these issues.

3 participants