Skip navigation
2019

For certificate-based authentication, the client presents its X.509 certificate chain to the server. The server then verifies this certificate chain using its truststore. The truststore only needs to contain certificates for root certificate authorities or intermediate certificate authorities, it doesn’t need to contain the individual client certificates. Once a server has successfully verified a client’s certificate chain, it checks if the corresponding identity is authorized to access a particular resource. This authorization check is done using a security realm that contains the roles that are associated with identities. This security realm also does not need to contain individual client certificates. Instead, it can contain principals that can be derived from a portion of the client’s certificate. As mentioned in a previous blog post, we are enhancing the way an X.509 certificate can be mapped to an underlying identity using Elytron.

 

In this blog post, we’ll take a look at how to secure a web application deployed to WildFly using the CLIENT_CERT HTTP authentication mechanism with two-way SSL and authorization. The server’s truststore will only contain an example CA certificate, it won’t contain any client certificates. Similarly, the security realm used for authorization in this example won’t contain any client certificates. It will contain principals that are derived from a portion of the CN value from the subject name from a client’s X.509 certificate.

 

 

Certificate generation

 

First, clone the elytron-examples repo locally:

 

git clone https://github.com/wildfly-security-incubator/elytron-examples
cd elytron-examples

 

Next, let's generate some client and server certificates that will be used in this example to set up two-way SSL:

 

cd dynamic-certificates
mvn clean install exec:java -Dexec.mainClass="org.wildfly.security.examples.CertificateGenerationExample" -Dexec.args="CN=Bob.Smith.123456 CN=Alice.Smith.456789"

 

Notice that the above command generates the following keystores and truststores in the dynamic-certificates/target directory:

 

client1.keystore

client2.keystore

server.keystore

server.truststore

 

  • client1.keystore contains a certificate with distinguished name: CN=Bob.Smith.123456
  • client2.keystore contains a certificate with distinguished name: CN=Alice.Smith.456789
  • Both client certificates are issued by an example certificate authority with distinguished name: CN=Elytron CA, ST=Elytron, C=UK, EMAILADDRESS=elytron@wildfly.org, O=Root Certificate Authority
  • server.truststore contains only this certificate authority's certificate

 

Next, convert the client keystores into PKCS12 format and import them into your browser so you can pick which one to present to the server later on:

 

keytool -importkeystore -srckeystore client1.keystore -srcstoretype jks -destkeystore client1.keystore.pkcs12 -deststoretype pkcs12 -srcstorepass keystorepass -deststorepass keystorepass

keytool -importkeystore -srckeystore client2.keystore -srcstoretype jks -destkeystore client2.keystore.pkcs12 -deststoretype pkcs12 -srcstorepass keystorepass -deststorepass keystorepass

 

Finally, copy the server.keystore and server.truststore files to your WildFly server instance:

 

cp /PATH/TO/ELYTRON/EXAMPLES/dynamic-certificates/target/server.* $WILDFLY_HOME/standalone/configuration

 

Server configuration

 

A WildFly CLI script that contains all of the commands that are used in this example can be found in the client-cert-with-authorization project in elytron-examples repository:

 

https://github.com/wildfly-security-incubator/elytron-examples/tree/master/client-cert-with-authorization

 

Security domain configuration

 

We’re going to configure a security domain such that only the client with ID "123456" will be able to access our secured web application.

 

First, create a principal decoder that can be used to obtain the CN value from the subject name from an X.509 client certificate:

 

/subsystem=elytron/x500-attribute-principal-decoder=cnDecoder:add(attribute-name=CN, maximum-segments=1)

 

Next, create a principal transformer that can be used to extract the ID portion from the CN value:

 

/subsystem=elytron/regex-principal-transformer=myRegexTransformer:add(pattern=".*\\.([0-9]+)",replacement="$1")

 

Now, let’s combine these two principal transformers into a chained principal transformer:

 

/subsystem=elytron/chained-principal-transformer=myChainedTransformer:add(principal-transformers=[cnDecoder, myRegexTransformer])

 

As an example, for client1’s certificate, the above chained-principal-transformer would map the subject name "CN=Bob.Smith.123456" to just the ID portion: "123456".

 

Next, create a file-system based security realm that will be used to store the client IDs and their roles:

 

