Class RefreshTokenCipher

java.lang.Object
com.kingsrook.qqq.backend.core.modules.authentication.implementations.RefreshTokenCipher

public class RefreshTokenCipher extends Object
Authenticated encryption (AES-256-GCM) of OAuth2 refresh tokens at rest (#1048), so a copy of the refresh-token table (a backup, a replica, an over-broad DB role) does not hand out live credentials. Stored values look like: v1::invalid input: '<'base64(nonce | ciphertext | tag)> with a random 96-bit nonce per value. The associated data binds each value to its session (uuid + userId), so a ciphertext copied to another row will not decrypt. The keyId names the key that encrypted the value, so keys can be rotated: values under a previous key still decrypt, and are re-encrypted under the current key the next time they are written. Keys come from configuration (OAuth2AuthenticationMetaData), never from the database; they may be given as ${env.X} / ${prop.X} references. Messages from this class never include key or token material.
  • Field Details

  • Method Details

    • fromMetaData

      public static RefreshTokenCipher fromMetaData(OAuth2AuthenticationMetaData metaData) throws QException
      Build a cipher from the OAuth2 meta-data's key settings. Returns null if no current key is configured (refreshTokenEncryptionKey is unset). Throws if any configured key or key id is invalid (the message names the setting, never the key).
      Throws:
      QException
    • buildAssociatedData

      public static String buildAssociatedData(String sessionUuid, String userId)
      Build the associated data that binds a stored value to its session.
    • encrypt

      public String encrypt(String plaintext, String associatedData) throws QException
      Encrypt a refresh token under the current key.
      Throws:
      QException
    • decrypt

      public String decrypt(String storedValue, String associatedData) throws QException
      Decrypt a stored value. Throws (with a short, token-free reason as the message) if the value is malformed, names an unknown key, or fails authentication (wrong key, tampered, or bound to a different session).
      Throws:
      QException
    • needsReEncryption

      public boolean needsReEncryption(String storedValue)
      Whether a stored value should be re-written under the current key (i.e., it was not encrypted with the current key id).
    • getCurrentKeyId

      public String getCurrentKeyId()
      Getter for currentKeyId