Auth Bypass in Chi with Openid Connect
Auth Bypass in Chi with Openid Connect — how this specific combination creates or exposes the vulnerability
Chi is a lightweight HTTP framework for the Crystal programming language. When integrating OpenID Connect (OIDC) for authentication, developers often rely on third-party middleware or libraries to handle protocol flows. If configuration or session handling is incomplete, an authentication bypass can occur. This typically happens when route-level protections assume a verified identity based solely on the presence of a session cookie, without validating the OIDC ID token on each request.
For example, an application might set a session after initial OIDC callback success but then skip token validation on subsequent endpoints. An attacker could access protected routes by using a stale or unsigned session cookie, especially if token revocation or expiry checks are not enforced. The risk is higher when the application exposes administrative or sensitive endpoints that rely only on route guards rather than verifying the current OIDC claims.
In a black-box scan, middleBrick tests unauthenticated attack surfaces and can detect scenarios where protected routes in Chi do not enforce OIDC token validation. One common misconfiguration is missing middleware on specific paths, allowing access without verifying nonce, issuer, or audience. Another is failing to validate token signature and expiration, which can lead to privilege escalation if roles or scopes are stored only client-side.
Because OIDC introduces stateful concepts (tokens, sessions, nonces) into a typically stateless HTTP flow, implementation errors are subtle. A developer might assume that enabling OIDC middleware globally ensures protection, but route-specific exclusions or inconsistent session management can create bypasses. middleBrick’s checks for Authentication and BOLA/IDOR help surface these gaps by probing endpoints without credentials and analyzing OpenAPI specs alongside runtime behavior to identify missing enforcement.
Openid Connect-Specific Remediation in Chi — concrete code fixes
Remediation centers on enforcing OIDC validation on every request to protected routes, validating tokens explicitly, and ensuring session state aligns with token metadata. Below are concrete, realistic examples using the openid-client Crystal library.
1. Configure OIDC client with required claims
require "openid/client"
oidc_client = OpenID::Client::Client.new(
issuer: "https://auth.example.com",
client_id: ENV["OIDC_CLIENT_ID"],
client_secret: ENV["OIDC_CLIENT_SECRET"],
redirect_uri: "https://app.example.com/callback",
scope: "openid profile email",
response_type: "code"
)
# Enforce issuer and audience validation
oidc_client.validate_issuer = true
oidc_client.validate_audience = true
oidc_client.expected_audience = ENV["OIDC_CLIENT_ID"]
2. Protect Chi routes with token validation
require "chi"
require "json"
app = Chi::Router.new do
# Public endpoint: no protection needed
get "/" do
{ status: "ok", message: "Public" }.to_json
end
# Protected endpoint: validate OIDC token on each request
get "/api/profile", {% if session && session["oidc_token"] && oidc_client.verify(session["oidc_token"]) %}
claims = oidc_client.decode(session["oidc_token"])
{ user: claims["sub"], email: claims["email"] }.to_json
{% else %}
response.status = 401
{ error: "unauthorized", message: "Missing or invalid OIDC token" }.to_json
{% end %}
end
3. Validate nonce and mitigate replay
# During authentication callback
nonce = session["oidc_nonce"]
begin
id_token = oidc_client.callback(request.query_params)
if id_token.nonce == nonce && id_token.verified?
session["oidc_token"] = id_token.access_token
session["oidc_id"] = id_token.id_token
else
raise "Nonce mismatch or token invalid"
end
rescue
response.status = 401
{ error: "authentication failed" }.to_json
end
4. Enforce token expiry and refresh
# Middleware to check expiry on protected routes
class TokenExpiryCheck
def initialize(app)
@app = app
end
def call(env)
req = HTTP::Request.new(env)
if req.path =~ /^\/api\// && session["oidc_exp"] && Time.utc < Time.union(session["oidc_exp"])
@app.call(env)
else
{ error: "token expired", refresh_required: true }.to_json
end
end
end
app = TokenExpiryCheck.new(app)
These patterns ensure each route explicitly verifies the OIDC token, validates claims, and checks nonce and expiry. For teams using middleBrick, the scan results under Authentication and BOLA/IDOR will highlight routes where token validation is absent. The GitHub Action can be configured to fail builds if critical endpoints lack OIDC checks, while the Web Dashboard tracks improvements over time. Remediation guidance from middleBrick maps findings to frameworks like OWASP API Top 10 and helps teams prioritize fixes.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |