jrd / django-oauth2-authcodeflow

Authenticate with any OpenId Connect/Oauth2 provider through authorization code flow. PKCE is also supported
https://pypi.org/project/django-oauth2-authcodeflow/
MIT License
14 stars 8 forks source link

CIAM token request fails with "The client MUST NOT use more than one authentication method in each" #18

Open pinoatrome opened 7 months ago

pinoatrome commented 7 months ago

After a valid login on CIAM the callback view invokes the authentication backend that POST a request to the OP to obtain a token but the server response has 400 error status with content: b'{"error_description":"The client MUST NOT use more than one authentication method in each","error":"invalid_request"}'

the CIAM is configured to not accept requests with 'client_secret' params when using PKCE flow.

the current implementation (v.1.1.0) requires an empty value for OIDC_RP_CLIENT_SECRET settings entry

https:///oauth2/token with params: { 'grant_type': 'authorization_code', 'client_id': , 'client_secret': , 'redirect_uri': 'http://127.0.0.1/oidc/callback', 'code': , 'code_verifier': <value from session (only if PKCE is enabled)> }

the response is an error 400 with content b'{"error_description":"The client MUST NOT use more than one authentication method in each","error":"invalid_request"}'

cpontvieux-systra commented 5 months ago

Ok, so why don’t set OIDC_RP_CLIENT_SECRET to None or empty string?

Your pull request made it explicit and it’s better in some ways, but I don’t see how you get an empty client_secret field in params here. Could you elaborate on how do you get that error?

pinoatrome commented 5 months ago

Hi Cyrille, many thanks for dedicating your time evaluating my PR and my apologies for making it not clear enough.

Could you elaborate on how do you get that error?

After configured the client with client_id and client_secrets values received from the OP manager the server response was an error 400 after a valid login. Thanks to a debug session I found that the solution recommended by the implementation was to configure an empty value for the client_secret -> and it worked actually. So the message from the server is correct: the client is using two methods, that are PKCE flow and client_secret.

so why don’t set OIDC_RP_CLIENT_SECRET to None or empty string?

Because I felt uncomfortable in remove a valid value from the config -> what if the client_secret is required in another scenario between the client and the server? I'm proposing this alternative approach: to keep the client_id and client_secret values as provided by the OP manager AND set to False the flag OIDC_OP_PKCE_ALLOW_SEND_SECRET (default is True for retro compatibility). The OP manager said that the server can be configured to accept the request with the client_secret or block it, so the flag can be True.

Your pull request made it explicit and it’s better in some ways

Correct: trying to avoid the use of 'talking' values (empty value for client_secret) to drive the behaviour of the client (to send the param or not) but rather use an additional flag for the PKCE flow.

Sorry for the long answer, hope this clarify my contribution. Ciao GG