Skip to content

Commit d07f14e

Browse files
committed
[WFCORE-5691] Allow setting timeout for token introspection
1 parent 5365664 commit d07f14e

File tree

7 files changed

+501
-4
lines changed

7 files changed

+501
-4
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

+3-1
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,9 @@ private void addMapperParser(PersistentResourceXMLDescription.PersistentResource
232232

233233
private void addRealmParser(PersistentResourceXMLDescription.PersistentResourceXMLBuilder builder) {
234234
RealmParser realmParser = new RealmParser();
235-
if (this.since(ElytronSubsystemSchema.VERSION_18_0)) {
235+
if (this.since(ElytronSubsystemSchema.VERSION_18_0_PREVIEW)) {
236+
builder.addChild(realmParser.realmParserPreview_18_0);
237+
} else if (this.since(ElytronSubsystemSchema.VERSION_18_0)) {
236238
builder.addChild(realmParser.realmParser_18);
237239
} else if (this.since(ElytronSubsystemSchema.VERSION_16_0)) {
238240
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_18_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_18_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_18_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

+49-3
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,13 @@
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;
6566
import org.jboss.as.controller.registry.ManagementResourceRegistration;
6667
import org.jboss.as.controller.registry.OperationEntry;
68+
import org.jboss.as.version.Stability;
6769
import org.jboss.dmr.ModelNode;
6870
import org.jboss.dmr.ModelType;
6971
import org.jboss.msc.service.ServiceBuilder;
@@ -148,6 +150,20 @@ static class JwtValidatorAttributes {
148150
.setMinSize(1)
149151
.build();
150152

153+
static final SimpleAttributeDefinition CONNECTION_TIMEOUT = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.CONNECTION_TIMEOUT, ModelType.INT, true)
154+
.setStability(Stability.PREVIEW)
155+
.setAllowExpression(true)
156+
.setValidator(new IntRangeValidator(0))
157+
.setRestartAllServices()
158+
.build();
159+
160+
static final SimpleAttributeDefinition READ_TIMEOUT = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.READ_TIMEOUT, ModelType.INT, true)
161+
.setStability(Stability.PREVIEW)
162+
.setAllowExpression(true)
163+
.setValidator(new IntRangeValidator(0))
164+
.setRestartAllServices()
165+
.build();
166+
151167
static final PropertiesAttributeDefinition KEY_MAP = new PropertiesAttributeDefinition.Builder(ElytronDescriptionConstants.KEY_MAP, true)
152168
.setAllowExpression(true)
153169
.setMinSize(1)
@@ -171,7 +187,7 @@ public void marshallSingleElement(AttributeDefinition attribute, ModelNode prope
171187
.setRestartAllServices()
172188
.build();
173189

174-
static final ObjectTypeAttributeDefinition JWT_VALIDATOR = new ObjectTypeAttributeDefinition.Builder(JWT, ISSUER, AUDIENCE, PUBLIC_KEY, KEY_STORE, CERTIFICATE, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY, KEY_MAP)
190+
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)
175191
.setRequired(false)
176192
.setRestartAllServices()
177193
.build();
@@ -198,9 +214,23 @@ static class OAuth2IntrospectionValidatorAttributes {
198214
.setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES)
199215
.build();
200216

201-
static final AttributeDefinition[] ATTRIBUTES = new AttributeDefinition[]{CLIENT_ID, CLIENT_SECRET, INTROSPECTION_URL, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY};
217+
static final SimpleAttributeDefinition CONNECTION_TIMEOUT = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.CONNECTION_TIMEOUT, ModelType.INT, true)
218+
.setStability(Stability.PREVIEW)
219+
.setAllowExpression(true)
220+
.setValidator(new IntRangeValidator(0))
221+
.setRestartAllServices()
222+
.build();
223+
224+
static final SimpleAttributeDefinition READ_TIMEOUT = new SimpleAttributeDefinitionBuilder(ElytronDescriptionConstants.READ_TIMEOUT, ModelType.INT, true)
225+
.setStability(Stability.PREVIEW)
226+
.setAllowExpression(true)
227+
.setValidator(new IntRangeValidator(0))
228+
.setRestartAllServices()
229+
.build();
230+
231+
static final AttributeDefinition[] ATTRIBUTES = new AttributeDefinition[]{CLIENT_ID, CLIENT_SECRET, INTROSPECTION_URL, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY, CONNECTION_TIMEOUT, READ_TIMEOUT};
202232

203-
static final ObjectTypeAttributeDefinition OAUTH2_INTROSPECTION_VALIDATOR = new ObjectTypeAttributeDefinition.Builder(OAUTH2_INTROSPECTION, CLIENT_ID, CLIENT_SECRET, INTROSPECTION_URL, SSL_CONTEXT, HOSTNAME_VERIFICATION_POLICY)
233+
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)
204234
.setRequired(false)
205235
.setRestartAllServices()
206236
.build();
@@ -271,6 +301,8 @@ protected void performRuntime(OperationContext context, ModelNode operation, Mod
271301
String sslContextRef = SSL_CONTEXT.resolveModelAttribute(context, jwtValidatorNode).asStringOrNull();
272302
String hostNameVerificationPolicy = HOSTNAME_VERIFICATION_POLICY.resolveModelAttribute(context, jwtValidatorNode).asStringOrNull();
273303
InjectedValue<SSLContext> sslContextInjector = new InjectedValue<>();
304+
Integer connectionTimeout = JwtValidatorAttributes.CONNECTION_TIMEOUT.resolveModelAttribute(context, jwtValidatorNode).asIntOrNull();
305+
Integer readTimeout = JwtValidatorAttributes.READ_TIMEOUT.resolveModelAttribute(context, jwtValidatorNode).asIntOrNull();
274306
ModelNode keyMap = KEY_MAP.resolveModelAttribute(context, jwtValidatorNode);
275307
Map<String, PublicKey> namedKeys = new LinkedHashMap<>();
276308
if (keyMap.isDefined()) {
@@ -320,6 +352,12 @@ public SecurityRealm get() throws StartException {
320352
if (namedKeys.size() > 0) {
321353
jwtValidatorBuilder.publicKeys(namedKeys);
322354
}
355+
if (connectionTimeout != null) {
356+
jwtValidatorBuilder.connectionTimeout(connectionTimeout);
357+
}
358+
if (readTimeout != null) {
359+
jwtValidatorBuilder.readTimeout(readTimeout);
360+
}
323361
KeyStore keyStore = keyStoreInjector.getOptionalValue();
324362

325363
if (keyStore != null) {
@@ -375,6 +413,8 @@ public void dispose() {
375413
String introspectionUrl = OAuth2IntrospectionValidatorAttributes.INTROSPECTION_URL.resolveModelAttribute(context, oAuth2IntrospectionNode).asString();
376414
String sslContextRef = SSL_CONTEXT.resolveModelAttribute(context, oAuth2IntrospectionNode).asStringOrNull();
377415
String hostNameVerificationPolicy = HOSTNAME_VERIFICATION_POLICY.resolveModelAttribute(context, oAuth2IntrospectionNode).asStringOrNull();
416+
Integer connectionTimeout = OAuth2IntrospectionValidatorAttributes.CONNECTION_TIMEOUT.resolveModelAttribute(context, oAuth2IntrospectionNode).asIntOrNull();
417+
Integer readTimeout = OAuth2IntrospectionValidatorAttributes.READ_TIMEOUT.resolveModelAttribute(context, oAuth2IntrospectionNode).asIntOrNull();
378418
InjectedValue<SSLContext> sslContextInjector = new InjectedValue<>();
379419

380420
service = new TrivialService<>(new TrivialService.ValueSupplier<SecurityRealm>() {
@@ -389,6 +429,12 @@ public SecurityRealm get() throws StartException {
389429
.tokenIntrospectionUrl(new URL(introspectionUrl))
390430
.useSslContext(sslContextInjector.getOptionalValue())
391431
.useSslHostnameVerifier(verifier);
432+
if (connectionTimeout != null) {
433+
builder.connectionTimeout(connectionTimeout);
434+
}
435+
if (readTimeout != null) {
436+
builder.readTimeout(readTimeout);
437+
}
392438
return TokenSecurityRealm.builder().principalClaimName(principalClaimNode.asString())
393439
.validator(builder.build())
394440
.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.

elytron/src/main/resources/schema/wildfly-elytron_preview_18_0.xsd

+28
Original file line numberDiff line numberDiff line change
@@ -2042,6 +2042,20 @@
20422042
</xs:documentation>
20432043
</xs:annotation>
20442044
</xs:attribute>
2045+
<xs:attribute name="connection-timeout" type="xs:integer" use="optional">
2046+
<xs:annotation>
2047+
<xs:documentation>
2048+
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.
2049+
</xs:documentation>
2050+
</xs:annotation>
2051+
</xs:attribute>
2052+
<xs:attribute name="read-timeout" type="xs:integer" use="optional">
2053+
<xs:annotation>
2054+
<xs:documentation>
2055+
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.
2056+
</xs:documentation>
2057+
</xs:annotation>
2058+
</xs:attribute>
20452059
</xs:complexType>
20462060

20472061
<xs:complexType name="oauth2IntrospectionTokenRealmValidatorType">
@@ -2085,6 +2099,20 @@
20852099
</xs:documentation>
20862100
</xs:annotation>
20872101
</xs:attribute>
2102+
<xs:attribute name="connection-timeout" type="xs:integer" use="optional">
2103+
<xs:annotation>
2104+
<xs:documentation>
2105+
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.
2106+
</xs:documentation>
2107+
</xs:annotation>
2108+
</xs:attribute>
2109+
<xs:attribute name="read-timeout" type="xs:integer" use="optional">
2110+
<xs:annotation>
2111+
<xs:documentation>
2112+
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.
2113+
</xs:documentation>
2114+
</xs:annotation>
2115+
</xs:attribute>
20882116
</xs:complexType>
20892117

20902118
<xs:complexType name="dirContextsType">

0 commit comments

Comments
 (0)