Certificate
Client-certificate authentication (mTLS) sidesteps the classic CSRF model because the browser presents a TLS certificate that an attacker site cannot replay from a cross-origin request. It is the right fit for admin tools, machine-to-machine APIs, and internal dashboards. This snippet shows the nginx side and the app-side identity check.
Require a client cert for the admin area
EXAMPLE
# nginx: terminate TLS and require a client certificate on /admin
server {
listen 443 ssl;
server_name admin.example.test;
ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key;
# Trust only this internal CA for client certs
ssl_client_certificate /etc/ssl/internal-ca.crt;
# Optional everywhere, required under /admin
ssl_verify_client optional;
location /admin/ {
if ($ssl_client_verify != SUCCESS) {
return 403;
}
# Pass verified subject DN to the upstream app
proxy_set_header X-Client-DN $ssl_client_s_dn;
proxy_set_header X-Client-Verify $ssl_client_verify;
proxy_pass http://127.0.0.1:8080;
}
}
# --- App side (Laravel middleware) ---
# Trust the header only because nginx is the sole entrypoint AND
# strips any client-supplied X-Client-* header before proxying.
<?php
public function handle($request, Closure $next) {
if ($request->header('X-Client-Verify') !== 'SUCCESS') abort(403);
$dn = $request->header('X-Client-DN');
$user = User::where('client_dn', $dn)->firstOrFail();
auth()->setUser($user);
return $next($request);
}
Why it matters
mTLS removes the CSRF threat for the gated routes but introduces a new failure mode: cert rotation. Build the renewal pipeline before you turn this on, or you will lock yourself out of the admin panel on expiry day.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Discussion
Loading…