frankie567 / httpx-oauth

Async OAuth client using HTTPX
https://frankie567.github.io/httpx-oauth/
MIT License
136 stars 45 forks source link

Quick Question: For the OpenID client is there a way to configure the revoke token endpoint? #291

Closed jdclawson closed 1 year ago

jdclawson commented 1 year ago

I've altered a package that integrates Streamlit with google auth (https://github.com/hunkim/streamlit-google-oauth) using this package. I altered it so it would use the OpenID client instead of the google one.

I've been sifting through the documentation for a couple of hours and I haven't been able to figure out where exactly I'm supposed to put the address to revoke the token for a log out button. I keep getting the RevokeTokenNotSupportedError(). I get that I'm supposed to put in the endpoint, but I'm not seeing a place to do that for the OpenID client.

Would I have to use a Generic client instead of the OpenID one? I'm pretty new to oauth, so I apologize if this is a dumb question.

frankie567 commented 1 year ago

Hi @jdclawson 👋

One of the benefit of OpenID is automatic discovery of the OAuth2 routes and configuration.

It means that your provider exposes an URL like this one: https://accounts.google.com/.well-known/openid-configuration If you open it, you'll see a result like this:

{
 "issuer": "https://accounts.google.com",
 "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
 "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code",
 "token_endpoint": "https://oauth2.googleapis.com/token",
 "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
 "revocation_endpoint": "https://oauth2.googleapis.com/revoke",
 "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
 "response_types_supported": [
  "code",
  "token",
  "id_token",
  "code token",
  "code id_token",
  "token id_token",
  "code token id_token",
  "none"
 ],
 "subject_types_supported": [
  "public"
 ],
 "id_token_signing_alg_values_supported": [
  "RS256"
 ],
 "scopes_supported": [
  "openid",
  "email",
  "profile"
 ],
 "token_endpoint_auth_methods_supported": [
  "client_secret_post",
  "client_secret_basic"
 ],
 "claims_supported": [
  "aud",
  "email",
  "email_verified",
  "exp",
  "family_name",
  "given_name",
  "iat",
  "iss",
  "locale",
  "name",
  "picture",
  "sub"
 ],
 "code_challenge_methods_supported": [
  "plain",
  "S256"
 ],
 "grant_types_supported": [
  "authorization_code",
  "refresh_token",
  "urn:ietf:params:oauth:grant-type:device_code",
  "urn:ietf:params:oauth:grant-type:jwt-bearer"
 ]
}

You see here that we have several URL, including revocation_endpoint, which is the route to call to revoke a token. In our code, you'll see that we try to get it this URL:

https://github.com/frankie567/httpx-oauth/blob/ab3d7015ce9d9765bfaaa48750c2eaf730c53fc7/httpx_oauth/clients/openid.py#L41

However, the revocation endpoint is optional in the OpenID specification; so it's possible that your OpenID provider doesn't have it.

If you're sure your OpenID provider has a revocation endpoint, you have two solutions:

  1. Ask them to add it in their /.well-known/openid-configuration.
  2. Overload the OpenID client to manually pass that URL:
class MyOpenIDProvider(OpenID):
    def __init__(
        self,
        client_id: str,
        client_secret: str,
        openid_configuration_endpoint: str,
        name: str = "openid",
        base_scopes: Optional[List[str]] = BASE_SCOPES,
    ):
        super().__init__(client_id, client_secret, openid_configuration_endpoint, name=name, base_scopes=base_scopes)
        self.revoke_token_endpoint = "https://www.myprovider.com/revoke"