Chapter 6. Changes in Eclipse Vert.x authentication and authorization

The following sections describe the changes in Eclipse Vert.x authentication and authorization.

The Eclipse Vert.x authentication module has major updates in Eclipse Vert.x 4. The io.vertx.ext.auth.AuthProvider interface has been split into two new interfaces:

  • io.vertx.ext.auth.authentication.AuthenticationProvider

    Important

    Authentication feature is provided as Technology Preview only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend to use them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

    See Technology Preview Features Support Scope on the Red Hat Customer Portal for information about the support scope for Technology Preview features.

  • io.vertx.ext.auth.authorization.AuthorizationProvider

This update enables any provider to independently perform either authentication and authorization.

6.1. Migrating the authentication applications

The authentication mechanism has changed at the result level. In earlier releases, the result was a User object, which was provider specific. In Eclipse Vert.x 4, the result is a common implementation of io.vertx.ext.auth.User.

The following example shows how a user was authenticated in Eclipse Vert.x 3.x releases.

JsonObject authInfo = new JsonObject()
  .put("username", "john")
  .put("password", "super$ecret");

// omitting the error handling for brevity
provider.authenticate(authInfo, res -> {
   if (res.succeeded()) {
     // may require type casting for example on Oauth2
     User user = res.result();
   }
});

The following example shows how to authenticate a user in Eclipse Vert.x 4.

JsonObject authInfo = new JsonObject()
  .put("username", "john")
  .put("password", "super$ecret");

// omitting the error handling for brevity
provider.authenticate(authInfo, res -> {
   if (res.succeeded()) {
     // Never needs type casting
     User user = res.result();
   }
});

6.2. Migrating the authorization applications

Authorization is a new feature in Eclipse Vert.x 4. In earlier releases, you could only check if a user was authorized to perform the tasks on the User object. This meant that the provider was responsible for both authentication and authorization of the user.

In Eclipse Vert.x 4, the User object instances are not associated with a particular authentication provider. So you can authenticate and authorize a user using different providers. For example, you can authenticate a user using OAuth2 and perform authorization checks against MongoDB or SQL database.

The following example shows how an application checks if a user can use Printer #1234 in Eclipse Vert.x 3.x releases.

// omitting the error handling for brevity
user.isAuthorized("printers:printer1234", res -> {
  if (res.succeeded()) {
    boolean hasAuthority = res.result();
    if (hasAuthority) {
      System.out.println("User can use the printer");
    } else {
      System.out.println("User cannot use the printer");
    }
  }
});

This authorization worked for JDBC and MongoDB. However it did not work for providers such as OAuth2, because the provider did not perform authorization checks. From Eclipse Vert.x 4, it is possible to perform such authorization checks by using different providers.

// omitting the error handling for brevity
provider.getAuthorizations(user, res -> {
  if (res.succeeded()) {
    if (PermissionBasedAuthorization.create("printer1234").match(user)) {
      System.out.println("User can use the printer");
    } else {
      System.out.println("User cannot use the printer");
    }
  }
});

You can check authorizations on roles, permissions, logic operations, wildcards and any other implementation you add.

6.3. Changes in key management

In Eclipse Vert.x 4, there are major updates in handling keys. The most important change is that when a key loads, there is no distinction between public buffer and private buffer.

The following classes have been updated:

  • io.vertx.ext.auth.KeyStoreOptions used to work with jce keystores
  • io.vertx.ext.auth.SecretOptions used to handle symmetric secrets
  • io.vertx.ext.auth.PubSecKeyOptions used to handle public secret keys

The following section describes the changes in key management.

6.3.1. Secret options class is no longer available

The SecretOptions class is no longer available. Use the new PubSecKeyOptions class instead to work with a cryptographic key.

The following example shows how methods of SecretOptions class were used in Eclipse Vert.x 3.x releases.

new SecretOptions()
    .setType("HS256")
    .setSecret("password")

The following example shows how methods of PubSecKeyOptions class should be used in Eclipse Vert.x 4.

new PubSecKeyOptions()
    .setAlgorithm("HS256")
    .setSecretKey("password")

6.3.2. Updates in public secret keys management

In Eclipse Vert.x 3.x, the configuration object in public secret key management assumed that:

  • Keys are configured as key-pairs.
  • Key data is a PKCS8 encoded string without standard delimiters.

The following example shows how to configure key pair in Eclipse Vert.x 3.x.

new PubSecKeyOptions()
  .setPublicKey(
    // remove the PEM boundaries
    pubPemString
      .replaceAll("-----BEGIN PUBLIC KEY----")
      .replaceAll("-----END PUBLIC KEY----"))
  .setSecretKey(
    // remove the PEM boundaries
    secPemString
      .replaceAll("-----BEGIN PUBLIC KEY----")
      .replaceAll("-----END PUBLIC KEY----"));