/subsystem=elytron/filesystem-realm=idsRealm:add(path=ids,relative-to=jboss.server.config.dir)

 

Now, let’s add the two IDs from the client certificates to our filesystem-realm. Notice that the user with ID "123546" has “Users” role but the second user with ID "456879" does not have any roles.

 

/subsystem=elytron/filesystem-realm=idsRealm:add-identity(identity=123456)  
/subsystem=elytron/filesystem-realm=idsRealm:add-identity-attribute(identity=123456,name=Roles,value=[Users])
/subsystem=elytron/filesystem-realm=idsRealm:add-identity(identity=456789)  

 

Finally, we’ll configure a security domain that references our security realm and makes use of our chained principal transformer:

 

/subsystem=elytron/security-domain=clientCertDomain:add(realms=[{realm=idsRealm}], default-realm=idsRealm, pre-realm-principal-transformer=myChainedTransformer, permission-mapper=default-permission-mapper)

 

Two-way SSL configuration

 

We’re now going to enable two-way SSL for web applications deployed to the server.

 

First, configure a key-store using our server.truststore file. Remember this only contains the example certificate authority’s certificate, it doesn’t contain the individual client certificates:

 

/subsystem=elytron/key-store=serverTS:add(path=server.truststore,relative-to=jboss.server.config.dir,credential-reference={clear-text=truststorepass},type=JKS)

 

Next, enable two-way SSL:

 

security enable-ssl-http-server --key-store-path=server.keystore --key-store-path-relative-to=jboss.server.config.dir --key-store-password=keystorepass --trust-store-name=serverTS

 

CLIENT_CERT configuration

 

We’re now going to configure the CLIENT_CERT HTTP authentication mechanism so we can secure our web application using this mechanism.

 

The CLIENT_CERT HTTP authentication mechanism makes use of the verified X.509 client certificate chain that is established on the SSL connection. By default, this authentication mechanism will attempt to use the configured security realm to validate this certificate chain using client certificates that are stored in the configured security realm. Since our security realm does not contain client certificates and only contains role information, there won’t be a way for the realm itself to verify the client certificate. This is fine since we know the certificate chain was already verified when establishing the SSL connection so we’re going to set the org.wildfly.security.http.skip-certificate-verification property to true for the CLIENT_CERT mechanism, as shown below. Our security realm will still be used for the authorization check.

 

/subsystem=elytron/configurable-http-server-mechanism-factory=configuredCert:add(http-server-mechanism-factory=global, properties={org.wildfly.security.http.skip-certificate-verification=true})

 

Now let’s finish configuring the CLIENT_CERT mechanism:

 

/subsystem=elytron/http-authentication-factory=clientCertAuth:add(http-server-mechanism-factory=configuredCert, security-domain=clientCertDomain, mechanism-configurations=[{mechanism-name=CLIENT_CERT}])
/subsystem=undertow/application-security-domain=other:add(http-authentication-factory=clientCertAuth,override-deployment-config=true)

 

Finally, reload the server:

 

reload

 

Deploying and accessing the application

 

We’re going to make use of the simple-webapp project in the elytron-examples repository. It can be deployed using the following commands:

 

cd /PATH/TO/ELYTRON/EXAMPLES/simple-webapp
mvn clean install wildfly:deploy

 

Then try accessing the application using https://localhost:8443/simple-webapp

 

Note that since the server's certificate won't be trusted by your browser, you'll need to manually confirm that this certificate is trusted or configure your browser to trust it.

 

First, select the certificate for "Alice.Smith.456789". Then try clicking on “Access Secured Servlet”. Notice that a Forbidden message occurs. This is because accessing the secured servlet requires “Users” role but the “456789” identity that we configured has no roles.

 

Now, try accessing the application again. This time, select the certificate for "Bob.Smith.123456" and then click on “Access Secured Servlet”. This time, this succeeds since the “123456” identity that we configured has “Users” role.

 

Summary

 

This example has shown to secure a web application deployed to WildFly using the CLIENT_CERT HTTP authentication mechanism with two-way SSL with authorization. It has also demonstrated that individual client certificates do not need to be stored in either the server’s truststore or in its security realm.

Since the feature development phase for WildFly 18 has now started, we wanted to highlight the security features that we are planning to work on for this release.

 

Planned Features

 

