HIGH broken authenticationhanamimutual tls

Broken Authentication in Hanami with Mutual Tls

Broken Authentication in Hanami with Mutual Tls — how this specific combination creates or exposes the vulnerability

Hanami is a Ruby web framework that encourages explicit, layered security. When mutual Transport Layer Security (mTLS) is used, both the client and the server present certificates during the TLS handshake. In theory, mTLS strengthens authentication by binding identity to cryptographic material. However, a misconfiguration or incomplete implementation can break authentication rather than improve it.

One common pattern is to terminate TLS at a load balancer or reverse proxy and forward requests to Hanami over plain HTTP internally. If the application then relies solely on the presence of a client certificate in the request headers (e.g., X-SSL-Client-Cert) without validating the certificate chain, issuer, or revocation status, an attacker can bypass authentication by omitting or spoofing that header. This is a classic broken authentication issue: the identity conferred by mTLS is not being verified by the application, so trust is placed in client-supplied data.

Additionally, Hanami applications may implement session-based authentication on top of mTLS (for example, to manage user sessions after the TLS client certificate is verified). If session tokens or cookies are not marked as Secure and HttpOnly, or if they lack proper SameSite attributes, an attacker who can intercept or steal a session identifier can impersonate a user even when mTLS is in place. This is a broken authentication weakness in how the application manages post-handshake identity.

Another scenario is weak or missing authorization checks after authentication. An attacker authenticated with a valid client certificate might be able to access endpoints or data belonging to other users (BOLA/IDOR). For example, an endpoint like GET /api/v1/users/:id that only checks that a certificate is present, but not whether the authenticated subject matches the requested user ID, exposes a broken authorization flaw enabled by mTLS context.

Finally, if Hanami uses the client certificate for authentication but does not enforce strong cipher suites or disable deprecated TLS versions (e.g., TLS 1.0 or 1.1), the security of the mTLS channel itself is weakened. This can expose authentication credentials or session material to downgrade attacks. Proper configuration of the TLS stack is essential to ensure that mTLS contributes to, rather than undermines, authentication security.

Mutual Tls-Specific Remediation in Hanami — concrete code fixes

Remediation focuses on ensuring that mTLS is correctly integrated with Hanami’s request lifecycle and that authentication decisions are based on verified certificate data, not headers alone.

First, validate the client certificate within the application or at the proxy layer and map it to a trusted identity. If using a Rack middleware approach, inspect the verified peer certificate from the connection environment. Here is an example of a Hanami-compatible Rack middleware that checks the certificate subject and issuer:

require 'openssl'

class MutualTlsAuth
  def initialize(app, cert_store_path)
    @app = app
    @cert_store = OpenSSL::X509::Store.new
    @cert_store.add_file cert_store_path
  end

  def call(env)
    client_cert = env['ssl_client_cert']
    unless client_cert
      return [401, { 'Content-Type' => 'application/json' }, [{ error: 'client certificate required' }.to_json]]
    end

    store = @cert_store
    unless store.verify(client_cert)
      return [403, { 'Content-Type' => 'application/json' }, [{ error: 'invalid certificate' }.to_json]]
    end

    # Optionally check subject or extended key usage
    subject = client_cert.subject.to_s
    unless subject.match?(/CN=([\w-]+)/)
      return [403, { 'Content-Type' => 'application/json' }, [{ error: 'certificate subject invalid' }.to_json]]
    end

    env['warden'].set_user({ subject: subject, cert_serial: client_cert.serial }, scope: :user)
    @app.call(env)
  end
end

# config/initializers/mutual_tls.rb
use MutualTlsAuth, '/path/to/ca-bundle.pem'

Second, ensure Hanami’s session cookies are hardened when mTLS is used. Even with client certificates, treat the session as a separate authentication factor and protect it:

# config/initializers/session_store.rb
Hanami.configure do
  session do
    config.store = :cookie
    config.cookie_name = '_hanami_session'
    config.secure = true
    config.http_only = true
    config.same_site = :lax
    config.expires = 30 * 24 * 60 * 60 # 30 days
  end
end

Third, enforce authorization checks that align with the authenticated identity from the certificate. For example, in a Hanami controller, resolve the user from the certificate subject and verify ownership before acting:

# app/controllers/api/users_controller.rb
class Api::UsersController < Hanami::Controller
  before_action :authenticate_by_cert

  def show
    user = UserRepository.new.find(params[:id])
    if user && user.subject == current_user.subject
      Response::Json.new(user.to_json)
    else
      Response::Json.new({ error: 'not found' }, status: 404)
    end
  end

  private

  def authenticate_by_cert
    subject = request.env['warden'].user[:subject]
    halt 401, { error: 'unauthorized' }.to_json unless subject
    @current_user = UserRepository.new.find_by_subject(subject)
    halt 403, { error: 'forbidden' }.to_json unless @current_user
  end
end

Fourth, configure your TLS termination point (proxy or load balancer) to require and verify client certificates and to forward only verified certificate details to Hanami. For example, with a proxy that supports mTLS, ensure that verify_client is enabled and that proxy_set_header does not override the verified identity with untrusted headers.

Lastly, rotate certificates and monitor revocation. Integrate certificate revocation checks (CRL or OCSP) where possible and establish a process to revoke compromised client certificates. Combined with strict session cookie policies and explicit authorization checks, this ensures that mTLS strengthens rather than weakens authentication in Hanami.

Related CWEs: authentication

CWE IDNameSeverity
CWE-287Improper Authentication CRITICAL
CWE-306Missing Authentication for Critical Function CRITICAL
CWE-307Brute Force HIGH
CWE-308Single-Factor Authentication MEDIUM
CWE-309Use of Password System for Primary Authentication MEDIUM
CWE-347Improper Verification of Cryptographic Signature HIGH
CWE-384Session Fixation HIGH
CWE-521Weak Password Requirements MEDIUM
CWE-613Insufficient Session Expiration MEDIUM
CWE-640Weak Password Recovery HIGH

Frequently Asked Questions

Can mTLS cause broken authentication if client certificates are not validated properly?
Yes. If a Hanami application trusts client certificate information from headers instead of verifying the certificate chain, issuer, and revocation status, authentication can be bypassed. Always validate the certificate cryptographically and map it to a trusted identity before establishing authentication.
What cookie settings should be used in Hanami when using mutual TLS for session management?
Set session cookies with Secure, HttpOnly, and SameSite attributes, and use an appropriate expiration. For example: secure: true, http_only: true, same_site: :lax or :strict, and a reasonable lifetime (e.g., 30 days), to reduce the risk of session hijacking even when mTLS is in place.