@@ -21,6 +21,7 @@ const UnauthorizedClientError = require('../errors/unauthorized-client-error');
2121const isFormat = require ( '@node-oauth/formats' ) ;
2222const tokenUtil = require ( '../utils/token-util' ) ;
2323const url = require ( 'url' ) ;
24+ const pkce = require ( '../pkce/pkce' ) ;
2425
2526/**
2627 * Response types.
@@ -77,10 +78,6 @@ AuthorizeHandler.prototype.handle = function(request, response) {
7778 throw new InvalidArgumentError ( 'Invalid argument: `response` must be an instance of Response' ) ;
7879 }
7980
80- if ( request . query . allowed === 'false' || request . body . allowed === 'false' ) {
81- return Promise . reject ( new AccessDeniedError ( 'Access denied: user denied access to application' ) ) ;
82- }
83-
8481 const fns = [
8582 this . getAuthorizationCodeLifetime ( ) ,
8683 this . getClient ( request ) ,
@@ -98,7 +95,7 @@ AuthorizeHandler.prototype.handle = function(request, response) {
9895 return Promise . bind ( this )
9996 . then ( function ( ) {
10097 state = this . getState ( request ) ;
101- if ( request . query . allowed === 'false' ) {
98+ if ( request . query . allowed === 'false' || request . body . allowed === 'false' ) {
10299 throw new AccessDeniedError ( 'Access denied: user denied access to application' ) ;
103100 }
104101 } )
@@ -114,8 +111,10 @@ AuthorizeHandler.prototype.handle = function(request, response) {
114111 } )
115112 . then ( function ( authorizationCode ) {
116113 ResponseType = this . getResponseType ( request ) ;
114+ const codeChallenge = this . getCodeChallenge ( request ) ;
115+ const codeChallengeMethod = this . getCodeChallengeMethod ( request ) ;
117116
118- return this . saveAuthorizationCode ( authorizationCode , expiresAt , scope , client , uri , user ) ;
117+ return this . saveAuthorizationCode ( authorizationCode , expiresAt , scope , client , uri , user , codeChallenge , codeChallengeMethod ) ;
119118 } )
120119 . then ( function ( code ) {
121120 const responseType = new ResponseType ( code . authorizationCode ) ;
@@ -293,13 +292,20 @@ AuthorizeHandler.prototype.getRedirectUri = function(request, client) {
293292 * Save authorization code.
294293 */
295294
296- AuthorizeHandler . prototype . saveAuthorizationCode = function ( authorizationCode , expiresAt , scope , client , redirectUri , user ) {
297- const code = {
295+ AuthorizeHandler . prototype . saveAuthorizationCode = function ( authorizationCode , expiresAt , scope , client , redirectUri , user , codeChallenge , codeChallengeMethod ) {
296+ let code = {
298297 authorizationCode : authorizationCode ,
299298 expiresAt : expiresAt ,
300299 redirectUri : redirectUri ,
301300 scope : scope
302301 } ;
302+
303+ if ( codeChallenge && codeChallengeMethod ) {
304+ code = Object . assign ( {
305+ codeChallenge : codeChallenge ,
306+ codeChallengeMethod : codeChallengeMethod
307+ } , code ) ;
308+ }
303309 return promisify ( this . model . saveAuthorizationCode , 3 ) . call ( this . model , code , client , user ) ;
304310} ;
305311
@@ -369,6 +375,27 @@ AuthorizeHandler.prototype.updateResponse = function(response, redirectUri, stat
369375 response . redirect ( url . format ( redirectUri ) ) ;
370376} ;
371377
378+ AuthorizeHandler . prototype . getCodeChallenge = function ( request ) {
379+ return request . body . code_challenge ;
380+ } ;
381+
382+ /**
383+ * Get code challenge method from request or defaults to plain.
384+ * https://www.rfc-editor.org/rfc/rfc7636#section-4.3
385+ *
386+ * @throws {InvalidRequestError } if request contains unsupported code_challenge_method
387+ * (see https://www.rfc-editor.org/rfc/rfc7636#section-4.4)
388+ */
389+ AuthorizeHandler . prototype . getCodeChallengeMethod = function ( request ) {
390+ const algorithm = request . body . code_challenge_method ;
391+
392+ if ( algorithm && ! pkce . isValidMethod ( algorithm ) ) {
393+ throw new InvalidRequestError ( `Invalid request: transform algorithm '${ algorithm } ' not supported` ) ;
394+ }
395+
396+ return algorithm || 'plain' ;
397+ } ;
398+
372399/**
373400 * Export constructor.
374401 */
0 commit comments