on 01-Nov-2021 09:54
In my last article, Integrating NGINX Controller API Management with PingFederate to secure financial services API trans..., we have seen how to configure NGINX Controller to perform basic JWT authorization against PingFederate, configured as OIDC IdP / OAuth Autorization Server.
One weakness of the basic JWT authentication mechanism is the lack of context: anyone presenting a valid JWT will be allowed to performed the actions granted by the token, even if the sender is not the original OAuth client that was issued the token. This opens an avenue for attackers to use JWTs stollen from their rightful owners. Ideally, a mechanism of restricting the usage of the JWT to their original requestor is needed and this type of protection is specifically required for API calls presenting the highest risk, such as financial API calls.
For example, Financial-grade API (FAPI) Security Profile 1.0 - Part 2: Advanced (Read and Write API Security Profile) specifies that:
Authorization server:
Uncertainty of resource server handling of access tokens
The protected resources that conform to this document shall not accept a bearer access token. They shall only support sender-constrained access tokens via MTLS.
It is therefore useful to examine the configuration of NGINX, in its micro-gateway deployment mode, needed to perform the function of a resource server in cases requiring the Advanced FAPI security profile.
A high-level diagram of the lab environment used to demonstrate this setup is found below:
The roles performed by each network element are described below:
The workflow is very similar with the one described in my last article, with the differences highlighted here in bold:
Examining the differences between the workflows, it becomes apparent the extra actions NGINX API micro-gateway has to perform to support this advanced security use case are MTLS termination and client certificate hash verification.
The full configuration is available on DevCentral's Code Share: Configure NGINX microgateway for MTLS termination and client certificate hash verification
I will highlight below the most relevant parts of the configuration.
server { server_name api.bank.f5lab; listen 443 ssl; ssl_certificate /etc/nginx/f5lab.crt; ssl_certificate_key /etc/nginx/f5lab.key; ssl_session_cache off; ssl_prefer_server_ciphers off; ssl_client_certificate /etc/nginx/updated_ca.crt; ssl_verify_client on; ssl_verify_depth 10;
A detailed explanation of each of these commands can be found in the ngx_http_ssl_module user guide.
To compute and validate the client certificate hash, we will use an njs script (more information on njs scripting language and installation process can be found here).
The njs script used (named "x5t.js" in our case) is shown below:
function validate(r) { var clientThumbprint = require("crypto") .createHash("sha256") .update(Buffer.from(r.variables.ssl_client_raw_cert.replace(/(\n|----|-BEGIN|-END| CERTIFICATE-)/gm, ''), 'base64')) .digest("base64url"); return clientThumbprint === r.variables.jwt_cnf_fingerprint ? '1' : '0'; } export default { validate }
Importing the "x5t.js" script in the main nginx configuration is done by:
js_import /etc/nginx/x5t.js;
We are populating the value of variable $jwt_cnf_fingerprint (available to the njs script via "r.variables.jwt_cnf_fingerprint") by extracting the 'x5t#S256' value from JWT:
auth_jwt_claim_set $jwt_cnf_fingerprint 'cnf' 'x5t#S256';
The "validate" function of "x5t.js" will the compare the value of $jwt_cnf_fingerprint variable extracted from JWT with the computed SHA256 hash of the client certificate and set the validation result in the $thumbprint_match variable.
js_set $thumbprint_match x5t.validate;
Lastly, we will make a decision to accept or block client's access based on the validation result:
if ($thumbprint_match != 1) { return 403 'Access denied because client SSL certificate thumbprint does not match jwt_cnf_fingerprint'; }
Supporting MTLS termination and client certificate hash validation against sender-constrained JWTs issued by Authorization Servers such as PingFederate, enables NGINX API micro-gateway to support Open Banking's Advanced FAPI security profile.
The UDF lab environment used to build this configuration can be found here.