The features in this first set are ones that were actively developed during the WildFly 17 feature development phase. Many of these are now close to being merged:

 

  • WFCORE-4362 Make the certificate authority used by a certificate-authority-account configurable

Currently, WildFly only supports integration with the Let’s Encrypt certificate authority. Once the certificate authority is configurable, it will be possible to use this integration with other certificate authorities that implement the ACME protocol.

 

  • WFCORE-4227 Add the ability for the CLI SSL security commands to be able to obtain a server certificate from Let's Encrypt

The ssl enable-ssl-management and enable-ssl-http-server already make it possible to enable one-way and two-way SSL easily. These commands will soon be able to obtain certificates from Let’s Encrypt.

 

  • WFCORE-4361 Enhanced mapping of X509Certificate to the underlying identity

Currently, the mapping of an X.509 certificate chain to an identity is done by taking the subject distinguished name from the first certificate in the X.509 certificate chain as an X.500 principal. It will soon be possible to map an X.509 certificate chain to an identity by using a subject alternative name from the first certificate in the X.509 certificate chain.

 

  • WFCORE-3947 Support SSL Certificate revocation using OCSP

 

 

  • WFCORE-4447 Ability to load the attributes of an identity from multiple sources

Elytron already provides a very flexible approach to assigning roles and permissions to an identity based on arbitrary attributes loaded by a security realm. This enhancement will add support for loading the attributes from multiple security realms and aggregating the results together.

 

This feature request looks at adding support for RFC 5424 and RFC 3164 as well as some other enhancements related to reliability vs. speed.

 

The features in this second set are new ones that we are planning to work on:

 

  • ELY-1778 Enhance Audit Logging by Feature Parity with Legacy Security Auditing

This feature request looks at adding support for additional audit events as well as support for a new @Audit annotation.

 

  • WFCORE-4360 Support encrypted expression resolution using a CredentialStore

The previous Vault implementation was basically a repository of encrypted clear text strings that could be referenced using expressions in the management model. The new CredentialStore is a repository of credentials. This feature request will look into how the CredentialStore could be used to support encrypted values within the overall model.

 

  • WFCORE-629 Enable automatic encryption of passwords stored in configuration

 

  • ELY-816 Support for masked passwords in client XML config

 

  • WFLY-11697 Web Services Integration with WildFly Elytron

The WildFly Elytron integration added a new API and configuration file to configure the client side security for outgoing calls. This feature request is to increase the integration for web services clients.

 

  • WFCORE-4483 Add support for missing MP-JWT requirements

This one will look at adding adding some remaining items needed to support the MicroProfile JWT RBAC security specification.

 

This feature request looks at allowing users to configure how much output should appear when invoking certain operations on Elytron key-stores.

 

Feedback

 

Please keep in mind that this blog post is a summary of our general plans and not a guarantee that each of these features will be merged. However, this blog post does give an indication of our team’s current priorities. If any of these features are a priority for you, please let us know. Please also let us know if there are any security features that are missing that you would like to see prioritized as we can take this kind of feedback into account for future releases.

A new security feature that we have been working on is enhancing the way an X.509 certificate chain gets mapped to an underlying identity. This feature will be included in WildFly 18. This blog post gives an overview of this new feature.

 

X.509 certificate chain evidence

 

For certificate-based authentication, the client presents its X.509 certificate chain to the server. The server then verifies this certificate chain. Elytron’s security realm APIs support using this type of X.509 certificate chain evidence to locate and load an identity. For example, after verifying a certificate chain, a server may need to check if the corresponding identity is authorized to access a particular resource. This would involve interacting with the security realm to locate and load an identity based on the X.509 certificate chain in order to determine the roles that are associated with that identity.

 

Mapping using the subject distinguished name

 

Currently, the mapping of an X.509 certificate chain to an identity is done by taking the subject distinguished name from the first certificate in the X.509 certificate chain as an X.500 principal. This principal then gets rewritten using any principal decoders or principal transformers that have been configured, as shown below:

 

 

Mapping using a subject alternative name

 

The X.509 v3 Subject Alternative Name extension provides the ability to specify one or more alternative names that can be used in addition to or instead of the subject distinguished name in an X.509 certificate. From WildFly 18, it will also be possible to map an X.509 certificate chain to an identity by using a subject alternative name from the first certificate in the X.509 certificate chain. This principal will then get rewritten using any principal decoders or principal transformers that have been configured, as shown below:

 

 

