Skip to content

Commit 7bd5dd4

Browse files
committed
Handle SASL SCRAM server error responses
Add proper error handling for SCRAM-SERVER-FINAL-MESSAGE error attribute. The SCRAM specification allows servers to return error messages via the 'e' attribute in the server final message. Currently, these errors are ignored and authentication fails later during signature verification. Postgres typically doesn't return this error (see [here](https://github.com/postgres/postgres/blob/2047ad068139f0b8c6da73d0b845ca9ba30fb33d/src/backend/libpq/auth-scram.c#L423) on why), but poolers, or other applications using the postgres protocol might, and it's part of the SCRAM spec, so it probably makes sense for node-postgres to handle it. Aligns behaviour with psql, postgrex, and somewhat with pgJDBC (pgJDBC in particular is stricter with scram errors). For reference: - libpq handling it: https://github.com/postgres/postgres/blob/2047ad068139f0b8c6da73d0b845ca9ba30fb33d/src/interfaces/libpq/fe-auth-scram.c#L708
1 parent 27a2754 commit 7bd5dd4

File tree

2 files changed

+23
-0
lines changed

2 files changed

+23
-0
lines changed

packages/pg/lib/crypto/sasl.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,13 @@ function parseServerFirstMessage(data) {
178178

179179
function parseServerFinalMessage(serverData) {
180180
const attrPairs = parseAttributePairs(serverData)
181+
const error = attrPairs.get('e')
181182
const serverSignature = attrPairs.get('v')
183+
184+
if (error) {
185+
throw new Error(`SASL: SCRAM-SERVER-FINAL-MESSAGE: server returned error: "${error}"`)
186+
}
187+
182188
if (!serverSignature) {
183189
throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature is missing')
184190
} else if (!isBase64(serverSignature)) {

packages/pg/test/unit/client/sasl-scram-tests.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,23 @@ suite.test('sasl/scram', function () {
284284
)
285285
})
286286

287+
suite.test('fails when server returns an error', function () {
288+
assert.throws(
289+
function () {
290+
sasl.finalizeSession(
291+
{
292+
message: 'SASLResponse',
293+
serverSignature: 'abcd',
294+
},
295+
'e=no-resources'
296+
)
297+
},
298+
{
299+
message: 'SASL: SCRAM-SERVER-FINAL-MESSAGE: server returned error: "no-resources"',
300+
}
301+
)
302+
})
303+
287304
suite.test('fails when server signature does not match', function () {
288305
assert.throws(
289306
function () {

0 commit comments

Comments
 (0)