From 3557b43fb87fb5751215ab86438dbce69a5e28e0 Mon Sep 17 00:00:00 2001 From: Florian Kaufmann <florian.kaufmann@codecentric.de> Date: Thu, 25 Nov 2021 11:30:44 +0100 Subject: [PATCH] Verschieben der Addressinformations Validationsinformationen --- docs/getting-started/receiving/routing.mdx | 132 ------------------ .../sending/get-destination.mdx | 132 ++++++++++++++++++ .../getting-started/receiving/routing.mdx | 132 ------------------ .../sending/get-destination.mdx | 132 ++++++++++++++++++ 4 files changed, 264 insertions(+), 264 deletions(-) diff --git a/docs/getting-started/receiving/routing.mdx b/docs/getting-started/receiving/routing.mdx index f73be9a61..5f44d084a 100644 --- a/docs/getting-started/receiving/routing.mdx +++ b/docs/getting-started/receiving/routing.mdx @@ -18,135 +18,3 @@ Von der Zwischenablage können diese Informationen dann in das zuständige Redak </div> Nach der Übernahme der Adressierungsinformationen in das Redaktionssystem werden diese im Format XZuFi an das [Onlinegateway des Portalverbund (PVOG)](https://servicesuche.bund.de/) übermittelt und sind anschließend [über die Routing API abrufbar](../sending/get-destination.mdx). - -### Inhalt der Adressierungsinformationen -Der dekodierte Inhalt (Payload) der Adressierungsinformationen sieht beispielhaft wie folgt aus (Leerzeichen und Zeilenumbrüche dienen ausschließlich der besseren Lesbarkeit): -```json -{ - "submissionHost": "submission-api-testing.fit-connect.fitko.dev", - "iss": "https://portal.auth-testing.fit-connect.fitko.dev", - "services": [ - { - "gebietIDs": [ - "urn:de:bund:destatis:bevoelkerungsstatistik:schluessel:rs:12345" - ], - "leistungIDs": [ - "urn:de:fim:leika:leistung:100" - ] - } - ], - "destinationId": "0c438057-ec3e-4ce0-b154-1683b5d3c2e8", - "iat": 1637685592, - "jti": "ae37e58b-e280-4706-b99e-738f24c8d98f" -} -``` - -### Signaturprüfung der vom Self-Service Portal (SSP) signierten Adressierungsinformationen -Bei den signierten Adressierungsinformationen handelt es sich um signierte JSON Web Tokens (JWTs). -Um die Signatur der vom Self-Service-Portal signierten JWTs zu überprüfen, ist es notwendig, auf die verwendeten Schlüssel (im Format JSON Web Key, kurz JWK) zugreifen zu können. -Das Self-Service-Portal stellt ein JSON Web Key Set (JWKS) öffentlich zugänglich über den Endpunkt `/.well-known/jwks.json` bereit. -Für unser Testsystem ist das JWKS z.B. [hier](https://portal.auth-testing.fit-connect.fitko.dev/.well-known/jwks.json) verfügbar. - -Ein Beispiel für ein JWKS ist in folgendem Ausschnitt dargestellt: -```json -{ - "keys": [ - { - "alg": "PS512", - "e": "AQAB", - "key_ops": [ - "verify" - ], - "kid": "6508dbcd-ab3b-4edb-a42b-37bc69f38fed", - "kty": "RSA", - "n": "65rmDz943SDKYWt8KhmaU…ga16_y9bAdoQJZRpcRr3_v9Q" - }, - { - "alg": "PS512", - "e": "AQAB", - "key_ops": [ - "verify" - ], - "kid": "14a70431-01e6-4d67-867d-d678a3686f4b", - "kty": "RSA", - "n": "wnqKgmQHSqJhvCfdUWWyi8q…yVv3TrQVvGtsjrJVjvJR-s_D7rWoBcJVM" - } - ] -} -``` - -Mit diesem JWKS kann die Signatur der Adressierungsinformationen überprüft werden. -Hierfür muss der Schlüssel mit der passenden Schlüssel-ID (Key-ID) aus dem `kid`-Header der Adressierungsinformationen im JWKS ermittelt werden. -Dann kann man mit diesem und einer entsprechenden Bibliothek eine Signaturprüfung durchführen. - -<Tabs - defaultValue="java" - values={[ - { label: 'Java (Spring)', value: 'java', }, - ] -}> -<TabItem value="java"> - -Im folgenden Beispiel wird die Bibliothek [nimbus-jose-jwt](https://connect2id.com/products/nimbus-jose-jwt) für die Prüfung genutzt. - -```java -SignedJWT signedJWT = SignedJWT.parse(eventToken); -UUID keyId = UUID.fromString(signedJWT.getHeader().getKeyID()); - -validateTokenStructure(signedJWT); - -verifySSPSignature(signedJWT, keyId) -``` - -```java -boolean validateTokenStructure(SignedJWT signedJWT) { - try { - validateHeader(signedJWT.getHeader()); - validatePayload(signedJWT.getJWTClaimsSet()); - } catch (ParseException e) { - throw new RuntimeException("The payload of the SET could not get parsed properly."); - } -} - -private void validateHeader(JWSHeader header) { - validateTrueOrElseThrow(header.getAlgorithm() == JWSAlgorithm.PS512, "The provided alg in the SET header is not allowed."); - validateTrueOrElseThrow(header.getType().toString().equals("jwt"), "The provided typ in the SET header is not jwt"); - validateTrueOrElseThrow(header.getKeyID() != null, "The kid the SET was signed with is not set."); -} - -private void validatePayload(JWTClaimsSet payload) throws ParseException { - validateTrueOrElseThrow(payload.getClaim("iss") != null, "The claim iss is missing in the payload of the JWT."); - validateTrueOrElseThrow(payload.getClaim("iat") != null, "The claim iat is missing in the payload of the JWT."); - validateTrueOrElseThrow(payload.getClaim("jti") != null, "The claim jti is missing in the payload of the JWT."); - validateTrueOrElseThrow(payload.getClaim("destinationId") != null, "The claim destinationId is missing in the payload of the JWT."); - validateTrueOrElseThrow(payload.getClaim("submissionHost") != null, "The claim submissionHost is missing in the payload of the JWT."); - validateTrueOrElseThrow(payload.getClaim("services") != null, "The claim services is missing in the payload of the JWT."); - validateTrueOrElseThrow(payload.getJSONObjectClaim("services").keySet().size() >= 1, "At least one service is needed."); -} - -private void validateTrueOrElseThrow(boolean expression, String msg) { - if (!expression) { - throw new RuntimeException(msg); - } -} -``` - -```java -static final SSP_BASE_URL = "https://portal.auth-testing.fit-connect.fitko.dev"; - -boolean verifySSPSignature(SignedJWT signedJWT, String keyId) { - - JWKSet jwks = JWKSet.load(SSP_BASE_URL + "/.well-known/jwks.json"); - JWK publicKey = jwks.getKeyByKeyId(keyId) - - if (publicKey.getAlgorithm() != JWSAlgorithm.PS512) { - throw new RuntimeException("The key specified for signature verification doesn't use/specify PS512 as algorithm.") - } - - JWSVerifier jwsVerifier = new RSASSAVerifier(publicKey.toRSAKey()); - return signedJWT.verify(jwsVerifier); -} -``` - -</TabItem> -</Tabs> diff --git a/docs/getting-started/sending/get-destination.mdx b/docs/getting-started/sending/get-destination.mdx index 35cb1a894..3d9da4d79 100644 --- a/docs/getting-started/sending/get-destination.mdx +++ b/docs/getting-started/sending/get-destination.mdx @@ -121,6 +121,138 @@ Beispiel für die Response: } ``` +### Inhalt der Adressierungsinformationen (Parameter `destinationSignature`) +Der dekodierte Inhalt (Payload) der Adressierungsinformationen sieht beispielhaft wie folgt aus (Leerzeichen und Zeilenumbrüche dienen ausschließlich der besseren Lesbarkeit): +```json +{ + "submissionHost": "submission-api-testing.fit-connect.fitko.dev", + "iss": "https://portal.auth-testing.fit-connect.fitko.dev", + "services": [ + { + "gebietIDs": [ + "urn:de:bund:destatis:bevoelkerungsstatistik:schluessel:rs:12345" + ], + "leistungIDs": [ + "urn:de:fim:leika:leistung:100" + ] + } + ], + "destinationId": "0c438057-ec3e-4ce0-b154-1683b5d3c2e8", + "iat": 1637685592, + "jti": "ae37e58b-e280-4706-b99e-738f24c8d98f" +} +``` + +### Signaturprüfung der vom Self-Service Portal (SSP) signierten Adressierungsinformationen (Parameter `destinationSignature`) +Bei den signierten Adressierungsinformationen handelt es sich um signierte JSON Web Tokens (JWTs). +Um die Signatur der vom Self-Service-Portal signierten JWTs zu überprüfen, ist es notwendig, auf die verwendeten Schlüssel (im Format JSON Web Key, kurz JWK) zugreifen zu können. +Das Self-Service-Portal stellt ein JSON Web Key Set (JWKS) öffentlich zugänglich über den Endpunkt `/.well-known/jwks.json` bereit. +Für unser Testsystem ist das JWKS z.B. [hier](https://portal.auth-testing.fit-connect.fitko.dev/.well-known/jwks.json) verfügbar. + +Ein Beispiel für ein JWKS ist in folgendem Ausschnitt dargestellt: +```json +{ + "keys": [ + { + "alg": "PS512", + "e": "AQAB", + "key_ops": [ + "verify" + ], + "kid": "6508dbcd-ab3b-4edb-a42b-37bc69f38fed", + "kty": "RSA", + "n": "65rmDz943SDKYWt8KhmaU…ga16_y9bAdoQJZRpcRr3_v9Q" + }, + { + "alg": "PS512", + "e": "AQAB", + "key_ops": [ + "verify" + ], + "kid": "14a70431-01e6-4d67-867d-d678a3686f4b", + "kty": "RSA", + "n": "wnqKgmQHSqJhvCfdUWWyi8q…yVv3TrQVvGtsjrJVjvJR-s_D7rWoBcJVM" + } + ] +} +``` + +Mit diesem JWKS kann die Signatur der Adressierungsinformationen überprüft werden. +Hierfür muss der Schlüssel mit der passenden Schlüssel-ID (Key-ID) aus dem `kid`-Header der Adressierungsinformationen im JWKS ermittelt werden. +Dann kann man mit diesem und einer entsprechenden Bibliothek eine Signaturprüfung durchführen. + +<Tabs + defaultValue="java" + values={[ + { label: 'Java (Spring)', value: 'java', }, + ] +}> +<TabItem value="java"> + +Im folgenden Beispiel wird die Bibliothek [nimbus-jose-jwt](https://connect2id.com/products/nimbus-jose-jwt) für die Prüfung genutzt. + +```java +SignedJWT signedJWT = SignedJWT.parse(eventToken); +UUID keyId = UUID.fromString(signedJWT.getHeader().getKeyID()); + +validateTokenStructure(signedJWT); + +verifySSPSignature(signedJWT, keyId) +``` + +```java +boolean validateTokenStructure(SignedJWT signedJWT) { + try { + validateHeader(signedJWT.getHeader()); + validatePayload(signedJWT.getJWTClaimsSet()); + } catch (ParseException e) { + throw new RuntimeException("The payload of the SET could not get parsed properly."); + } +} + +private void validateHeader(JWSHeader header) { + validateTrueOrElseThrow(header.getAlgorithm() == JWSAlgorithm.PS512, "The provided alg in the SET header is not allowed."); + validateTrueOrElseThrow(header.getType().toString().equals("jwt"), "The provided typ in the SET header is not jwt"); + validateTrueOrElseThrow(header.getKeyID() != null, "The kid the SET was signed with is not set."); +} + +private void validatePayload(JWTClaimsSet payload) throws ParseException { + validateTrueOrElseThrow(payload.getClaim("iss") != null, "The claim iss is missing in the payload of the JWT."); + validateTrueOrElseThrow(payload.getClaim("iat") != null, "The claim iat is missing in the payload of the JWT."); + validateTrueOrElseThrow(payload.getClaim("jti") != null, "The claim jti is missing in the payload of the JWT."); + validateTrueOrElseThrow(payload.getClaim("destinationId") != null, "The claim destinationId is missing in the payload of the JWT."); + validateTrueOrElseThrow(payload.getClaim("submissionHost") != null, "The claim submissionHost is missing in the payload of the JWT."); + validateTrueOrElseThrow(payload.getClaim("services") != null, "The claim services is missing in the payload of the JWT."); + validateTrueOrElseThrow(payload.getJSONObjectClaim("services").keySet().size() >= 1, "At least one service is needed."); +} + +private void validateTrueOrElseThrow(boolean expression, String msg) { + if (!expression) { + throw new RuntimeException(msg); + } +} +``` + +```java +static final SSP_BASE_URL = "https://portal.auth-testing.fit-connect.fitko.dev"; + +boolean verifySSPSignature(SignedJWT signedJWT, String keyId) { + + JWKSet jwks = JWKSet.load(SSP_BASE_URL + "/.well-known/jwks.json"); + JWK publicKey = jwks.getKeyByKeyId(keyId) + + if (publicKey.getAlgorithm() != JWSAlgorithm.PS512) { + throw new RuntimeException("The key specified for signature verification doesn't use/specify PS512 as algorithm.") + } + + JWSVerifier jwsVerifier = new RSASSAVerifier(publicKey.toRSAKey()); + return signedJWT.verify(jwsVerifier); +} +``` + +</TabItem> +</Tabs> + :::note Hinweis Sofern eine Destination-ID und die Adresse des zuständigen Zustelldienstes bereits bekannt sind, können die in einem Zustellpunkt hinterlegten technischen Parameter auch über den Endpunkt <ApiLink to="/v1/destinations/{destinationId}" /> der Submission API des zuständigen Zustelldienstes angefragt werden. ::: diff --git a/versioned_docs/version-FIT-Connect_v1/getting-started/receiving/routing.mdx b/versioned_docs/version-FIT-Connect_v1/getting-started/receiving/routing.mdx index f73be9a61..5f44d084a 100644 --- a/versioned_docs/version-FIT-Connect_v1/getting-started/receiving/routing.mdx +++ b/versioned_docs/version-FIT-Connect_v1/getting-started/receiving/routing.mdx @@ -18,135 +18,3 @@ Von der Zwischenablage können diese Informationen dann in das zuständige Redak </div> Nach der Übernahme der Adressierungsinformationen in das Redaktionssystem werden diese im Format XZuFi an das [Onlinegateway des Portalverbund (PVOG)](https://servicesuche.bund.de/) übermittelt und sind anschließend [über die Routing API abrufbar](../sending/get-destination.mdx). - -### Inhalt der Adressierungsinformationen -Der dekodierte Inhalt (Payload) der Adressierungsinformationen sieht beispielhaft wie folgt aus (Leerzeichen und Zeilenumbrüche dienen ausschließlich der besseren Lesbarkeit): -```json -{ - "submissionHost": "submission-api-testing.fit-connect.fitko.dev", - "iss": "https://portal.auth-testing.fit-connect.fitko.dev", - "services": [ - { - "gebietIDs": [ - "urn:de:bund:destatis:bevoelkerungsstatistik:schluessel:rs:12345" - ], - "leistungIDs": [ - "urn:de:fim:leika:leistung:100" - ] - } - ], - "destinationId": "0c438057-ec3e-4ce0-b154-1683b5d3c2e8", - "iat": 1637685592, - "jti": "ae37e58b-e280-4706-b99e-738f24c8d98f" -} -``` - -### Signaturprüfung der vom Self-Service Portal (SSP) signierten Adressierungsinformationen -Bei den signierten Adressierungsinformationen handelt es sich um signierte JSON Web Tokens (JWTs). -Um die Signatur der vom Self-Service-Portal signierten JWTs zu überprüfen, ist es notwendig, auf die verwendeten Schlüssel (im Format JSON Web Key, kurz JWK) zugreifen zu können. -Das Self-Service-Portal stellt ein JSON Web Key Set (JWKS) öffentlich zugänglich über den Endpunkt `/.well-known/jwks.json` bereit. -Für unser Testsystem ist das JWKS z.B. [hier](https://portal.auth-testing.fit-connect.fitko.dev/.well-known/jwks.json) verfügbar. - -Ein Beispiel für ein JWKS ist in folgendem Ausschnitt dargestellt: -```json -{ - "keys": [ - { - "alg": "PS512", - "e": "AQAB", - "key_ops": [ - "verify" - ], - "kid": "6508dbcd-ab3b-4edb-a42b-37bc69f38fed", - "kty": "RSA", - "n": "65rmDz943SDKYWt8KhmaU…ga16_y9bAdoQJZRpcRr3_v9Q" - }, - { - "alg": "PS512", - "e": "AQAB", - "key_ops": [ - "verify" - ], - "kid": "14a70431-01e6-4d67-867d-d678a3686f4b", - "kty": "RSA", - "n": "wnqKgmQHSqJhvCfdUWWyi8q…yVv3TrQVvGtsjrJVjvJR-s_D7rWoBcJVM" - } - ] -} -``` - -Mit diesem JWKS kann die Signatur der Adressierungsinformationen überprüft werden. -Hierfür muss der Schlüssel mit der passenden Schlüssel-ID (Key-ID) aus dem `kid`-Header der Adressierungsinformationen im JWKS ermittelt werden. -Dann kann man mit diesem und einer entsprechenden Bibliothek eine Signaturprüfung durchführen. - -<Tabs - defaultValue="java" - values={[ - { label: 'Java (Spring)', value: 'java', }, - ] -}> -<TabItem value="java"> - -Im folgenden Beispiel wird die Bibliothek [nimbus-jose-jwt](https://connect2id.com/products/nimbus-jose-jwt) für die Prüfung genutzt. - -```java -SignedJWT signedJWT = SignedJWT.parse(eventToken); -UUID keyId = UUID.fromString(signedJWT.getHeader().getKeyID()); - -validateTokenStructure(signedJWT); - -verifySSPSignature(signedJWT, keyId) -``` - -```java -boolean validateTokenStructure(SignedJWT signedJWT) { - try { - validateHeader(signedJWT.getHeader()); - validatePayload(signedJWT.getJWTClaimsSet()); - } catch (ParseException e) { - throw new RuntimeException("The payload of the SET could not get parsed properly."); - } -} - -private void validateHeader(JWSHeader header) { - validateTrueOrElseThrow(header.getAlgorithm() == JWSAlgorithm.PS512, "The provided alg in the SET header is not allowed."); - validateTrueOrElseThrow(header.getType().toString().equals("jwt"), "The provided typ in the SET header is not jwt"); - validateTrueOrElseThrow(header.getKeyID() != null, "The kid the SET was signed with is not set."); -} - -private void validatePayload(JWTClaimsSet payload) throws ParseException { - validateTrueOrElseThrow(payload.getClaim("iss") != null, "The claim iss is missing in the payload of the JWT."); - validateTrueOrElseThrow(payload.getClaim("iat") != null, "The claim iat is missing in the payload of the JWT."); - validateTrueOrElseThrow(payload.getClaim("jti") != null, "The claim jti is missing in the payload of the JWT."); - validateTrueOrElseThrow(payload.getClaim("destinationId") != null, "The claim destinationId is missing in the payload of the JWT."); - validateTrueOrElseThrow(payload.getClaim("submissionHost") != null, "The claim submissionHost is missing in the payload of the JWT."); - validateTrueOrElseThrow(payload.getClaim("services") != null, "The claim services is missing in the payload of the JWT."); - validateTrueOrElseThrow(payload.getJSONObjectClaim("services").keySet().size() >= 1, "At least one service is needed."); -} - -private void validateTrueOrElseThrow(boolean expression, String msg) { - if (!expression) { - throw new RuntimeException(msg); - } -} -``` - -```java -static final SSP_BASE_URL = "https://portal.auth-testing.fit-connect.fitko.dev"; - -boolean verifySSPSignature(SignedJWT signedJWT, String keyId) { - - JWKSet jwks = JWKSet.load(SSP_BASE_URL + "/.well-known/jwks.json"); - JWK publicKey = jwks.getKeyByKeyId(keyId) - - if (publicKey.getAlgorithm() != JWSAlgorithm.PS512) { - throw new RuntimeException("The key specified for signature verification doesn't use/specify PS512 as algorithm.") - } - - JWSVerifier jwsVerifier = new RSASSAVerifier(publicKey.toRSAKey()); - return signedJWT.verify(jwsVerifier); -} -``` - -</TabItem> -</Tabs> diff --git a/versioned_docs/version-FIT-Connect_v1/getting-started/sending/get-destination.mdx b/versioned_docs/version-FIT-Connect_v1/getting-started/sending/get-destination.mdx index 35cb1a894..3d9da4d79 100644 --- a/versioned_docs/version-FIT-Connect_v1/getting-started/sending/get-destination.mdx +++ b/versioned_docs/version-FIT-Connect_v1/getting-started/sending/get-destination.mdx @@ -121,6 +121,138 @@ Beispiel für die Response: } ``` +### Inhalt der Adressierungsinformationen (Parameter `destinationSignature`) +Der dekodierte Inhalt (Payload) der Adressierungsinformationen sieht beispielhaft wie folgt aus (Leerzeichen und Zeilenumbrüche dienen ausschließlich der besseren Lesbarkeit): +```json +{ + "submissionHost": "submission-api-testing.fit-connect.fitko.dev", + "iss": "https://portal.auth-testing.fit-connect.fitko.dev", + "services": [ + { + "gebietIDs": [ + "urn:de:bund:destatis:bevoelkerungsstatistik:schluessel:rs:12345" + ], + "leistungIDs": [ + "urn:de:fim:leika:leistung:100" + ] + } + ], + "destinationId": "0c438057-ec3e-4ce0-b154-1683b5d3c2e8", + "iat": 1637685592, + "jti": "ae37e58b-e280-4706-b99e-738f24c8d98f" +} +``` + +### Signaturprüfung der vom Self-Service Portal (SSP) signierten Adressierungsinformationen (Parameter `destinationSignature`) +Bei den signierten Adressierungsinformationen handelt es sich um signierte JSON Web Tokens (JWTs). +Um die Signatur der vom Self-Service-Portal signierten JWTs zu überprüfen, ist es notwendig, auf die verwendeten Schlüssel (im Format JSON Web Key, kurz JWK) zugreifen zu können. +Das Self-Service-Portal stellt ein JSON Web Key Set (JWKS) öffentlich zugänglich über den Endpunkt `/.well-known/jwks.json` bereit. +Für unser Testsystem ist das JWKS z.B. [hier](https://portal.auth-testing.fit-connect.fitko.dev/.well-known/jwks.json) verfügbar. + +Ein Beispiel für ein JWKS ist in folgendem Ausschnitt dargestellt: +```json +{ + "keys": [ + { + "alg": "PS512", + "e": "AQAB", + "key_ops": [ + "verify" + ], + "kid": "6508dbcd-ab3b-4edb-a42b-37bc69f38fed", + "kty": "RSA", + "n": "65rmDz943SDKYWt8KhmaU…ga16_y9bAdoQJZRpcRr3_v9Q" + }, + { + "alg": "PS512", + "e": "AQAB", + "key_ops": [ + "verify" + ], + "kid": "14a70431-01e6-4d67-867d-d678a3686f4b", + "kty": "RSA", + "n": "wnqKgmQHSqJhvCfdUWWyi8q…yVv3TrQVvGtsjrJVjvJR-s_D7rWoBcJVM" + } + ] +} +``` + +Mit diesem JWKS kann die Signatur der Adressierungsinformationen überprüft werden. +Hierfür muss der Schlüssel mit der passenden Schlüssel-ID (Key-ID) aus dem `kid`-Header der Adressierungsinformationen im JWKS ermittelt werden. +Dann kann man mit diesem und einer entsprechenden Bibliothek eine Signaturprüfung durchführen. + +<Tabs + defaultValue="java" + values={[ + { label: 'Java (Spring)', value: 'java', }, + ] +}> +<TabItem value="java"> + +Im folgenden Beispiel wird die Bibliothek [nimbus-jose-jwt](https://connect2id.com/products/nimbus-jose-jwt) für die Prüfung genutzt. + +```java +SignedJWT signedJWT = SignedJWT.parse(eventToken); +UUID keyId = UUID.fromString(signedJWT.getHeader().getKeyID()); + +validateTokenStructure(signedJWT); + +verifySSPSignature(signedJWT, keyId) +``` + +```java +boolean validateTokenStructure(SignedJWT signedJWT) { + try { + validateHeader(signedJWT.getHeader()); + validatePayload(signedJWT.getJWTClaimsSet()); + } catch (ParseException e) { + throw new RuntimeException("The payload of the SET could not get parsed properly."); + } +} + +private void validateHeader(JWSHeader header) { + validateTrueOrElseThrow(header.getAlgorithm() == JWSAlgorithm.PS512, "The provided alg in the SET header is not allowed."); + validateTrueOrElseThrow(header.getType().toString().equals("jwt"), "The provided typ in the SET header is not jwt"); + validateTrueOrElseThrow(header.getKeyID() != null, "The kid the SET was signed with is not set."); +} + +private void validatePayload(JWTClaimsSet payload) throws ParseException { + validateTrueOrElseThrow(payload.getClaim("iss") != null, "The claim iss is missing in the payload of the JWT."); + validateTrueOrElseThrow(payload.getClaim("iat") != null, "The claim iat is missing in the payload of the JWT."); + validateTrueOrElseThrow(payload.getClaim("jti") != null, "The claim jti is missing in the payload of the JWT."); + validateTrueOrElseThrow(payload.getClaim("destinationId") != null, "The claim destinationId is missing in the payload of the JWT."); + validateTrueOrElseThrow(payload.getClaim("submissionHost") != null, "The claim submissionHost is missing in the payload of the JWT."); + validateTrueOrElseThrow(payload.getClaim("services") != null, "The claim services is missing in the payload of the JWT."); + validateTrueOrElseThrow(payload.getJSONObjectClaim("services").keySet().size() >= 1, "At least one service is needed."); +} + +private void validateTrueOrElseThrow(boolean expression, String msg) { + if (!expression) { + throw new RuntimeException(msg); + } +} +``` + +```java +static final SSP_BASE_URL = "https://portal.auth-testing.fit-connect.fitko.dev"; + +boolean verifySSPSignature(SignedJWT signedJWT, String keyId) { + + JWKSet jwks = JWKSet.load(SSP_BASE_URL + "/.well-known/jwks.json"); + JWK publicKey = jwks.getKeyByKeyId(keyId) + + if (publicKey.getAlgorithm() != JWSAlgorithm.PS512) { + throw new RuntimeException("The key specified for signature verification doesn't use/specify PS512 as algorithm.") + } + + JWSVerifier jwsVerifier = new RSASSAVerifier(publicKey.toRSAKey()); + return signedJWT.verify(jwsVerifier); +} +``` + +</TabItem> +</Tabs> + :::note Hinweis Sofern eine Destination-ID und die Adresse des zuständigen Zustelldienstes bereits bekannt sind, können die in einem Zustellpunkt hinterlegten technischen Parameter auch über den Endpunkt <ApiLink to="/v1/destinations/{destinationId}" /> der Submission API des zuständigen Zustelldienstes angefragt werden. ::: -- GitLab