In particular, to specify that a subject alternative name from a certificate should be used as the principal associated with that certificate, it will be possible to configure an x509-subject-alt-name-evidence-decoder in the mappers configuration in the Elytron subsystem. This element will have two attributes:

 

  • alt-name-type - The subject alternative name type to decode. This required attribute must be one of the subject alternative name types that can be represented as a String:
    • rfc822Name
    • dNSName
    • uniformResourceIdentifier
    • iPAddress
    • registeredID
    • directoryName
  • segment - The 0-based occurrence of the subject alternative name to map. This attribute is optional and only used when there is more than one subject alternative name of the given alt-name-type. The default value will be 0.

 

For example, to associate the X.509 certificate in the diagram above with the principal "bob.smith@example.com", it will be possible to configure the following x509-subject-alt-name-evidence-decoder:

 

/subsystem=elytron/x509-subject-alt-name-evidence-decoder=emailDecoder:add(alt-name-type=rfc822Name)

 

This evidence decoder can then be referenced when creating an Elytron security-domain:

 

/subsystem=elytron/security-domain=exampleSD:add(...,evidence-decoder=emailDecoder)

 

Other types of evidence decoders

 

It will also be possible to configure an x500-subject-evidence-decoder that will just extract the subject from the first certificate in the certificate chain, as an X.500 principal, as shown below:

 

/subsystem=elytron/x500-subject-evidence-decoder=subjectDecoder:add()

 

Finally, it will also be possible to configure an aggregate-evidence-decoder that is made up of two or more evidence decoders, as shown in the following example:

 

/subsystem=elytron/x509-subject-alt-name-evidence-decoder=emailDecoder:add(alt-name-type=rfc822Name)
/subsystem=elytron/x509-subject-alt-name-evidence-decoder=dnsDecoder:add(alt-name-type=dNSName)
/subsystem=elytron/x500-subject-evidence-decoder=subjectDecoder:add()
/subsystem=elytron/aggregate-evidence-decoder=aggregateDecoder:add(evidence-decoders=[emailDecoder,subjectDecoder,dnsDecoder])

 

The evidence decoders that make up an aggregate-evidence-decoder will be attempted in order until one returns a non-null principal or until there are no more evidence decoders left to try.

 

Summary

 

This blog post has described how we are enhancing the mapping of an X.509 certificate to an underlying identity in WildFly 18.

One of the new security features that we have been working on is adding support for TLS 1.3 to WildFly. Although this feature didn’t make it into WildFly 17, the plan is to have it included in WildFly 18. This blog post will give a quick introduction to this feature.

 

Server Side Configuration

 

Within the Elytron subsystem in WildFly, the server-ssl-context and client-ssl-context are used to configure a server and client SSL context, respectively. Note that a client SSL context is used when a WildFly instance creates an SSL connection as a client. Both the server-ssl-context and client-ssl-context have a protocols attribute which contains a list of the protocols to be supported by WildFly. From WildFly 18, this attribute will also allow TLSv1.3 to be specified.

 

Since the TLS 1.3 specification introduced a few new cipher suites, both the server-ssl-context and client-ssl-context will also have a new cipher-suite-names attribute that will be used to specify the TLS 1.3 cipher suites to enable. The format will be a colon separated list of cipher suite names that will default to:

 

“TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256”

 

It is important to note the new TLS 1.3 cipher suites cannot be used with TLS 1.2 and below. Similarly, the old cipher suites cannot be used with TLS 1.3.

 

Client Side Configuration

 

Within the Elytron authentication client, similar changes will be made to the ssl-context. In particular, from WildFly 18, the ssl-context’s protocol element will also allow TLSv1.3 to be specified in the list of protocol names to be supported.

 

The ssl-context’s cipher-suite element will also have a new names attribute to specify the TLS 1.3 cipher suites to enable. As on the server side, this will default to:

 

“TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256”

 

Summary

 

This blog post has given a quick introduction to the upcoming support for TLS 1.3 in WildFly. Since the TLS 1.3 implementation was introduced in JDK 11, this new feature will only be available when running WildFly against JDK 11 or higher.

 

For more details on this feature and updates on the status of this feature, keep an eye on WFCORE-4172.