From d2086b0c850e3cafbc5ec35be8621612a9b1b833 Mon Sep 17 00:00:00 2001 From: Joren Vandeweyer Date: Sat, 26 Aug 2023 09:24:21 +0200 Subject: [PATCH] fixed critical scope validation bug for 4.x --- lib/grant-types/abstract-grant-type.js | 12 ++--- .../authorization-code-grant-type.js | 47 ++++++++++--------- .../client-credentials-grant-type.js | 37 ++++++++------- lib/grant-types/password-grant-type.js | 45 +++++++++--------- 4 files changed, 75 insertions(+), 66 deletions(-) diff --git a/lib/grant-types/abstract-grant-type.js b/lib/grant-types/abstract-grant-type.js index d9894b6a..c09e6fb2 100644 --- a/lib/grant-types/abstract-grant-type.js +++ b/lib/grant-types/abstract-grant-type.js @@ -93,18 +93,18 @@ AbstractGrantType.prototype.getScope = function(request) { /** * Validate requested scope. */ -AbstractGrantType.prototype.validateScope = function(user, client, scope) { +AbstractGrantType.prototype.validateScope = function(user, client, requestedScoped) { if (this.model.validateScope) { - return promisify(this.model.validateScope, 3).call(this.model, user, client, scope) - .then(function (scope) { - if (!scope) { + return promisify(this.model.validateScope, 3).call(this.model, user, client, requestedScoped) + .then(function (validatedScope) { + if (!validatedScope) { throw new InvalidScopeError('Invalid scope: Requested scope is invalid'); } - return scope; + return validatedScope; }); } else { - return scope; + return requestedScoped; } }; diff --git a/lib/grant-types/authorization-code-grant-type.js b/lib/grant-types/authorization-code-grant-type.js index 92193d3c..ca423ef7 100644 --- a/lib/grant-types/authorization-code-grant-type.js +++ b/lib/grant-types/authorization-code-grant-type.js @@ -205,28 +205,31 @@ AuthorizationCodeGrantType.prototype.revokeAuthorizationCode = function(code) { * Save token. */ -AuthorizationCodeGrantType.prototype.saveToken = function(user, client, authorizationCode, scope) { - const fns = [ - this.validateScope(user, client, scope), - this.generateAccessToken(client, user, scope), - this.generateRefreshToken(client, user, scope), - this.getAccessTokenExpiresAt(), - this.getRefreshTokenExpiresAt() - ]; - - return Promise.all(fns) - .bind(this) - .spread(function(scope, accessToken, refreshToken, accessTokenExpiresAt, refreshTokenExpiresAt) { - const token = { - accessToken: accessToken, - authorizationCode: authorizationCode, - accessTokenExpiresAt: accessTokenExpiresAt, - refreshToken: refreshToken, - refreshTokenExpiresAt: refreshTokenExpiresAt, - scope: scope - }; - - return promisify(this.model.saveToken, 3).call(this.model, token, client, user); +AuthorizationCodeGrantType.prototype.saveToken = function(user, client, authorizationCode, requestedScope) { + return Promise.bind(this) + .then(function() { + return this.validateScope(user, client, requestedScope); + }) + .then(function(validatedScoped) { + return Promise.all([ + this.generateAccessToken(client, user, validatedScoped), + this.generateRefreshToken(client, user, validatedScoped), + this.getAccessTokenExpiresAt(), + this.getRefreshTokenExpiresAt() + ]) + .bind(this) + .spread(function(accessToken, refreshToken, accessTokenExpiresAt, refreshTokenExpiresAt) { + const token = { + accessToken: accessToken, + authorizationCode: authorizationCode, + accessTokenExpiresAt: accessTokenExpiresAt, + refreshToken: refreshToken, + refreshTokenExpiresAt: refreshTokenExpiresAt, + scope: validatedScoped + }; + + return promisify(this.model.saveToken, 3).call(this.model, token, client, user); + }); }); }; diff --git a/lib/grant-types/client-credentials-grant-type.js b/lib/grant-types/client-credentials-grant-type.js index d0af0fe5..57e2a0e7 100644 --- a/lib/grant-types/client-credentials-grant-type.js +++ b/lib/grant-types/client-credentials-grant-type.js @@ -84,23 +84,26 @@ ClientCredentialsGrantType.prototype.getUserFromClient = function(client) { * Save token. */ -ClientCredentialsGrantType.prototype.saveToken = function(user, client, scope) { - const fns = [ - this.validateScope(user, client, scope), - this.generateAccessToken(client, user, scope), - this.getAccessTokenExpiresAt(client, user, scope) - ]; - - return Promise.all(fns) - .bind(this) - .spread(function(scope, accessToken, accessTokenExpiresAt) { - const token = { - accessToken: accessToken, - accessTokenExpiresAt: accessTokenExpiresAt, - scope: scope - }; - - return promisify(this.model.saveToken, 3).call(this.model, token, client, user); +ClientCredentialsGrantType.prototype.saveToken = function(user, client, requestedScope) { + return Promise.bind(this) + .then(function() { + return this.validateScope(user, client, requestedScope); + }) + .then(function(validatedScope) { + return Promise.all([ + this.generateAccessToken(client, user, validatedScope), + this.getAccessTokenExpiresAt(client, user, validatedScope) + ]) + .bind(this) + .spread(function(accessToken, accessTokenExpiresAt) { + const token = { + accessToken: accessToken, + accessTokenExpiresAt: accessTokenExpiresAt, + scope: validatedScope + }; + + return promisify(this.model.saveToken, 3).call(this.model, token, client, user); + }); }); }; diff --git a/lib/grant-types/password-grant-type.js b/lib/grant-types/password-grant-type.js index b65f9e1f..dc3462f2 100644 --- a/lib/grant-types/password-grant-type.js +++ b/lib/grant-types/password-grant-type.js @@ -102,27 +102,30 @@ PasswordGrantType.prototype.getUser = function(request) { * Save token. */ -PasswordGrantType.prototype.saveToken = function(user, client, scope) { - const fns = [ - this.validateScope(user, client, scope), - this.generateAccessToken(client, user, scope), - this.generateRefreshToken(client, user, scope), - this.getAccessTokenExpiresAt(), - this.getRefreshTokenExpiresAt() - ]; - - return Promise.all(fns) - .bind(this) - .spread(function(scope, accessToken, refreshToken, accessTokenExpiresAt, refreshTokenExpiresAt) { - const token = { - accessToken: accessToken, - accessTokenExpiresAt: accessTokenExpiresAt, - refreshToken: refreshToken, - refreshTokenExpiresAt: refreshTokenExpiresAt, - scope: scope - }; - - return promisify(this.model.saveToken, 3).call(this.model, token, client, user); +PasswordGrantType.prototype.saveToken = function(user, client, requestedScope) { + return Promise.bind(this) + .then(function () { + return this.validateScope(user, client,requestedScope); + }) + .then(function(validatedScope) { + return Promise.all([ + this.generateAccessToken(client, user, validatedScope), + this.generateRefreshToken(client, user, validatedScope), + this.getAccessTokenExpiresAt(), + this.getRefreshTokenExpiresAt() + ]) + .bind(this) + .spread(function(accessToken, refreshToken, accessTokenExpiresAt, refreshTokenExpiresAt) { + const token = { + accessToken: accessToken, + accessTokenExpiresAt: accessTokenExpiresAt, + refreshToken: refreshToken, + refreshTokenExpiresAt: refreshTokenExpiresAt, + scope: validatedScope + }; + + return promisify(this.model.saveToken, 3).call(this.model, token, client, user); + }); }); };