44
55namespace SimpleSAML \Module \oidc \Server \RequestRules \Rules ;
66
7- use Lcobucci \JWT \Configuration ;
8- use Lcobucci \JWT \Signer \Key \InMemory ;
9- use Lcobucci \JWT \Validation \Constraint \IssuedBy ;
10- use Lcobucci \JWT \Validation \Constraint \SignedWith ;
117use Psr \Http \Message \ServerRequestInterface ;
12- use SimpleSAML \Module \oidc \Factories \CryptKeyFactory ;
138use SimpleSAML \Module \oidc \Helpers ;
149use SimpleSAML \Module \oidc \ModuleConfig ;
1510use SimpleSAML \Module \oidc \Server \Exceptions \OidcServerException ;
2015use SimpleSAML \Module \oidc \Utils \RequestParamsResolver ;
2116use SimpleSAML \OpenID \Codebooks \HttpMethodsEnum ;
2217use SimpleSAML \OpenID \Codebooks \ParamsEnum ;
23- use Throwable ;
18+ use SimpleSAML \OpenID \Core ;
19+ use SimpleSAML \OpenID \Jwks ;
2420
2521class IdTokenHintRule extends AbstractRule
2622{
2723 public function __construct (
2824 RequestParamsResolver $ requestParamsResolver ,
2925 Helpers $ helpers ,
30- protected ModuleConfig $ moduleConfig ,
31- protected CryptKeyFactory $ cryptKeyFactory ,
26+ protected readonly ModuleConfig $ moduleConfig ,
27+ protected readonly Jwks $ jwks ,
28+ protected readonly Core $ core ,
3229 ) {
3330 parent ::__construct ($ requestParamsResolver , $ helpers );
3431 }
@@ -58,16 +55,6 @@ public function checkRule(
5855 return new Result ($ this ->getKey (), $ idTokenHintParam );
5956 }
6057
61- // TODO v7 mivanci Fix: unmockable services... inject instead.
62- $ privateKey = $ this ->cryptKeyFactory ->buildPrivateKey ();
63- $ publicKey = $ this ->cryptKeyFactory ->buildPublicKey ();
64- /** @psalm-suppress ArgumentTypeCoercion */
65- $ jwtConfig = Configuration::forAsymmetricSigner (
66- $ this ->moduleConfig ->getProtocolSigner (),
67- InMemory::plainText ($ privateKey ->getKeyContents (), $ privateKey ->getPassPhrase () ?? '' ),
68- InMemory::plainText ($ publicKey ->getKeyContents ()),
69- );
70-
7158 if (empty ($ idTokenHintParam )) {
7259 throw OidcServerException::invalidRequest (
7360 ParamsEnum::IdTokenHint->value ,
@@ -78,23 +65,25 @@ public function checkRule(
7865 );
7966 }
8067
81- try {
82- /** @var \Lcobucci\JWT\UnencryptedToken $idTokenHint */
83- $ idTokenHint = $ jwtConfig ->parser ()->parse ($ idTokenHintParam );
68+ $ jwks = $ this ->jwks ->jwksDecoratorFactory ()->fromJwkDecorators (
69+ ...$ this ->moduleConfig ->getProtocolSignatureKeyPairBag ()->getAllPublicKeys (),
70+ )->jsonSerialize ();
71+
72+ $ idTokenHint = $ this ->core ->idTokenFactory ()->fromToken ($ idTokenHintParam );
8473
85- /** @psalm-suppress ArgumentTypeCoercion */
86- $ jwtConfig ->validator ()->assert (
87- $ idTokenHint ,
88- new IssuedBy ($ this ->moduleConfig ->getIssuer ()),
89- // Note: although logout spec does not mention it, validating signature seems like an important check
90- // to make. However, checking the signature in a key roll-over scenario will fail for ID tokens
91- // signed with previous key...
92- new SignedWith (
93- $ this ->moduleConfig ->getProtocolSigner (),
94- InMemory::plainText ($ publicKey ->getKeyContents ()),
95- ),
74+ if ($ idTokenHint ->getIssuer () !== $ this ->moduleConfig ->getIssuer ()) {
75+ throw OidcServerException::invalidRequest (
76+ ParamsEnum::IdTokenHint->value ,
77+ 'Invalid ID Token Hint Issuer ' ,
78+ null ,
79+ null ,
80+ $ state ,
9681 );
97- } catch (Throwable $ exception ) {
82+ }
83+
84+ try {
85+ $ idTokenHint ->verifyWithKeySet ($ jwks );
86+ } catch (\Throwable $ exception ) {
9887 throw OidcServerException::invalidRequest (
9988 ParamsEnum::IdTokenHint->value ,
10089 $ exception ->getMessage (),
@@ -104,6 +93,7 @@ public function checkRule(
10493 );
10594 }
10695
96+
10797 return new Result ($ this ->getKey (), $ idTokenHint );
10898 }
10999}
0 commit comments