Skip to content
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

authenticate_oidc: No client_id found (when OIDC provider does not list refresh_token grant type) #530

Open
m-mohr opened this issue Jan 19, 2024 · 8 comments

Comments

@m-mohr
Copy link
Member

m-mohr commented Jan 19, 2024

I have a backend with the following response to GET /credentials/oidc:

{
  "providers":[
    {
      "id":"google",
      "issuer":"https://accounts.google.com",
      "title":"Google",
      "description":"Login with your Google Earth Engine account.",
      "scopes":[
        "openid",
        "email",
        "https://www.googleapis.com/auth/earthengine"
      ],
      "default_clients":[
        {
          "id":"123.apps.googleusercontent.com",
          "grant_types":[
            "implicit"
          ],
          "redirect_urls":[
            "https://editor.openeo.org/",
            "http://localhost/"
          ]
        },
        {
          "id":"abc.apps.googleusercontent.com",
          "grant_types":[
            "urn:ietf:params:oauth:grant-type:device_code+pkce"
          ]
        }
      ]
    }
  ]
}

I'm running:

import openeo
connection = openeo.connect("http://localhost:8080")
connection.authenticate_oidc()

And get unexpectedly the following error:

OpenEoClientException: No client_id found.

Why is that? I think there's a reasonable default client ID available. (All client IDs are placeholders in the example.)

@m-mohr m-mohr added the auth label Jan 19, 2024
@soxofaan
Copy link
Member

Looking into that. Do you have the full stack trace of that error?

@soxofaan
Copy link
Member

soxofaan commented Jan 19, 2024

first guess is that refresh_token grant type is not listed in your /credentials/oidc: response

@soxofaan
Copy link
Member

soxofaan commented Jan 19, 2024

"grant_types":[
            "urn:ietf:params:oauth:grant-type:device_code+pkce"
          ]

this indicates that you are only interested in device code grant, and not refresh token.
So .authenticate_oidc() is not really recommended to use (as automated refresh token handling is one of it's key features).

Using .authenticate_oidc_device() should work against that /credentials/oidc setup however. Can you confirm that?

That being said, I think there is a case to be made to make .authenticate_oidc() work againsts your setup too

@soxofaan soxofaan self-assigned this Jan 19, 2024
@m-mohr
Copy link
Member Author

m-mohr commented Jan 19, 2024

I've also tried it with urn:ietf:params:oauth:grant-type:device_code as default client and that lead to the same error.
I need to check the other parts...

@soxofaan
Copy link
Member

I've also tried it with urn:ietf:params:oauth:grant-type:device_code as default client and that lead to the same error.

indeed, with or without the +pkce doesn't matter here

soxofaan added a commit that referenced this issue Jan 19, 2024
@m-mohr
Copy link
Member Author

m-mohr commented Jan 19, 2024

The Google OIDC is a bit weird in that it supports refresh_token, but not the offline_access scope. I always thought they were somewhat related, maybe they are not though. Also fiddling around with it in Open-EO/openeo-web-editor#319 - Maybe the primary issue is actually that we don't usually list offline_access in the scopes that are reported by the default clients? Should they do that?

Stack trace based on your last commit:

---------------------------------------------------------------------------
OpenEoClientException                     Traceback (most recent call last)
Cell In[9], line 1
----> 1 connection.authenticate_oidc()

File /mnt/c/Dev/openeo-python-client/openeo/rest/connection.py:716, in Connection.authenticate_oidc(self, provider_id, client_id, client_secret, store_refresh_token, use_pkce, display, max_poll_time)
    714 else:
    715     default_client_grant_check = lambda grants: (_g.DEVICE_CODE in grants or _g.DEVICE_CODE_PKCE in grants)
--> 716 provider_id, client_info = self._get_oidc_provider_and_client_info(
    717     provider_id=provider_id,
    718     client_id=client_id,
    719     client_secret=client_secret,
    720     default_client_grant_check=default_client_grant_check,
    721 )
    723 # Try refresh token first.
    724 refresh_token = self._get_refresh_token_store().get_refresh_token(
    725     issuer=client_info.provider.issuer,
    726     client_id=client_info.client_id
    727 )

File /mnt/c/Dev/openeo-python-client/openeo/rest/connection.py:454, in Connection._get_oidc_provider_and_client_info(self, provider_id, client_id, client_secret, default_client_grant_check)
    450         _log.info("Using default client_id {c!r} from OIDC provider {p!r} info.".format(
    451             c=client_id, p=provider_id
    452         ))
    453 if client_id is None:
--> 454     raise OpenEoClientException("No client_id found.")
    456 client_info = OidcClientInfo(client_id=client_id, client_secret=client_secret, provider=provider)
    458 return provider_id, client_info

OpenEoClientException: No client_id found.

@soxofaan
Copy link
Member

Stack trace based on your last commit:

With that POC commit you should also disable refresh token storage connection.authenticate_oidc(store_refresh_token=False)

FYI The other workaround mentioned above (which should work with a normal release of python client) is to use

connection.authenticate_oidc_device()

Have you tried that already with your setup?

@m-mohr
Copy link
Member Author

m-mohr commented Jan 19, 2024

connection.authenticate_oidc(store_refresh_token=False)

This works indeed, thanks. A bit cumbersome that users have to specify a parameter.

But generally, I still struggle to understand whether the Google Auth supports PKCE for device_code or not. Some docy imply it does, but all requests ask me to provide a secret. So may not be supported.

Generally, I got it working in the Editor, but have still issues connecting through Google without a secret...

Have you tried that already with your setup?

Yes, works (with the caveats above). This also works:
connection.authenticate_oidc_device(provider_id="google", client_id="abc.apps.googleusercontent.com", client_secret="..." use_pkce=False)

More to be investigated (also the relation between offline_access scope and refresh_token grant).

@soxofaan soxofaan changed the title authenticate_oidc: No client_id found authenticate_oidc: No client_id found (when OIDC provider does not list refresh_token grant type) Jan 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants