2222use LogicException ;
2323use Psr \Http \Message \ServerRequestInterface ;
2424use SimpleSAML \Module \oidc \Codebooks \FlowTypeEnum ;
25+ use SimpleSAML \Module \oidc \Entities \AuthCodeEntity ;
2526use SimpleSAML \Module \oidc \Entities \Interfaces \AccessTokenEntityInterface ;
2627use SimpleSAML \Module \oidc \Entities \Interfaces \AuthCodeEntityInterface ;
2728use SimpleSAML \Module \oidc \Entities \Interfaces \RefreshTokenEntityInterface ;
2829use SimpleSAML \Module \oidc \Entities \UserEntity ;
2930use SimpleSAML \Module \oidc \Factories \Entities \AccessTokenEntityFactory ;
3031use SimpleSAML \Module \oidc \Factories \Entities \AuthCodeEntityFactory ;
3132use SimpleSAML \Module \oidc \Helpers ;
33+ use SimpleSAML \Module \oidc \Repositories \AuthCodeRepository ;
3234use SimpleSAML \Module \oidc \Repositories \Interfaces \AccessTokenRepositoryInterface ;
3335use SimpleSAML \Module \oidc \Repositories \Interfaces \AuthCodeRepositoryInterface ;
3436use SimpleSAML \Module \oidc \Repositories \Interfaces \RefreshTokenRepositoryInterface ;
4042use SimpleSAML \Module \oidc \Server \RequestRules \Interfaces \ResultBagInterface ;
4143use SimpleSAML \Module \oidc \Server \RequestRules \RequestRulesManager ;
4244use SimpleSAML \Module \oidc \Server \RequestRules \Rules \AcrValuesRule ;
45+ use SimpleSAML \Module \oidc \Server \RequestRules \Rules \AuthorizationDetailsRule ;
4346use SimpleSAML \Module \oidc \Server \RequestRules \Rules \ClientAuthenticationRule ;
4447use SimpleSAML \Module \oidc \Server \RequestRules \Rules \ClientRule ;
4548use SimpleSAML \Module \oidc \Server \RequestRules \Rules \CodeChallengeMethodRule ;
@@ -288,6 +291,8 @@ public function completeOidcAuthorizationRequest(
288291 'claims ' => $ authorizationRequest ->getClaims (),
289292 'acr ' => $ authorizationRequest ->getAcr (),
290293 'session_id ' => $ authorizationRequest ->getSessionId (),
294+ // Do not add anything else to the payload, as it will make it dangerously long to send it as a query
295+ // parameter. Use storage instead.
291296 ];
292297
293298 $ jsonPayload = json_encode ($ payload , JSON_THROW_ON_ERROR );
@@ -338,6 +343,7 @@ protected function issueOidcAuthCode(
338343 $ redirectUri ,
339344 $ authorizationRequest ->getNonce (),
340345 flowTypeEnum: $ flowType ,
346+ authorizationDetails: $ authorizationRequest ->getAuthorizationDetails (),
341347 );
342348 $ this ->authCodeRepository ->persistNewAuthCode ($ authCode );
343349
@@ -448,7 +454,21 @@ public function respondToAccessTokenRequest(
448454 */
449455 $ authCodePayload = json_decode ($ this ->decrypt ($ encryptedAuthCode ), null , 512 , JSON_THROW_ON_ERROR );
450456
451- $ this ->validateAuthorizationCode ($ authCodePayload , $ client , $ request );
457+ if (!property_exists ($ authCodePayload , 'auth_code_id ' )) {
458+ throw OAuthServerException::invalidRequest ('code ' , 'Authorization code malformed ' );
459+ }
460+
461+ if (! is_a ($ this ->authCodeRepository , AuthCodeRepository::class)) {
462+ throw OidcServerException::serverError ('Unexpected auth code repository entity type. ' );
463+ }
464+
465+ $ storedAuthCodeEntity = $ this ->authCodeRepository ->findById ($ authCodePayload ->auth_code_id );
466+
467+ if ($ storedAuthCodeEntity === null ) {
468+ throw OAuthServerException::invalidGrant ('Authorization code not found ' );
469+ }
470+
471+ $ this ->validateAuthorizationCode ($ authCodePayload , $ client , $ request , $ storedAuthCodeEntity );
452472
453473 $ scopes = $ this ->scopeRepository ->finalizeScopes (
454474 $ this ->validateScopes ($ authCodePayload ->scopes ),
@@ -569,9 +589,6 @@ public function respondToAccessTokenRequest(
569589 $ responseType ->setRefreshToken ($ refreshToken );
570590 }
571591 }
572- if (! is_a ($ this ->authCodeRepository , AuthCodeRepositoryInterface::class)) {
573- throw OidcServerException::serverError ('Unexpected auth code repository entity type. ' );
574- }
575592
576593 // Revoke used auth code
577594 $ this ->authCodeRepository ->revokeAuthCode ($ authCodePayload ->auth_code_id );
@@ -592,20 +609,13 @@ protected function validateAuthorizationCode(
592609 object $ authCodePayload ,
593610 OAuth2ClientEntityInterface $ client ,
594611 ServerRequestInterface $ request ,
612+ AuthCodeEntity $ storedAuthCodeEntity ,
595613 ): void {
596614 /**
597615 * @noinspection PhpUndefinedClassInspection
598616 * @psalm-var AuthCodePayloadObject $authCodePayload
599617 */
600618
601- if (!property_exists ($ authCodePayload , 'auth_code_id ' )) {
602- throw OAuthServerException::invalidRequest ('code ' , 'Authorization code malformed ' );
603- }
604-
605- if (! is_a ($ this ->authCodeRepository , AuthCodeRepositoryInterface::class)) {
606- throw OidcServerException::serverError ('Unexpected auth code repository entity type. ' );
607- }
608-
609619 if (! is_a ($ this ->accessTokenRepository , AccessTokenRepositoryInterface::class)) {
610620 throw OidcServerException::serverError ('Unexpected access token repository entity type. ' );
611621 }
@@ -618,7 +628,7 @@ protected function validateAuthorizationCode(
618628 throw OAuthServerException::invalidGrant ('Authorization code has expired ' );
619629 }
620630
621- if ($ this -> authCodeRepository -> isAuthCodeRevoked ( $ authCodePayload -> auth_code_id ) === true ) {
631+ if ($ storedAuthCodeEntity -> isRevoked () ) {
622632 // Code is reused, all related tokens must be revoked, per https://tools.ietf.org/html/rfc6749#section-4.1.2
623633 $ this ->accessTokenRepository ->revokeByAuthCodeId ($ authCodePayload ->auth_code_id );
624634 $ this ->refreshTokenRepository ->revokeByAuthCodeId ($ authCodePayload ->auth_code_id );
@@ -663,6 +673,7 @@ public function validateAuthorizationRequestWithRequestRules(
663673 CodeChallengeRule::class,
664674 CodeChallengeMethodRule::class,
665675 IssuerStateRule::class,
676+ AuthorizationDetailsRule::class,
666677 ];
667678
668679 // Since we have already validated redirect_uri, and we have state, make it available for other checkers.
@@ -710,7 +721,15 @@ public function validateAuthorizationRequestWithRequestRules(
710721 $ oAuth2AuthorizationRequest ->setCodeChallengeMethod ($ codeChallengeMethod );
711722 }
712723
713- if (! $ this ->isOidcCandidate ($ oAuth2AuthorizationRequest )) {
724+ $ isVciAuthorizationCodeRequest = $ this ->requestParamsResolver ->isVciAuthorizationCodeRequest (
725+ $ request ,
726+ $ this ->allowedAuthorizationHttpMethods ,
727+ );
728+
729+ if (
730+ (! $ this ->isOidcCandidate ($ oAuth2AuthorizationRequest )) &&
731+ (! $ isVciAuthorizationCodeRequest )
732+ ) {
714733 return $ oAuth2AuthorizationRequest ;
715734 }
716735
@@ -743,17 +762,22 @@ public function validateAuthorizationRequestWithRequestRules(
743762 $ acrValues = $ resultBag ->getOrFail (AcrValuesRule::class)->getValue ();
744763 $ authorizationRequest ->setRequestedAcrValues ($ acrValues );
745764
746- $ authorizationRequest ->setIsVciRequest (
747- $ this ->requestParamsResolver ->isVciAuthorizationCodeRequest (
748- $ request ,
749- $ this ->allowedAuthorizationHttpMethods ,
750- ),
765+
766+ $ authorizationRequest ->setIsVciRequest ($ isVciAuthorizationCodeRequest );
767+ $ authorizationRequest ->setFlowType (
768+ $ isVciAuthorizationCodeRequest ?
769+ FlowTypeEnum::VciAuthorizationCode :
770+ FlowTypeEnum::OidcAuthorizationCode,
751771 );
752772
753773 /** @var ?string $issuerState */
754774 $ issuerState = $ resultBag ->get (IssuerStateRule::class)?->getValue();
755775 $ authorizationRequest ->setIssuerState ($ issuerState );
756776
777+ /** @var ?array $authorizationDetails */
778+ $ authorizationDetails = $ resultBag ->get (AuthorizationDetailsRule::class)?->getValue();
779+ $ authorizationRequest ->setAuthorizationDetails ($ authorizationDetails );
780+
757781 return $ authorizationRequest ;
758782 }
759783
0 commit comments