The addition of SCRAM-SHA-256 is proving to have many benefits in PostgreSQL over MD5, but it has required an extension of the authentication protocol so as message exchanges for SASL authentication are able to work correctly. A lot of details on this matter are defined in the documentation:
- When beginning the SASL authentication, the server sends a list of mechanisms that it supports. In Postgres 10 only SCRAM-SHA-256 is supported (definition by IANA). In the future more of them could be added, like SCRAM-SHA-256-PLUS which is the same as the latter with support for channel binding. Note that the message format is predefined, as a list of zero-terminated string with an empty string as last element of the list.
- The client chooses the mechanism it wants to use with the server, which is a unique choice for now.
- Then follows a set of messages exchanged. In the case of SCRAM those messages is are roughly a challenge from the server and response to it by the client.
- Once the exchange completes, the server sends back a finalization message.
As this facility is already implemented in libpq, all drivers that do not speak directly the PostgreSQL protocol do not need any work, like ODBC for example: everything works out-of-the-box. However, there are some drivers that need some work to support SCRAM, like:
- Crystal, which has no support yet.
- Go, in which case there is a patch lying around, waiting for review.
- Npgsql, where there is no package yet.
- JDBC, where a patch is in the works.
- Node, the use of libpq being optional here, things are still possible.
The PostgreSQL wiki maintains a list of all the drivers related to the project here, so if you know about an extra driver that is not listed in it, feel free to add it.
Note as well that some work is planned to add channel binding in Postgres 11, so any implementation done should be careful enough to handle multiple mechanism names received from the server. The current plan is to implement two channel binding types as listed in RFC 5929:
- tls-unique, which uses the TLS finish message.
- tls-server-end-point, which uses a hash of the TLS server certificate for validation.
Any implementation of channel binding must have tls-unique, and for OpenSSL this data can be fetched thanks to two undocumented APIs, SSL_get_peer_finished() and SSL_get_finished(). For some drivers putting their hands on this data may require some extra, unwelcome dependencies, which is actually the case of the JDBC driver. So if you are a driver maintainer, feel free to drop any opinion on the thread dedicated to the channel binding development of SCRAM that is here.