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

Misuse of client_credentials and password grant #6139

Closed
RobotHanzo opened this issue Jul 4, 2023 · 8 comments · Fixed by #8471
Closed

Misuse of client_credentials and password grant #6139

RobotHanzo opened this issue Jul 4, 2023 · 8 comments · Fixed by #8471
Labels
bug Something isn't working

Comments

@RobotHanzo
Copy link

RobotHanzo commented Jul 4, 2023

Describe the bug
According to Section 4.3 of RFC6749, the client_credentials grant should only take in client_id and client_secret (if any) as its authentication method and return an access token, however, this is not the case in authentik.
According to authentik docs, the "client_credentials" grant somehow requires both username and password, which is not what client_credentials grant was originally designed for in the standards.
On the other hand, there is this password grant defined in Section 4.4 of RFC6749, stating it requires both username and password fields in the request body, which I believe is what authentik is originally targeting for.

Expected behavior
client_credentials to not take username and password as a required field, this grant should be named password instead.

Version and Deployment (please complete the following information):

  • authentik version: 2023.5.4
  • Deployment: docker-compose

Additional context
In authentik docs, there's this line that says

Note that authentik does treat a grant type of password the same as client_credentials to support applications which rely on a password grant.

However, after testing, it appears that passing in a grant_type of password makes authentik throw the following exception

Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/asgiref/sync.py", line 472, in thread_handler
    raise exc_info[1]
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
    response = await wrapped_callback(
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/asgiref/sync.py", line 435, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/asyncio/tasks.py", line 442, in wait_for
    return await fut
           ^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/asgiref/current_thread_executor.py", line 22, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/asgiref/sync.py", line 476, in thread_handler
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 103, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/utils/decorators.py", line 46, in _wrapper
    return bound_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 55, in wrapped_view
    return view_func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/authentik/providers/oauth2/views/token.py", line 429, in dispatch
    response = super().dispatch(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 142, in dispatch
    return handler(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/authentik/providers/oauth2/views/token.py", line 467, in post
    raise ValueError(f"Invalid grant_type: {self.params.grant_type}")
builtins.ValueError: Invalid grant_type: password

Which is not expected by the documentations

@RobotHanzo RobotHanzo added the bug Something isn't working label Jul 4, 2023
@BeryJu
Copy link
Member

BeryJu commented Jul 20, 2023

I think some of the reason for this is due to https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow using client_credentials in conjunction with client_assertion_type

I'm not sure how we could implement a spec-accurate version of this, since there would need to be some kind of user in authentik to attribute actions to.

The exception should definitely not happen though

@RobotHanzo
Copy link
Author

I think some of the reason for this is due to https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow using client_credentials in conjunction with client_assertion_type

I'm not sure how we could implement a spec-accurate version of this, since there would need to be some kind of user in authentik to attribute actions to.

The exception should definitely not happen though

https://github.com/goauthentik/authentik/blob/0b5870f16e41d9eb5535b495443dd2b0bb65a19c/authentik/providers/oauth2/views/token.py#L456C1-L469C1
According to these lines ^, password grant is not included in the checks, therefore raising an exception

@authentik-automation
Copy link
Contributor

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@authentik-automation authentik-automation bot closed this as not planned Won't fix, can't repro, duplicate, stale Sep 27, 2023
@RobotHanzo
Copy link
Author

I don’t think this issue is fully fixed yet, can @BeryJu reopen it?

@mhoyer
Copy link

mhoyer commented Nov 2, 2023

I agree and also was kind of confused to see this way of passing credentials (client_id + username + password) to the /token endpoint to retrieve an access_token. Wouldn't this produce quite some issues in existing oidc/oauth2 libraries existing out there?

One quick suggestion (hack?) to make it RFC6749 compliant: concatenate username and password with a :, base64-decode it and use it as client_secret. Then you're able to extract username/password on Authentik server side again.

@modem7
Copy link

modem7 commented Dec 29, 2023

Hey guys,

Just came across this issue thanks to CommanderStorm's mention.

I'm not sure how we could implement a spec-accurate version of this, since there would need to be some kind of user in authentik to attribute actions to.

Would a dynamically created service user + role per outpost (if selected for example) be sufficient or would that be overcomplicating matters?

Keycloak seems to have a similar-ish method to assign the Client Credentials grant, which then allows it to work with services such as uptimekuma.

image

@modem7
Copy link

modem7 commented Feb 8, 2024

Hey guys,

Apologies for poking, but is there any progress on this one?

I'm unable to use Authentik with services like UptimeKuma, which means unfortunately I can't migrate things across.

Cheers!

@fheisler
Copy link
Contributor

We're weighing solution with an aim to fix this in the next (March/April) release in a backwards-compatible way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants