go-oauth2 / oauth2

OAuth 2.0 server library for the Go programming language.
https://pkg.go.dev/github.com/go-oauth2/oauth2/v4
MIT License
3.31k stars 563 forks source link

ClientBasicHandler should unescape client ID and client secret #235

Closed f-pisani closed 1 year ago

f-pisani commented 1 year ago

Hi,

When using ClientBasicHandler, the handler returns the raw values from r.BasicAuth, but theses values should be unescaped using url.QueryUnescape before being returned.

As stated by RFC 6749#section-2.3.1:

The client identifier is encoded using the "application/x-www-form-urlencoded" encoding algorithm per Appendix B, and the encoded value is used as the username; the client password is encoded using the same algorithm and used as the password.

This make the server not compatible with OAuth2 clients enforcing the RFC when using basic auth.

golang.org/x/oauth2 for example is not working properly when using basic auth with this server implementation because the Client ID and Client secret are url.QueryEscaped before being sent (source).

The following could fix the problem and should also work for non-compliant clients:

func ClientBasicHandler(r *http.Request) (string, string, error) {
    username, password, ok := r.BasicAuth()
    if !ok {
        return "", "", errors.ErrInvalidClient
    }

    if usernameUnescaped, err := url.QueryUnescape(username); err == nil {
        username = usernameUnescaped
    }

    if passwordUnescaped, err := url.QueryUnescape(password); err == nil {
        password = passwordUnescaped
    }

    return username, password, nil
}