-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Describe the bug
When trying to obtaining a token via /application/o/token/ using client_credentials in the Authorization: Basic header, the request is rejected with "error": "invalid_grant", if the client_id or client_secret contain urlencoded characters (as per rfc6749#section-2.3.1)
How to reproduce
You Need:
- An Application with an OAuth2/OpenID Provider.
- A service-account with an App password.
Let
# the username of the service-account
USER="service-account"
# the App passwort of the service account (60 random characters)
PASS="IkZRYWekQfBaZTRh6bpeBQQKKoqCoToQL6cTPI5BetoxxyzWof3BFZMuZaty"
# form service-account client_credentials as per rfc6749#section-2.3.1.
# neither USER nor PASS contain characters, that need urlencoding at this stage
CLIENT_CREDENTIALS="$(echo -n "$USER:$PASS" | base64 -w0)"
# the OAuth2/OpenID Provider client_id (40 random characters)
CLIENT_ID="f2jgG2J40E6yai6t30aDiJirdgtKYyGtpUXFckzj"
# form the token request credentials as per rfc6749#section-2.3.1.
# CLIENT_CREDENTIALS may contain base64 padding `=`-chars, which must be replaced with `%3D`.
# the length of `service-account` is chosen, such that there are two padding-chars in this example.
ENCODED_CLIENT_CREDENTIALS="${CLIENT_CREDENTIALS//=/%3D}"
TOKEN_REQUEST_CREDENTIALS="$(echo -n "$CLIENT_ID:$ENCODED_CLIENT_CREDENTIALS" | base64 -w0)"Request:
POST https://authentik/application/o/token/
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Basic $TOKEN_REQUEST_CREDENTIALS
grant_type=client_credentials&scope=openidObserve:
{
"error": "invalid_grant",
"error_description": "The provided authorization grant or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client",
"request_id": "9fc942296bf344f081a6870648d2470f"
}If TOKEN_REQUEST_CREDENTIALS is formed with the unencoded CLIENT_CREDENTIALS like follows, the request succeeds:
TOKEN_REQUEST_CREDENTIALS="$(echo -n "$CLIENT_ID:$CLIENT_CREDENTIALS" | base64 -w0)"Expected behavior
The request should succeed, when the TOKEN_REQUEST_CREDENTIALS are formed, as described.
Probably: https://github.com/goauthentik/authentik/blob/main/authentik/providers/oauth2/utils.py#L123 should url-decode the received client_id and client_secret as specified in rfc6749#section-2.3.1.
Screenshots
No response
Additional context
I don't know, whether there are clients that rely on the "broken" behaviour. I don't know the OAuth2 spec and its history too well. I only found the spec reference by links from my client-library, which even allows me to circumvent this behaviour (spring-projects/spring-security#11440).
A existing client would break, if its client_id or client_secret contain char-sequences, that would be processed by url-decoding.
Deployment Method
Docker
Version
2026.2.1
Relevant log output
Metadata
Metadata
Assignees
Labels
Type
Projects
Status