Skip to content

Instantly share code, notes, and snippets.

@arajkumar
Created April 4, 2023 05:07
Show Gist options
  • Save arajkumar/9ea0f94ac69ebfdd7b2e45f900220da9 to your computer and use it in GitHub Desktop.
Save arajkumar/9ea0f94ac69ebfdd7b2e45f900220da9 to your computer and use it in GitHub Desktop.
nginx config to validate client credentials
// /etc/nginx/njs/stream/auth_request.js
async function authValidate(r) {
const basicAuth = r.headersIn['Authorization'];
if (!basicAuth.toLowerCase().startsWith("basic")) {
r.error("Only BasicAuth is supported");
r.return(401);
return;
}
const basicAuthDecoded = atob(basicAuth.replace(/Basic/gi, "").trim());
const keys = basicAuthDecoded.split(":");
const query = `
query GetJWTForClientCredentials($accessKey: String!, $secretKey: String!) {
getJWTForClientCredentials (data:{
accessKey: $accessKey,
secretKey: $secretKey
})
}`;
if (keys.length < 2) {
r.error("Username or password is missing");
r.return(401);
return;
}
const authBody = {
operationName: "GetJWTForClientCredentials",
query: query,
variables: {
accessKey: keys[0],
secretKey: keys[1]
}
};
const resp = await ngx.fetch('https://console.cloud.timescale.com/api/query',
{
method: "POST",
body: JSON.stringify(authBody),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
});
if (!resp.ok) {
r.error(resp.ok + "," + resp.status);
r.return(resp.status);
return;
}
const jsonResp = await resp.json();
if (jsonResp["errors"] != null) {
r.error(JSON.stringify(jsonResp));
r.return(401);
return;
}
const claims = jwtClaim(jsonResp.data.getJWTForClientCredentials);
for (const claim in claims) {
r.headersOut["x-" + claim.toLowerCase()] = claims[claim];
}
r.error(JSON.stringify(r.headersOut));
r.return(200);
}
function jwtClaim(jwtToken) {
const segments = jwtToken.split(".");
const payload = String.bytesFrom(segments[1], 'base64');
return JSON.parse(payload)
}
export default {authValidate};
# run nginx container
docker run --rm --name nginx -v ~/Downloads/nginx.conf:/etc/nginx/nginx.conf:ro -v ~/Downloads/njs:/etc/nginx/njs -p 8080:8080 -it nginx
# invoke endpoint
curl http://username:password@localhost:8080 -v
load_module modules/ngx_http_js_module.so;
events {}
http {
js_path "/etc/nginx/njs/";
js_import main from stream/auth_request.js;
server {
resolver 8.8.8.8;
listen 8080;
server_name localhost;
location / {
auth_request /auth;
# proxy_pass https://$arg_org.$arg_bucket;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Authorization "";
proxy_set_header X-Original-URI $request_uri;
auth_request_set $project_id $sent_http_x_timescale_pat_project_id;
# proxy_pass https://google.com?q=$sub;
proxy_pass https://httpbin.org/anything?q=$project_id;
}
location = /auth {
internal;
js_content main.authValidate;
js_fetch_verify off;
}
location = /auth_verify {
internal;
proxy_pass https://console.cloud.timescale.com/api/query;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment