An extension for Wildfly that provides container-managed JWT-based authentication for a Java web application.
This extension provides container-managed support for JWT, such that web
applications can use the Java EE standard security mechanisms; for example,
declarative roles and constraints in web.xml
and the @RolesAllowed
bean
annotation.
The main component is a standard JAAS LoginModule
that participates in
Wildfly's security subsystem. The login module validates a JWT bearer token
delegate and makes the claims specified in it available as roles in Wildfly's
built in security stack. Additionally, it makes the claims from the JWT payload
available to a deployed Java web application via a custom subtype of the
javax.security.Principal
interface.
Using the module, a Java web application can utilize almost any combination
of container-managed authorization (through the standard mechanisms of
Java EE) as well as application-specific authorization by examining the
claims made available via the custom Principal
that is available via
the HttpServletRequest
object.
The module and its dependencies must be installed in the modules
directory
of your Wildfly server. Thanks to Wildfly's modular design, the installed
modules remain isolated in your server's configuration, and will never be seen
by applications that do not require JWT support. Moreover, the library
components needed by this extension will not appear on your
application's class loader, avoiding any potential for conflict.
Clone this repository and then run Maven at the top level of the source tree. This will create a version of the extension that is compatible with Wildfly 11 and up.
mvn clean install
tar -C ${WILDFLY_HOME} -zxpvf target/wildfly-jwt-${VERSION}-modules.tar.gz
TODO
RS256
algorihm, a 2048-bit key RSA key pair is recommendedRS384
algorihm, a 3072-bit key RSA key pair is recommendedRS512
algorihm, a 4096-bit key RSA key pair is recommendedThe commands below produce a 2048-bit RSA key pair for RSA256
.
openssl genrsa -out rsa-private.pem 2048
openssl rsa -in rsa-private.pem -pubout -out rsa-public.pem
openssl pkcs8 -topk8 -nocrypt -in rsa-private.pem -out rsa-private-pk8.pem
The EC curve specified by the -name
parameter of the OpenSSL ecparam
command must be supported by the platform.
On Alpine, note that only the
secp256r1
,secp384r1
, andsecp521r1
curves are supported.
openssl ecparam -name secp256r1 -genkey -noout -out ec-private.pem
openssl ec -in ec-private.pem -pubout -out ec-public.pem
openssl pkcs8 -topk8 -nocrypt -in ec-private.pem -out ec-private-pk8.pem
Alpine note on supported EC curves: secp256r1, secp384r1, secp521r1 see https://github.com/docker-library/openjdk/issues/115
/extension=org.soulwing.jwt:add(module=org.soulwing.jwt)
/subsystem=jwt:add
reload
/subsystem=security/security-domain=jwt:add
/subsystem=security/security-domain=jwt/authentication=classic:add
/subsystem=security/security-domain=jwt/authentication=classic/login-module=JwtClaim:add(module=org.soulwing.jwt, code=org.soulwing.jwt.extension.jaas.JwtLoginModule, flag=required, module-options={ role-claims="grp, afl" })
/subsystem=security/security-domain=jwt/authentication=classic/login-module=RoleMapping:add(code=RoleMapping, flag=optional, module-options={ rolesProperties="file:/run/wildfly/configuration/role-mapping.properties" })
reload
/subsystem=jwt/secret=trust-store-password:add(provider=FILE, properties={path="/run/secrets/trust-store-password"})
/subsystem=jwt/trust-store=default-jks:add(path="jwt-truststore.jks", relative-to="jboss.server.config.dir", provider="JCA", password-secret=trust-store-password, properties={type=JKS})
/subsystem=jwt/secret-key=shared-key-1:add(id=1, type=AES, length=128, provider=FILE, properties={path="/run/secrets/encryption-password"})
/subsystem=jwt/transformer=DistinguishedToSimpleName:add(properties={name-component=uugid})
/subsystem=jwt/transformer=FlattenCase:add
/subsystem=jwt/claim-transform=grp:add(transformers=[DistinguishedToSimpleName,FlattenCase])
/subsystem=jwt/signature=public-key:add(algorithm=RS256, trust-store=default-jks)
/subsystem=jwt/encryption=shared-key:add(key-management-algorithm=A128KW, content-encryption-algorithm=A128CBC-HS256, compression-algorithm=DEF, secret-keys=[shared-key-1])
/subsystem=jwt/validator=default:add(issuer="token-issuer", issuer-url="https://token-issuer.localhost.vt.edu", expiration-tolerance=90, audience="test-service", signature=public-key, encryption=shared-key, transforms=[grp])