44
55namespace SimpleSAML \Module \oidc \Controllers \VerifiableCredentials ;
66
7+ use League \OAuth2 \Server \ResourceServer ;
8+ use SimpleSAML \Module \oidc \Bridges \PsrHttpBridge ;
79use SimpleSAML \Module \oidc \ModuleConfig ;
10+ use SimpleSAML \Module \oidc \Repositories \AccessTokenRepository ;
811use SimpleSAML \Module \oidc \Server \Exceptions \OidcServerException ;
12+ use SimpleSAML \Module \oidc \Utils \FingerprintGenerator ;
913use SimpleSAML \Module \oidc \Utils \Routes ;
14+ use SimpleSAML \OpenID \Algorithms \SignatureAlgorithmEnum ;
15+ use SimpleSAML \OpenID \Codebooks \AtContextsEnum ;
16+ use SimpleSAML \OpenID \Codebooks \ClaimsEnum ;
17+ use SimpleSAML \OpenID \Codebooks \CredentialTypesEnum ;
18+ use SimpleSAML \OpenID \Jwk ;
19+ use SimpleSAML \OpenID \VerifiableCredentials ;
20+ use Symfony \Component \HttpFoundation \Request ;
1021use Symfony \Component \HttpFoundation \Response ;
1122
1223class CredentialIssuerCredentialController
@@ -15,19 +26,81 @@ class CredentialIssuerCredentialController
1526 * @throws \SimpleSAML\Module\oidc\Server\Exceptions\OidcServerException
1627 */
1728 public function __construct (
29+ protected readonly ResourceServer $ resourceServer ,
30+ protected readonly AccessTokenRepository $ accessTokenRepository ,
1831 protected readonly ModuleConfig $ moduleConfig ,
1932 protected readonly Routes $ routes ,
33+ protected readonly PsrHttpBridge $ psrHttpBridge ,
34+ protected readonly VerifiableCredentials $ verifiableCredentials ,
35+ protected readonly Jwk $ jwk ,
2036 ) {
2137 if (!$ this ->moduleConfig ->getVerifiableCredentialEnabled ()) {
2238 throw OidcServerException::forbidden ('Verifiable Credential capabilities not enabled ' );
2339 }
2440 }
2541
26- public function credential (): Response
42+ public function credential (Request $ request ): Response
2743 {
44+ $ authorization = $ this ->resourceServer ->validateAuthenticatedRequest (
45+ $ this ->psrHttpBridge ->getPsrHttpFactory ()->createRequest ($ request ),
46+ );
47+
48+ // TODO mivanci validate
49+ $ accessToken = $ this ->accessTokenRepository ->findById ($ authorization ->getAttribute ('oauth_access_token_id ' ));
50+ if ($ accessToken ->isRevoked ()) {
51+ throw OidcServerException::accessDenied ('Access token is revoked. ' );
52+ }
53+
54+ // TODO mivanci validate requested credential identifier
55+
56+ $ jwk = $ this ->jwk ->jwkDecoratorFactory ()->fromPkcs1Or8KeyFile (
57+ $ this ->moduleConfig ->getProtocolPrivateKeyPath (),
58+ null ,
59+ );
60+
61+ $ issuedAt = new \DateTimeImmutable ();
62+
63+ $ verifiableCredential = $ this ->verifiableCredentials ->jwtVcJsonFactory ()->fromData (
64+ $ jwk ,
65+ SignatureAlgorithmEnum::RS256 ,
66+ [
67+ ClaimsEnum::Vc->value => [
68+ ClaimsEnum::AtContext->value => [
69+ AtContextsEnum::W3Org2018CredentialsV1->value ,
70+ ],
71+ ClaimsEnum::Type->value => [
72+ CredentialTypesEnum::VerifiableCredential->value ,
73+ 'ResearchAndScholarshipCredentialJwtVcJson ' ,
74+ ],
75+ ClaimsEnum::Issuer->value => $ this ->moduleConfig ->getIssuer (),
76+ ClaimsEnum::Issuance_Date->value => $ issuedAt ->format (\DateTimeInterface::RFC3339 ),
77+ ClaimsEnum::Credential_Subject->value => [
78+ 'eduPersonPrincipalName ' =>
'[email protected] ' ,
79+ 'eduPersonTargetedID ' => 'abc123 ' ,
80+ 'displayName ' => 'Test User ' ,
81+ 'givenName ' => 'Test ' ,
82+ 'sn ' => 'User ' ,
83+ 84+ 'eduPersonScopedAffiliation ' =>
'[email protected] ' ,
85+ ],
86+ ],
87+ ClaimsEnum::Iss->value => $ this ->moduleConfig ->getIssuer (),
88+ ClaimsEnum::Iat->value => $ issuedAt ->getTimestamp (),
89+ ClaimsEnum::Nbf->value => $ issuedAt ->getTimestamp (),
90+ ClaimsEnum::Sub->value => 'testuid ' ,
91+ ],
92+ [
93+ ClaimsEnum::Kid->value => FingerprintGenerator::forFile (
94+ $ this ->moduleConfig ->getProtocolCertPath (),
95+ ),
96+ ],
97+ );
98+
2899 return $ this ->routes ->newJsonResponse (
29100 [
30- 'credential ' => 'credential ' ,
101+ 'credentials ' => [
102+ 'credential ' => $ verifiableCredential ->getToken (),
103+ ],
31104 ],
32105 );
33106 }
0 commit comments