Skip to content

Commit b02c9f2

Browse files
committed
[WFCORE-5691] Allow setting timeout for token introspection
1 parent 01c05bc commit b02c9f2

File tree

8 files changed

+6908
-8
lines changed

8 files changed

+6908
-8
lines changed

elytron/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@
414414
<exclude>jacc-with-providers.xml</exclude>
415415
<exclude>legacy*.xml</exclude>
416416
<exclude>elytron-subsystem-community*.xml</exclude>
417+
<exclude>elytron-subsystem-preview*.xml</exclude>
417418
</excludes>
418419
<systemId>src/main/resources/schema/wildfly-elytron_18_0.xsd</systemId>
419420
</validationSet>

elytron/src/main/java/org/wildfly/extension/elytron/ElytronSubsystemSchema.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ public enum ElytronSubsystemSchema implements PersistentSubsystemSchema<ElytronS
5454
VERSION_17_0(17),
5555
VERSION_18_0(18),
5656
VERSION_18_0_COMMUNITY(18, Stability.COMMUNITY),
57+
VERSION_19_0_PREVIEW(19, Stability.PREVIEW),
5758
;
58-
static final Map<Stability, ElytronSubsystemSchema> CURRENT = Feature.map(EnumSet.of(VERSION_18_0, VERSION_18_0_COMMUNITY));
59+
static final Map<Stability, ElytronSubsystemSchema> CURRENT = Feature.map(EnumSet.of(VERSION_18_0, VERSION_18_0_COMMUNITY, VERSION_19_0_PREVIEW));
5960

6061
private final VersionedNamespace<IntVersion, ElytronSubsystemSchema> namespace;
6162

