Skip to content

Commit 2fcedc0

Browse files
NFC-46 Delegate supports() in AuthTokenValidatorImpl to tokenValidatorFactory. Refactor AuthTokenV11Validator to extend AuthTokenV1Validator and delegate common validation logic. Delegate parsing to format-specific validators via factory
1 parent be722c1 commit 2fcedc0

File tree

6 files changed

+74
-50
lines changed

6 files changed

+74
-50
lines changed

src/main/java/eu/webeid/security/validator/AuthTokenV11Validator.java

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,46 @@
66
import eu.webeid.security.exceptions.AuthTokenException;
77
import eu.webeid.security.exceptions.AuthTokenParseException;
88
import eu.webeid.security.validator.certvalidators.SubjectCertificateValidatorBatch;
9+
import eu.webeid.security.validator.ocsp.OcspClient;
10+
import eu.webeid.security.validator.ocsp.OcspServiceProvider;
911

12+
import java.security.cert.CertStore;
13+
import java.security.cert.TrustAnchor;
1014
import java.security.cert.X509Certificate;
1115
import java.util.List;
1216
import java.util.Set;
13-
import java.util.function.Supplier;
1417

1518
import static eu.webeid.security.util.Strings.isNullOrEmpty;
1619

17-
public final class AuthTokenV11Validator implements AuthTokenValidator {
20+
final class AuthTokenV11Validator extends AuthTokenV1Validator {
1821

1922
private static final String SUPPORTED_PREFIX = "web-eid:1.1";
2023

21-
private final SubjectCertificateValidatorBatch simpleSubjectCertificateValidators;
22-
private final Supplier<SubjectCertificateValidatorBatch> certTrustValidatorsSupplier;
23-
private final AuthTokenSignatureValidator authTokenSignatureValidator;
24-
2524
public AuthTokenV11Validator(
2625
SubjectCertificateValidatorBatch simpleSubjectCertificateValidators,
27-
Supplier<SubjectCertificateValidatorBatch> certTrustValidatorsSupplier,
28-
AuthTokenSignatureValidator authTokenSignatureValidator
26+
Set<TrustAnchor> trustedCACertificateAnchors,
27+
CertStore trustedCACertificateCertStore,
28+
AuthTokenSignatureValidator authTokenSignatureValidator,
29+
AuthTokenValidationConfiguration configuration,
30+
OcspClient ocspClient,
31+
OcspServiceProvider ocspServiceProvider
2932
) {
30-
this.simpleSubjectCertificateValidators = simpleSubjectCertificateValidators;
31-
this.certTrustValidatorsSupplier = certTrustValidatorsSupplier;
32-
this.authTokenSignatureValidator = authTokenSignatureValidator;
33+
super(
34+
simpleSubjectCertificateValidators,
35+
trustedCACertificateAnchors,
36+
trustedCACertificateCertStore,
37+
authTokenSignatureValidator,
38+
configuration,
39+
ocspClient,
40+
ocspServiceProvider
41+
);
3342
}
3443

3544
@Override
3645
public boolean supports(String format) {
3746
return format != null && format.startsWith(SUPPORTED_PREFIX);
3847
}
3948

40-
@Override
41-
public WebEidAuthToken parse(String authToken) throws AuthTokenException {
42-
throw new UnsupportedOperationException("Parsing is handled by AuthTokenValidatorImpl. " + this.getClass().getSimpleName() + " only supports validation.");
43-
}
44-
4549
@Override
4650
public X509Certificate validate(WebEidAuthToken token, String currentChallengeNonce) throws AuthTokenException {
4751
if (token.getFormat() == null || !token.getFormat().startsWith(SUPPORTED_PREFIX)) {
@@ -65,17 +69,7 @@ public X509Certificate validate(WebEidAuthToken token, String currentChallengeNo
6569
throw new AuthTokenParseException("Signing certificate subject does not match authentication certificate subject");
6670
}
6771

68-
simpleSubjectCertificateValidators.executeFor(signingCertificate);
69-
certTrustValidatorsSupplier.get().executeFor(signingCertificate);
70-
71-
authTokenSignatureValidator.validate(
72-
token.getAlgorithm(),
73-
token.getSignature(),
74-
signingCertificate.getPublicKey(),
75-
currentChallengeNonce
76-
);
77-
78-
return subjectCertificate;
72+
return super.validate(token, currentChallengeNonce);
7973
}
8074

8175
private static void validateSupportedSignatureAlgorithms(List<SupportedSignatureAlgorithm> algorithms) throws AuthTokenParseException {

src/main/java/eu/webeid/security/validator/AuthTokenV1Validator.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package eu.webeid.security.validator;
22

3+
import com.fasterxml.jackson.databind.ObjectMapper;
34
import eu.webeid.security.authtoken.WebEidAuthToken;
45
import eu.webeid.security.certificate.CertificateLoader;
56
import eu.webeid.security.exceptions.AuthTokenException;
@@ -10,14 +11,15 @@
1011
import eu.webeid.security.validator.ocsp.OcspClient;
1112
import eu.webeid.security.validator.ocsp.OcspServiceProvider;
1213

14+
import java.io.IOException;
1315
import java.security.cert.CertStore;
1416
import java.security.cert.TrustAnchor;
1517
import java.security.cert.X509Certificate;
1618
import java.util.Set;
1719

18-
public final class AuthTokenV1Validator implements AuthTokenValidator {
20+
class AuthTokenV1Validator implements AuthTokenValidator {
1921

20-
private static final String SUPPORTED_TOKEN_FORMAT_VERSION = "web-eid:1";
22+
protected static final String SUPPORTED_TOKEN_FORMAT_VERSION = "web-eid:1";
2123

2224
private final SubjectCertificateValidatorBatch simpleSubjectCertificateValidators;
2325
private final Set<TrustAnchor> trustedCACertificateAnchors;
@@ -52,7 +54,15 @@ public boolean supports(String format) {
5254

5355
@Override
5456
public WebEidAuthToken parse(String authToken) throws AuthTokenException {
55-
throw new UnsupportedOperationException("Parsing is handled by AuthTokenValidatorImpl. " + this.getClass().getSimpleName() + " only supports validation.");
57+
try {
58+
final WebEidAuthToken token = new ObjectMapper().readValue(authToken, WebEidAuthToken.class);
59+
if (token == null) {
60+
throw new AuthTokenParseException("Web eID authentication token is null");
61+
}
62+
return token;
63+
} catch (IOException e) {
64+
throw new AuthTokenParseException("Error parsing Web eID authentication token", e);
65+
}
5666
}
5767

5868
@Override

src/main/java/eu/webeid/security/validator/AuthTokenValidatorFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import java.util.List;
66

7+
import static eu.webeid.security.validator.AuthTokenV1Validator.SUPPORTED_TOKEN_FORMAT_VERSION;
8+
79
public final class AuthTokenValidatorFactory {
810
private final List<AuthTokenValidator> validators;
911

@@ -15,6 +17,6 @@ public AuthTokenValidator requireFor(String format) throws AuthTokenParseExcepti
1517
return validators.stream()
1618
.filter(v -> v.supports(format))
1719
.findFirst()
18-
.orElseThrow(() -> new AuthTokenParseException("Only token format version 'web-eid:1' is currently supported"));
20+
.orElseThrow(() -> new AuthTokenParseException("Only token format version '" + SUPPORTED_TOKEN_FORMAT_VERSION + "' is currently supported"));
1921
}
2022
}

src/main/java/eu/webeid/security/validator/AuthTokenValidatorImpl.java

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,12 @@ final class AuthTokenValidatorImpl implements AuthTokenValidator {
8888
this.tokenValidatorFactory = new AuthTokenValidatorFactory(List.of(
8989
new AuthTokenV11Validator(
9090
simpleSubjectCertificateValidators,
91-
() -> AuthTokenV1Validator.createCertTrustValidators(
92-
copiedConfig,
93-
trustedCACertificateAnchors,
94-
trustedCACertificateCertStore,
95-
ocspClient,
96-
ocspServiceProvider
97-
),
98-
authTokenSignatureValidator
91+
trustedCACertificateAnchors,
92+
trustedCACertificateCertStore,
93+
authTokenSignatureValidator,
94+
copiedConfig,
95+
ocspClient,
96+
ocspServiceProvider
9997
),
10098
new AuthTokenV1Validator(
10199
simpleSubjectCertificateValidators,
@@ -111,15 +109,21 @@ final class AuthTokenValidatorImpl implements AuthTokenValidator {
111109

112110
@Override
113111
public boolean supports(String format) {
114-
throw new UnsupportedOperationException("AuthTokenValidatorImpl is not format-specific. Use format-specific validators instead.");
112+
try {
113+
tokenValidatorFactory.requireFor(format);
114+
return true;
115+
} catch (AuthTokenParseException e) {
116+
return false;
117+
}
115118
}
116119

117120
@Override
118121
public WebEidAuthToken parse(String authToken) throws AuthTokenException {
119122
try {
120123
LOG.info("Starting token parsing");
121124
validateTokenLength(authToken);
122-
return parseToken(authToken);
125+
WebEidAuthToken token = parseToken(authToken);
126+
return tokenValidatorFactory.requireFor(token.getFormat()).parse(authToken);
123127
} catch (Exception e) {
124128
// Generally "log and rethrow" is an anti-pattern, but it fits with the surrounding logging style.
125129
LOG.warn("Token parsing was interrupted:", e);

src/test/java/eu/webeid/security/validator/AuthTokenStructureTest.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222

2323
package eu.webeid.security.validator;
2424

25-
import eu.webeid.security.authtoken.WebEidAuthToken;
26-
import eu.webeid.security.exceptions.AuthTokenException;
2725
import eu.webeid.security.exceptions.AuthTokenParseException;
2826
import eu.webeid.security.testutil.AbstractTestWithValidator;
2927
import org.junit.jupiter.api.Test;
@@ -65,10 +63,8 @@ void whenTokenTooLong_thenParsingFails() {
6563
}
6664

6765
@Test
68-
void whenUnknownTokenVersion_thenParsingFails() throws AuthTokenException {
69-
final WebEidAuthToken token = replaceTokenField(VALID_AUTH_TOKEN, "web-eid:1", "invalid");
70-
assertThatThrownBy(() -> validator
71-
.validate(token, ""))
66+
void whenUnknownTokenVersion_thenParsingFails() {
67+
assertThatThrownBy(() -> replaceTokenField(VALID_AUTH_TOKEN, "web-eid:1", "invalid"))
7268
.isInstanceOf(AuthTokenParseException.class)
7369
.hasMessage("Only token format version 'web-eid:1' is currently supported");
7470
}

src/test/java/eu/webeid/security/validator/AuthTokenV11ValidatorTest.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@
22

33
import eu.webeid.security.authtoken.WebEidAuthToken;
44
import eu.webeid.security.validator.certvalidators.SubjectCertificateValidatorBatch;
5+
import eu.webeid.security.validator.ocsp.OcspClient;
6+
import eu.webeid.security.validator.ocsp.OcspServiceProvider;
57
import org.junit.jupiter.api.BeforeEach;
68
import org.junit.jupiter.api.Test;
79
import org.junit.jupiter.params.ParameterizedTest;
810
import org.junit.jupiter.params.provider.NullAndEmptySource;
911
import org.junit.jupiter.params.provider.ValueSource;
1012

11-
import java.util.function.Supplier;
13+
import java.security.cert.CertStore;
14+
import java.security.cert.TrustAnchor;
15+
import java.util.Collections;
16+
import java.util.Set;
1217

1318
import static org.assertj.core.api.Assertions.assertThat;
1419
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -24,9 +29,22 @@ class AuthTokenV11ValidatorTest {
2429
@BeforeEach
2530
void setUp() {
2631
SubjectCertificateValidatorBatch scvb = mock(SubjectCertificateValidatorBatch.class);
27-
Supplier<SubjectCertificateValidatorBatch> trustSupplier = () -> mock(SubjectCertificateValidatorBatch.class);
32+
Set<TrustAnchor> trustAnchors = Collections.emptySet();
33+
CertStore certStore = mock(CertStore.class);
2834
AuthTokenSignatureValidator signatureValidator = mock(AuthTokenSignatureValidator.class);
29-
validator = new AuthTokenV11Validator(scvb, trustSupplier, signatureValidator);
35+
AuthTokenValidationConfiguration config = mock(AuthTokenValidationConfiguration.class);
36+
OcspClient ocspClient = mock(OcspClient.class);
37+
OcspServiceProvider ocspServiceProvider = mock(OcspServiceProvider.class);
38+
39+
validator = new AuthTokenV11Validator(
40+
scvb,
41+
trustAnchors,
42+
certStore,
43+
signatureValidator,
44+
config,
45+
ocspClient,
46+
ocspServiceProvider
47+
);
3048
}
3149

3250
@ParameterizedTest

0 commit comments

Comments
 (0)