simov / grant

OAuth Proxy
MIT License
4.09k stars 257 forks source link

Incorrect inclusion of client_secret for authorization_code grant in OAuth2 implementation #292

Closed tosoikea closed 1 year ago

tosoikea commented 1 year ago

Summary

The current OAuth2 library implementation incorrectly includes the client_secret for the authorization_code grant type. This is against the specifications as mentioned in the RFC6749.

Details

Reference

Current Implementation

The current implementation sends the client_secret when making a POST request to the token endpoint for the authorization_code grant:

var options = {
  method: 'POST',
  url: provider.access_url,
  form: {
    grant_type: 'authorization_code',
    code: query.code,
    client_id: provider.key,
    client_secret: provider.secret,
    redirect_uri: provider.redirect_uri
  }
}

Source: OAuth2 Implementation

Question for Development Team

Is there a specific and valid reason why the client_secret is included in this scenario?

Impact

This misalignment with the OAuth2 standard might cause compatibility issues with certain OAuth2 providers that strictly enforce the token endpoint specification. Moreover, unnecessary transmission of client_secret could pose a potential security risk if intercepted.

Recommended Action

Please review the decision to include the client_secret and adjust the implementation to align with the OAuth2 standard unless there's a compelling reason to do otherwise.

simov commented 1 year ago

I think the correct link should be this https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3 but I get your point.

If the client type is confidential or the client was issued client credentials (or assigned other authentication requirements), the client MUST authenticate with the authorization server as described in Section 3.2.1.

So I guess this is why most authorization servers (read hundreds tested with this module) require client authentication for the token endpoint. That being said, if you omit the secret option when using Grant then client_secret won't be sent to the authorization server, because undefined values are being filtered out.

For example, I removed my secret and tried to login with Google, here is the resulting error:

{
  "error": "invalid_request",
  "error_description": "client_secret is missing."
}

For apps hosted on Azure AD in particular you may want to provide a certificate and use that to authenticate your client:

Screenshot from 2023-10-03 15-23-40

As you can see in that case there is no secret provided in the Grant config: https://github.com/simov/grant/blob/master/examples/token-endpoint/config.json