@@ -231,7 +232,9 @@ private void addMapperParser(PersistentResourceXMLDescription.PersistentResource
231232

232233
private void addRealmParser(PersistentResourceXMLDescription.PersistentResourceXMLBuilder builder) {
233234
RealmParser realmParser = new RealmParser();
234-
if (this.since(ElytronSubsystemSchema.VERSION_18_0)) {
235+
if (this.since(ElytronSubsystemSchema.VERSION_19_0_PREVIEW)) {
236+
builder.addChild(realmParser.realmParserPreview_19_0);
237+
} else if (this.since(ElytronSubsystemSchema.VERSION_18_0)) {
235238
builder.addChild(realmParser.realmParser_18);
236239
} else if (this.since(ElytronSubsystemSchema.VERSION_16_0)) {
237240
builder.addChild(realmParser.realmParser_16);

elytron/src/main/java/org/wildfly/extension/elytron/RealmParser.java

+20
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ class RealmParser {
112112
private final PersistentResourceXMLDescription tokenRealmParser = builder(PathElement.pathElement(ElytronDescriptionConstants.TOKEN_REALM))
113113
.addAttributes(TokenRealmDefinition.ATTRIBUTES)
114114
.build();
115+
private final PersistentResourceXMLDescription tokenRealmParserPreview_19_0 = builder(PathElement.pathElement(ElytronDescriptionConstants.TOKEN_REALM))
116+
.addAttributes(TokenRealmDefinition.ATTRIBUTES)
117+
.build();
115118
private final PersistentResourceXMLDescription cachingRealmParser = builder(PathElement.pathElement(ElytronDescriptionConstants.CACHING_REALM))
116119
.addAttributes(CachingRealmDefinition.ATTRIBUTES)
117120
.build();
@@ -272,6 +275,23 @@ class RealmParser {
272275
.addChild(jaasRealmParser)
273276
.build();
274277

278+
final PersistentResourceXMLDescription realmParserPreview_19_0 = decorator(ElytronDescriptionConstants.SECURITY_REALMS)
279+
.addChild(aggregateRealmParser_8_0)
280+
.addChild(customRealmParser)
281+
.addChild(customModifiableRealmParser)
282+
.addChild(identityRealmParser)
283+
.addChild(jdbcRealmParser_14_0)
284+
.addChild(keyStoreRealmParser)
285+
.addChild(propertiesRealmParser_14_0)
286+
.addChild(ldapRealmParser)
287+
.addChild(filesystemRealmParser_16)
288+
.addChild(tokenRealmParserPreview_19_0)
289+
.addChild(cachingRealmParser)
290+
.addChild(distributedRealmParser_18)
291+
.addChild(failoverRealmParser)
292+
.addChild(jaasRealmParser)
293+
.build();
294+
275295
RealmParser() {
276296

277297
}

elytron/src/main/java/org/wildfly/extension/elytron/TokenRealmDefinition.java

+44-3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import org.jboss.as.controller.StringListAttributeDefinition;
6060
import org.jboss.as.controller.capability.RuntimeCapability;
6161
import org.jboss.as.controller.operations.validation.EnumValidator;
62+
import org.jboss.as.controller.operations.validation.IntRangeValidator;
6263
import org.jboss.as.controller.operations.validation.StringLengthValidator;
6364
import org.jboss.as.controller.parsing.ParseUtils;
6465
import org.jboss.as.controller.registry.AttributeAccess;
@@ -148,6 +149,18 @@ static class JwtValidatorAttributes {
148149
.setMinSize(1)
149150
.build();
150151

152+
static final SimpleAttributeDefinition CONNECTION_TIMEOUT = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.CONNECTION_TIMEOUT, ModelType.INT, true)
153+
.setAllowExpression(true)
154+
.setValidator(new IntRangeValidator(0))
155+
.setRestartAllServices()
156+
.build();
157+
158+
static final SimpleAttributeDefinition READ_TIMEOUT = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.READ_TIMEOUT, ModelType.INT, true)
159+
.setAllowExpression(true)
160+
.setValidator(new IntRangeValidator(0))
161+
.setRestartAllServices()
162+
.build();
163+
151164
static final PropertiesAttributeDefinition KEY_MAP = new PropertiesAttributeDefinition.Builder(ElytronDescriptionConstants.KEY_MAP, true)
152165
.setAllowExpression(true)
153166
.setMinSize(1)
@@ -171,7 +184,7 @@ public void marshallSingleElement(AttributeDefinition attribute, ModelNode prope
171184
.setRestartAllServices()
172185
.build();
173186

174-
static final ObjectTypeAttributeDefinition JWT_VALIDATOR = new ObjectTypeAttributeDefinition.Builder(JWT, ISSUER, AUDIENCE, PUBLIC_KEY, KEY_STORE, CERTIFICATE, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY, KEY_MAP)
187+
static final ObjectTypeAttributeDefinition JWT_VALIDATOR = new ObjectTypeAttributeDefinition.Builder(JWT, ISSUER, AUDIENCE, PUBLIC_KEY, KEY_STORE, CERTIFICATE, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY, KEY_MAP, CONNECTION_TIMEOUT, READ_TIMEOUT)
175188
.setRequired(false)
176189
.setRestartAllServices()
177190
.build();
@@ -198,9 +211,21 @@ static class OAuth2IntrospectionValidatorAttributes {
198211
.setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES)
199212
.build();
200213

201-
static final AttributeDefinition[] ATTRIBUTES = new AttributeDefinition[]{CLIENT_ID, CLIENT_SECRET, INTROSPECTION_URL, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY};
214+
static final SimpleAttributeDefinition CONNECTION_TIMEOUT = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.CONNECTION_TIMEOUT, ModelType.INT, true)
215+
.setAllowExpression(true)
216+
.setValidator(new IntRangeValidator(0))
217+
.setRestartAllServices()
218+
.build();
219+
220+
static final SimpleAttributeDefinition READ_TIMEOUT = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.READ_TIMEOUT, ModelType.INT, true)
221+
.setAllowExpression(true)
222+
.setValidator(new IntRangeValidator(0))
223+
.setRestartAllServices()
224+
.build();
225+
226+
static final AttributeDefinition[] ATTRIBUTES = new AttributeDefinition[]{CLIENT_ID, CLIENT_SECRET, INTROSPECTION_URL, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY, CONNECTION_TIMEOUT, READ_TIMEOUT};
202227

203-
static final ObjectTypeAttributeDefinition OAUTH2_INTROSPECTION_VALIDATOR = new ObjectTypeAttributeDefinition.Builder(OAUTH2_INTROSPECTION, CLIENT_ID, CLIENT_SECRET, INTROSPECTION_URL, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY)
228+
static final ObjectTypeAttributeDefinition OAUTH2_INTROSPECTION_VALIDATOR = new ObjectTypeAttributeDefinition.Builder(OAUTH2_INTROSPECTION, CLIENT_ID, CLIENT_SECRET, INTROSPECTION_URL, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY, CONNECTION_TIMEOUT, READ_TIMEOUT)
204229
.setRequired(false)
205230
.setRestartAllServices()
206231
.build();
@@ -271,6 +296,8 @@ protected void performRuntime(OperationContext context, ModelNode operation, Mod
271296
String sslContextRef = SSL_CONTEXT.resolveModelAttribute(context, jwtValidatorNode).asStringOrNull();
272297
String hostNameVerificationPolicy = HOSTNAME_VERIFICATION_POLICY.resolveModelAttribute(context, jwtValidatorNode).asStringOrNull();
273298
InjectedValue<SSLContext> sslContextInjector = new InjectedValue<>();
299+
Integer connectionTimeout = JwtValidatorAttributes.CONNECTION_TIMEOUT.resolveModelAttribute(context, jwtValidatorNode).asIntOrNull();
300+
Integer readTimeout = JwtValidatorAttributes.READ_TIMEOUT.resolveModelAttribute(context, jwtValidatorNode).asIntOrNull();
274301
ModelNode keyMap = KEY_MAP.resolveModelAttribute(context, jwtValidatorNode);
275302
Map<String, PublicKey> namedKeys = new LinkedHashMap<>();
276303
if (keyMap.isDefined()) {
@@ -320,6 +347,12 @@ public SecurityRealm get() throws StartException {
320347
if (namedKeys.size() > 0) {
321348
jwtValidatorBuilder.publicKeys(namedKeys);
322349
}
350+
if (connectionTimeout != null) {
351+
jwtValidatorBuilder.connectionTimeout(connectionTimeout);
352+
}
353+
if (readTimeout != null) {
354+
jwtValidatorBuilder.readTimeout(readTimeout);
355+
}
323356
KeyStore keyStore = keyStoreInjector.getOptionalValue();
324357

325358
if (keyStore != null) {
@@ -375,6 +408,8 @@ public void dispose() {
375408
String introspectionUrl = OAuth2IntrospectionValidatorAttributes.INTROSPECTION_URL.resolveModelAttribute(context, oAuth2IntrospectionNode).asString();
376409
String sslContextRef = SSL_CONTEXT.resolveModelAttribute(context, oAuth2IntrospectionNode).asStringOrNull();
377410
String hostNameVerificationPolicy = HOSTNAME_VERIFICATION_POLICY.resolveModelAttribute(context, oAuth2IntrospectionNode).asStringOrNull();
411+
Integer connectionTimeout = OAuth2IntrospectionValidatorAttributes.CONNECTION_TIMEOUT.resolveModelAttribute(context, oAuth2IntrospectionNode).asIntOrNull();
412+
Integer readTimeout = OAuth2IntrospectionValidatorAttributes.READ_TIMEOUT.resolveModelAttribute(context, oAuth2IntrospectionNode).asIntOrNull();
378413
InjectedValue<SSLContext> sslContextInjector = new InjectedValue<>();
379414

380415
service = new TrivialService<>(new TrivialService.ValueSupplier<SecurityRealm>() {
@@ -389,6 +424,12 @@ public SecurityRealm get() throws StartException {
389424
.tokenIntrospectionUrl(new URL(introspectionUrl))
390425
.useSslContext(sslContextInjector.getOptionalValue())
391426
.useSslHostnameVerifier(verifier);
427+
if (connectionTimeout != null) {
428+
builder.connectionTimeout(connectionTimeout);
429+
}
430+
if (readTimeout != null) {
431+
builder.readTimeout(readTimeout);
432+
}
392433
return TokenSecurityRealm.builder().principalClaimName(principalClaimNode.asString())
393434
.validator(builder.build())
394435
.build();

elytron/src/main/resources/org/wildfly/extension/elytron/LocalDescriptions.properties

+4
Original file line numberDiff line numberDiff line change
@@ -932,13 +932,17 @@ elytron.token-realm.jwt.key-map=A map of named public keys for token verificatio
932932
elytron.token-realm.jwt.certificate=The name of the certificate with a public key to load from the key store.
933933
elytron.token-realm.jwt.client-ssl-context=The SSL context to be used for fetching jku keys using HTTPS.
934934
elytron.token-realm.jwt.host-name-verification-policy=A policy that defines how host names should be verified when using HTTPS.
935+
elytron.token-realm.jwt.connection-timeout=The timeout for connecting in milliseconds. A non-zero value specifies the timeout when connecting to a resource. A timeout of zero is interpreted as an infinite timeout.
936+
elytron.token-realm.jwt.read-timeout=The read timeout in milliseconds. A non-zero value specifies the timeout when reading from Input stream when a connection is established to a resource. A timeout of zero is interpreted as an infinite timeout.
935937
# OAuth2 Introspection Validator Complex Attribute
936938
elytron.token-realm.oauth2-introspection=A token validator to be used in conjunction with a token-based realm that handles OAuth2 Access Tokens and validates them using an endpoint compliant with OAuth2 Token Introspection specification(RFC-7662).
937939
elytron.token-realm.oauth2-introspection.client-id=The identifier of the client on the OAuth2 Authorization Server.
938940
elytron.token-realm.oauth2-introspection.client-secret=The secret of the client.
939941
elytron.token-realm.oauth2-introspection.introspection-url=The URL of token introspection endpoint.
940942
elytron.token-realm.oauth2-introspection.client-ssl-context=The SSL context to be used if the introspection endpoint is using HTTPS.
941943
elytron.token-realm.oauth2-introspection.host-name-verification-policy=A policy that defines how host names should be verified when using HTTPS. Allowed values: 'ANY'.
944+
elytron.token-realm.oauth2-introspection.connection-timeout=The timeout for connecting in milliseconds. A non-zero value specifies the timeout when connecting to a resource. A timeout of zero is interpreted as an infinite timeout.
945+
elytron.token-realm.oauth2-introspection.read-timeout=The read timeout in milliseconds. A non-zero value specifies the timeout when reading from Input stream when a connection is established to a resource. A timeout of zero is interpreted as an infinite timeout.
942946

943947
# Identity management descriptions
944948
elytron.modifiable-security-realm.add-identity=Add an identity to a security realm.

0 commit comments

Comments
 (0)