In Eclipse Vert.x 4, you must specify both the public and private key.

The following example shows how to configure key pair in Eclipse Vert.x 4.

PubSecKeyOptions pubKey =
  new PubSecKeyOptions()
    // the buffer is the exact contents of the PEM file and had boundaries included in it
    .setBuffer(pubPemString);

PubSecKeyOptions secKey =
  new PubSecKeyOptions()
    // the buffer is the exact contents of the PEM file and had boundaries included in it
    .setBuffer(secPemString);

You can now handle X509 certificates using PubSecKeyOptions.

PubSecKeyOptions x509Certificate =
  new PubSecKeyOptions()
    // the buffer is the exact contents of the PEM file and had boundaries included in it
    .setBuffer(x509PemString);

6.3.3. Changes in keystore management

In Eclipse Vert.x 3.x, KeyStoreOptions assumes that the keystore format is jceks, and the stored password is the same as the password of the key. As jceks is a proprietary format, it is recommended to use a standard format, such as JDK, instead.

When you use KeyStoreOptions in Eclipse Vert.x 4, you can specify a store type. For example, store types such as PKCS11, PKCS12, and so on can be set. The default store type is jceks.

In Eclipse Vert.x 3.x, all keystore entries would share the same password, that is, the keystore password. In Eclipse Vert.x 4, each keystore entry can have a dedicated password. If you do not want to set password for each keystore entry, you can configure the keystore password as the default password for all entries.

The following example shows how to load a jceks keystore in Eclipse Vert.x 3.x.

new KeyStoreOptions()
  .setPath("path/to/keystore.jks")
  .setPassword("keystore-password");

In Eclipse Vert.x 4, the default format is assumed to be the default format configured by JDK. The format is PKCS12 in Java 9 and above.

The following example shows how to load a jceks keystore in Eclipse Vert.x 4.

new KeyStoreOptions()
  .setPath("path/to/keystore.jks")
  // Modern JDKs use `jceks` keystore. But this type is not the default
  // If the type is not set to `jceks` then probably `pkcs12` will be used
  .setType("jceks")
  .setPassword("keystore-password")
  // optionally if your keys have different passwords
  // and if a key specific id is not provided it defaults to
  // the keystore password
  .putPasswordProtection("key-id", "key-specific-password");

6.4. Deprecated and removed authentication and authorization methods

The following sections list methods deprecated and removed for authentication and authorization.

6.4.1. List of removed authentication and authorization methods

The following methods have been removed:

Removed methodsReplacing methods

OAuth2Auth.createKeycloak()

KeycloakAuth.create(vertx, JsonObject) ()

OAuth2Auth.create(Vertx, OAuth2FlowType, OAuth2ClientOptions)()

OAuth2Auth.create(vertx, new OAuth2ClientOptions().setFlow(YOUR_DESIRED_FLOW))

OAuth2Auth.create(Vertx, OAuth2FlowType)

OAuth2Auth.create(vertx, new OAuth2ClientOptions().setFlow(YOUR_DESIRED_FLOW))

User.isAuthorised()

User.isAuthorized()

User.setAuthProvider()

No replacing method

AccessToken.refreshToken()

AccessToken.opaqueRefreshToken()

io.vertx.ext.auth.jwt.JWTOptions data object

io.vertx.ext.jwt.JWTOptions data object

Oauth2ClientOptions.isUseAuthorizationHeader()

No replacing method

Oauth2ClientOptions.scopeSeparator()

No replacing method

6.4.2. List of deprecated authentication and authorization methods

The following methods have been deprecated:

Deprecated methodsReplacing methods

OAuth2Auth.decodeToken()

AuthProvider.authenticate()

OAuth2Auth.introspectToken()

AuthProvider.authenticate()

OAuth2Auth.getFlowType()

No replacing method

OAuth2Auth.loadJWK()

OAuth2Auth.jwkSet()

Oauth2ClientOptions.isUseAuthorizationHeader()

No replacing method

6.4.3. List of deprecated authentication and authorization classes

The following classes have been deprecated:

Deprecated classReplacing class

AbstractUser

Create user objects using the ` User.create(JsonObject)` method.

AuthOptions

No replacing class

JDBCAuthOptions

JDBCAuthenticationOptions for authentication and JDBCAuthorizationOptions for authorization

JDBCHashStrategy

No replacing class

OAuth2RBAC

AuthorizationProvider

Oauth2Response

Recommended to use WebClient class

KeycloakHelper

No replacing class