lepture / authlib

The ultimate Python library in building OAuth, OpenID Connect clients and servers. JWS,JWE,JWK,JWA,JWT included.
https://authlib.org/
BSD 3-Clause "New" or "Revised" License
4.45k stars 445 forks source link

Can't have more than 1 oauth client registered #587

Open cesarqdt opened 10 months ago

cesarqdt commented 10 months ago

Describe the bug

When there are more than 1 oauth client to connect (registered as oauth.register(...)), the application always picks the last one in the definition instead of any of the defined ones. There should be a way to keep every client registered and usable in subsequent calls.

Follow this example:

# 1. Register client_1
oauth.register(
        "client_1",
        client_id = client_id,
        client_secret = client_secret,
        client_kwargs = {
            "scope": "openid profile email",
        },
        server_metadata_url = f'{domain}/.well-known/openid-configuration'
    )

# 2. Register client_2
oauth.register(
        "client_2",
        client_id = client_id_2,
        client_secret = client_secret_2,
        client_kwargs = {
            "scope": "openid profile email",
        },
        server_metadata_url = f'{domain_2}/.well-known/openid-configuration'
    )

@app.route('client_1/login')
def client_1_login():
    return oauth.client_1.....

@app.route('client_2/login')
def client_2_login():
    return oauth.client_2....

Error Stacks when someone accesses route client_1/login, an error will raise with the following traceback:

Traceback (most recent call last):
  File "/usr/src/app/.local/lib/python3.9/site-packages/flask/app.py", line 2077, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/src/app/.local/lib/python3.9/site-packages/flask/app.py", line 1525, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/src/app/.local/lib/python3.9/site-packages/flask_cors/extension.py", line 165, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/usr/src/app/.local/lib/python3.9/site-packages/flask/app.py", line 1523, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/src/app/.local/lib/python3.9/site-packages/flask/app.py", line 1509, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "/usr/src/app/app/views/auth.py", line xxx, in client_1_login
    token = oauth.client_1.authorize_access_token()
  File "/usr/src/app/.local/lib/python3.9/site-packages/authlib/integrations/base_client/registry.py", line 118, in __getattr__
    raise AttributeError('No such client: %s' % key)
AttributeError: No such client: client_1

To Reproduce

Create a simple app and register two OAuth clients globally.

Expected behavior Try accessing any route where the first client is required.

Environment:

andersnauman commented 9 months ago

Disclaimer: There might still be a bug but...

If you use create_client() which both creates and gets a client (comments in the code "Create or get the given named OAuth client") then you can call/use both clients, at least what it looks like for me.

Example code:

client = oauth.create_client("client_1")
client.authorize_access_token()

This way you can consolidate the code to:

@app.route('/login/<client_name>')
def client_login(client_name):
    client = oauth.create_client(client_name)
    client.authorize_access_token()
    ...