Configuring a Proxy for OAuth Authorization
Here is how you should configure the proxy to receive and validate requests with tokens:
frontend myapi
bind :80
bind :443 ssl crt /etc/hapee-2.4/certs/foo.com/cert.crt alpn h2
http-request redirect scheme https unless { ssl_fc }
http-request deny content-type 'text/html' string 'Missing Authorization HTTP header' unless { req.hdr(authorization) -m found }
# get header part of the JWT
http-request set-var(txn.alg) http_auth_bearer,jwt_header_query('$.alg')
# get payload part of the JWT
http-request set-var(txn.iss) http_auth_bearer,jwt_payload_query('$.iss')
http-request set-var(txn.aud) http_auth_bearer,jwt_payload_query('$.aud')
http-request set-var(txn.exp) http_auth_bearer,jwt_payload_query('$.exp','int')
http-request set-var(txn.scope) http_auth_bearer,jwt_payload_query('$.scope')
# Validate the JWT
http-request deny content-type 'text/html' string 'Unsupported JWT signing algorithm' unless { var(txn.alg) -m str RS256 }
http-request deny content-type 'text/html' string 'Invalid JWT issuer' unless { var(txn.iss) -m str https://myaccount.auth0.com/ }
http-request deny content-type 'text/html' string 'Invalid JWT audience' unless { var(txn.aud) -m str https://api.mywebsite.com }
http-request deny content-type 'text/html' string 'Invalid JWT signature' unless { http_auth_bearer,jwt_verify(txn.alg,"/etc/hapee-2.4/pubkey.pem") -m int 1 }
http-request set-var(txn.now) date()
http-request deny content-type 'text/html' string 'JWT has expired' if { var(txn.exp),sub(txn.now) -m int lt 0 }
# OPTIONAL: Deny requests that lack sufficient permissions
http-request deny if { path_beg /api/ } { method GET } ! { var(txn.scope) -m sub read }
http-request deny if { path_beg /api/ } { method DELETE POST PUT } ! { var(txn.scope) -m sub write }
default_backend servers
backend servers
balance roundrobin
server web1 192.168.56.31:3000 check maxconn 30
Here's a breakdown of the configuration:
We get the token from the Authentication HTTP header by using the
http_auth_bearer
fetch method. Thejwt_header_query
converter then extracts fields from the token's header, and thejwt_payload_query
converter extracts fields from the payload.We store the fields in variables by using the
http-request set-var
directive.We use the
http-request deny
directive to deny requests that fail validation in some way. This directive allows you to set a string parameter, which lets you return an error message to the user.We verify the token's signature using the
jwt_verify
converter.We relay valid requests to the backend named servers.
Here's how HAProxy Enterprise validates the token:
Was the token signed using an algorithm we support? In this case, yes, we allow
RS256
.Can the token's signature be verified using the Auth0 public key that we downloaded?
Is the issuer the expected value,
https://myaccount.auth0.com/
, which is our Auth0 account name?Is the audience the expected value,
https://api.mywebsite.com
, which is theIdentifier
we set for the API in Auth0?Has the token expired? HAProxy Enterprise answers this question by subtracting the current timestamp from the expiration date timestamp.
Does the token's
scopes
field contain the permissions necessary to perform the requested action? Here we consider GET requests to beread
actions and DELETE, POST, and PUT requests to bewrite
actions.
Call your service at the address where the proxy is listening. In your request, the token should be set in the Authorization
header.
$ curl --request GET \
-k \
--url https://192.168.56.20/ \
--header 'authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6Ikp...'
See also
Next up
Bot Management