From 008d7a696394367af35b2af08f83faf2aca8d32a Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Thu, 27 Feb 2020 10:15:07 -0500 Subject: [PATCH 01/10] redirect to ./index.html for trailing slash requests --- authn/github.index.js | 8 +++++++- authn/openid.index.js | 9 ++++++++- authn/pkce.index.js | 9 ++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/authn/github.index.js b/authn/github.index.js index 8241cb0..bc11cd6 100644 --- a/authn/github.index.js +++ b/authn/github.index.js @@ -131,7 +131,13 @@ function mainProcess(event, context, callback) { } function redirect(request, headers, callback) { - config.AUTH_REQUEST.state = request.uri; + var requestUri = request.uri; + + if (requestUri.endsWith('/')) { + requestUri += "index.html"; + } + + config.AUTH_REQUEST.state = requestUri; // Redirect to Authorization Server var querystring = qs.stringify(config.AUTH_REQUEST); diff --git a/authn/openid.index.js b/authn/openid.index.js index 898c272..912b52c 100644 --- a/authn/openid.index.js +++ b/authn/openid.index.js @@ -242,7 +242,14 @@ function mainProcess(event, context, callback) { function redirect(request, headers, callback) { const n = nonce.getNonce(); config.AUTH_REQUEST.nonce = n[0]; - config.AUTH_REQUEST.state = request.uri; + + var requestUri = request.uri; + + if (requestUri.endsWith('/')) { + requestUri += "index.html"; + } + + config.AUTH_REQUEST.state = requestUri; // Redirect to Authorization Server var querystring = qs.stringify(config.AUTH_REQUEST); diff --git a/authn/pkce.index.js b/authn/pkce.index.js index e795bb6..a33d176 100755 --- a/authn/pkce.index.js +++ b/authn/pkce.index.js @@ -251,7 +251,14 @@ function redirect(request, headers, callback) { config.AUTH_REQUEST.code_challenge=challenge[1]; config.AUTH_REQUEST.code_challenge_method="S256" config.AUTH_REQUEST.nonce = n[0]; - config.AUTH_REQUEST.state = request.uri; + + var requestUri = request.uri; + + if (requestUri.endsWith('/')) { + requestUri += "index.html"; + } + + config.AUTH_REQUEST.state = requestUri; // Redirect to Authorization Server var querystring = qs.stringify(config.AUTH_REQUEST); From b259996ce458e93c97361c842c4a82992e431ceb Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Thu, 27 Feb 2020 11:42:02 -0500 Subject: [PATCH 02/10] intercept and rewrite default / urls before auth --- authn/github.index.js | 22 +++++++++++++++------- authn/openid.index.js | 23 +++++++++++++++-------- authn/pkce.index.js | 23 +++++++++++++++-------- 3 files changed, 45 insertions(+), 23 deletions(-) diff --git a/authn/github.index.js b/authn/github.index.js index bc11cd6..bed7106 100644 --- a/authn/github.index.js +++ b/authn/github.index.js @@ -23,6 +23,20 @@ function mainProcess(event, context, callback) { config.AUTH_REQUEST.redirect_uri = event.Records[0].cf.config.test + config.CALLBACK_PATH; config.TOKEN_REQUEST.redirect_uri = event.Records[0].cf.config.test + config.CALLBACK_PATH; } + + if (request.uri.endsWith('/')) { + var requestUrl = request.uri; + + // Match url ending with '/' and replace with /index.html + var redirectUrl = requestUrl.replace(/\/$/, '\/index.html'); + + // Replace the received URI with the URI that includes the index page + request.uri = redirectUrl; + + // Return to CloudFront + return callback(null, request); + } + if (request.uri.startsWith(config.CALLBACK_PATH)) { console.log("Callback from GitHub received"); /** Verify code is in querystring */ @@ -131,13 +145,7 @@ function mainProcess(event, context, callback) { } function redirect(request, headers, callback) { - var requestUri = request.uri; - - if (requestUri.endsWith('/')) { - requestUri += "index.html"; - } - - config.AUTH_REQUEST.state = requestUri; + config.AUTH_REQUEST.state = request.uri; // Redirect to Authorization Server var querystring = qs.stringify(config.AUTH_REQUEST); diff --git a/authn/openid.index.js b/authn/openid.index.js index 912b52c..2283c65 100644 --- a/authn/openid.index.js +++ b/authn/openid.index.js @@ -62,6 +62,20 @@ function mainProcess(event, context, callback) { config.AUTH_REQUEST.redirect_uri = event.Records[0].cf.config.test + config.CALLBACK_PATH; config.TOKEN_REQUEST.redirect_uri = event.Records[0].cf.config.test + config.CALLBACK_PATH; } + + if (request.uri.endsWith('/')) { + var requestUrl = request.uri; + + // Match url ending with '/' and replace with /index.html + var redirectUrl = requestUrl.replace(/\/$/, '\/index.html'); + + // Replace the received URI with the URI that includes the index page + request.uri = redirectUrl; + + // Return to CloudFront + return callback(null, request); + } + if (request.uri.startsWith(config.CALLBACK_PATH)) { console.log("Callback from OIDC provider received"); @@ -242,14 +256,7 @@ function mainProcess(event, context, callback) { function redirect(request, headers, callback) { const n = nonce.getNonce(); config.AUTH_REQUEST.nonce = n[0]; - - var requestUri = request.uri; - - if (requestUri.endsWith('/')) { - requestUri += "index.html"; - } - - config.AUTH_REQUEST.state = requestUri; + config.AUTH_REQUEST.state = request.uri; // Redirect to Authorization Server var querystring = qs.stringify(config.AUTH_REQUEST); diff --git a/authn/pkce.index.js b/authn/pkce.index.js index a33d176..f8b8bb4 100755 --- a/authn/pkce.index.js +++ b/authn/pkce.index.js @@ -63,6 +63,20 @@ function mainProcess(event, context, callback) { config.AUTH_REQUEST.redirect_uri = event.Records[0].cf.config.test + config.CALLBACK_PATH; config.TOKEN_REQUEST.redirect_uri = event.Records[0].cf.config.test + config.CALLBACK_PATH; } + + if (request.uri.endsWith('/')) { + var requestUrl = request.uri; + + // Match url ending with '/' and replace with /index.html + var redirectUrl = requestUrl.replace(/\/$/, '\/index.html'); + + // Replace the received URI with the URI that includes the index page + request.uri = redirectUrl; + + // Return to CloudFront + return callback(null, request); + } + if (request.uri.startsWith(config.CALLBACK_PATH)) { console.log("Callback from OIDC provider received"); @@ -251,14 +265,7 @@ function redirect(request, headers, callback) { config.AUTH_REQUEST.code_challenge=challenge[1]; config.AUTH_REQUEST.code_challenge_method="S256" config.AUTH_REQUEST.nonce = n[0]; - - var requestUri = request.uri; - - if (requestUri.endsWith('/')) { - requestUri += "index.html"; - } - - config.AUTH_REQUEST.state = requestUri; + config.AUTH_REQUEST.state = request.uri; // Redirect to Authorization Server var querystring = qs.stringify(config.AUTH_REQUEST); From 5c7ff0dae3467f0798cfd6d86d5520eeed6b1b61 Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Thu, 27 Feb 2020 12:58:21 -0500 Subject: [PATCH 03/10] only check html/png urls to avoid spamming github --- authn/github.index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/authn/github.index.js b/authn/github.index.js index bed7106..6c5652b 100644 --- a/authn/github.index.js +++ b/authn/github.index.js @@ -37,6 +37,11 @@ function mainProcess(event, context, callback) { return callback(null, request); } + // only protect html, image requests, to not spam github + if (!(request.uri.endsWith('.html') || request.uri.endsWith('.png'))) { + return callback(null, request); + } + if (request.uri.startsWith(config.CALLBACK_PATH)) { console.log("Callback from GitHub received"); /** Verify code is in querystring */ From dd33fd0c1234c3dbfa3d4f575c332f5cbcf21f86 Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Thu, 27 Feb 2020 13:28:06 -0500 Subject: [PATCH 04/10] fix order of req handling --- authn/github.index.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/authn/github.index.js b/authn/github.index.js index 6c5652b..cb57a11 100644 --- a/authn/github.index.js +++ b/authn/github.index.js @@ -37,11 +37,6 @@ function mainProcess(event, context, callback) { return callback(null, request); } - // only protect html, image requests, to not spam github - if (!(request.uri.endsWith('.html') || request.uri.endsWith('.png'))) { - return callback(null, request); - } - if (request.uri.startsWith(config.CALLBACK_PATH)) { console.log("Callback from GitHub received"); /** Verify code is in querystring */ @@ -143,6 +138,9 @@ function mainProcess(event, context, callback) { auth.isAuthorized(decoded, request, callback, unauthorized, internalServerError, config); } }); + } else if (!(request.uri.endsWith('.html') || request.uri.endsWith('.png'))) { + // only protect html, image requests, to not spam github + return callback(null, request); } else { console.log("Redirecting to GitHub."); redirect(request, headers, callback); From ecf21d47a638cafa1e938e78a90166d71caed2f5 Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Thu, 27 Feb 2020 14:20:42 -0500 Subject: [PATCH 05/10] another attempt at proper req handling order --- authn/github.index.js | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/authn/github.index.js b/authn/github.index.js index cb57a11..39c8cc2 100644 --- a/authn/github.index.js +++ b/authn/github.index.js @@ -23,20 +23,6 @@ function mainProcess(event, context, callback) { config.AUTH_REQUEST.redirect_uri = event.Records[0].cf.config.test + config.CALLBACK_PATH; config.TOKEN_REQUEST.redirect_uri = event.Records[0].cf.config.test + config.CALLBACK_PATH; } - - if (request.uri.endsWith('/')) { - var requestUrl = request.uri; - - // Match url ending with '/' and replace with /index.html - var redirectUrl = requestUrl.replace(/\/$/, '\/index.html'); - - // Replace the received URI with the URI that includes the index page - request.uri = redirectUrl; - - // Return to CloudFront - return callback(null, request); - } - if (request.uri.startsWith(config.CALLBACK_PATH)) { console.log("Callback from GitHub received"); /** Verify code is in querystring */ @@ -138,11 +124,18 @@ function mainProcess(event, context, callback) { auth.isAuthorized(decoded, request, callback, unauthorized, internalServerError, config); } }); - } else if (!(request.uri.endsWith('.html') || request.uri.endsWith('.png'))) { - // only protect html, image requests, to not spam github - return callback(null, request); } else { console.log("Redirecting to GitHub."); + + if (request.uri.endsWith('/')) { + var requestUrl = request.uri; + + // Match url ending with '/' and replace with /index.html + var redirectUrl = requestUrl.replace(/\/$/, '\/index.html'); + + // Replace the received URI with the URI that includes the index page + request.uri = redirectUrl; + } redirect(request, headers, callback); } } From 73de833117afbe0c5e09334b1272a5926aef4c6c Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Thu, 27 Feb 2020 15:14:32 -0500 Subject: [PATCH 06/10] update request.uri before any processing --- authn/github.index.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/authn/github.index.js b/authn/github.index.js index 39c8cc2..d5191e7 100644 --- a/authn/github.index.js +++ b/authn/github.index.js @@ -23,6 +23,17 @@ function mainProcess(event, context, callback) { config.AUTH_REQUEST.redirect_uri = event.Records[0].cf.config.test + config.CALLBACK_PATH; config.TOKEN_REQUEST.redirect_uri = event.Records[0].cf.config.test + config.CALLBACK_PATH; } + + if (request.uri.endsWith('/')) { + var requestUrl = request.uri; + + // Match url ending with '/' and replace with /index.html + var redirectUrl = requestUrl.replace(/\/$/, '\/index.html'); + + // Replace the received URI with the URI that includes the index page + request.uri = redirectUrl; + } + if (request.uri.startsWith(config.CALLBACK_PATH)) { console.log("Callback from GitHub received"); /** Verify code is in querystring */ @@ -126,16 +137,6 @@ function mainProcess(event, context, callback) { }); } else { console.log("Redirecting to GitHub."); - - if (request.uri.endsWith('/')) { - var requestUrl = request.uri; - - // Match url ending with '/' and replace with /index.html - var redirectUrl = requestUrl.replace(/\/$/, '\/index.html'); - - // Replace the received URI with the URI that includes the index page - request.uri = redirectUrl; - } redirect(request, headers, callback); } } From 045ebed15f9c53154c392ca1f43fbce58e22a767 Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Mon, 7 Sep 2020 11:09:12 -0400 Subject: [PATCH 07/10] allow reqs from slackbot UA for unfurling --- authn/github.index.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/authn/github.index.js b/authn/github.index.js index d5191e7..6b29375 100644 --- a/authn/github.index.js +++ b/authn/github.index.js @@ -135,6 +135,12 @@ function mainProcess(event, context, callback) { auth.isAuthorized(decoded, request, callback, unauthorized, internalServerError, config); } }); + } else if ("user-agent" in headers + && "Slackbot-LinkExpanding" in headers["user-agent"][0].value) { + // Request from slackbot for link unfurl + // TODO only serve up partial page? + console.log("Authorizing Slackbot for link unfurl."); + auth.isAuthorized(null, request, callback, unauthorized, internalServerError, config); } else { console.log("Redirecting to GitHub."); redirect(request, headers, callback); From 580835db99fd5d5dc50295a837aead99a23e62cb Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Mon, 7 Sep 2020 11:16:35 -0400 Subject: [PATCH 08/10] fix string search --- authn/github.index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/authn/github.index.js b/authn/github.index.js index 6b29375..eb9f3d3 100644 --- a/authn/github.index.js +++ b/authn/github.index.js @@ -136,7 +136,9 @@ function mainProcess(event, context, callback) { } }); } else if ("user-agent" in headers - && "Slackbot-LinkExpanding" in headers["user-agent"][0].value) { + && headers["user-agent"].length > 0 + && headers["user-agent"][0].value + && headers["user-agent"][0].value.includes("Slackbot-LinkExpanding")) { // Request from slackbot for link unfurl // TODO only serve up partial page? console.log("Authorizing Slackbot for link unfurl."); From 9db023f1bc35e45efda2d115968eb46feac98f99 Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Tue, 5 Jan 2021 23:21:46 -0500 Subject: [PATCH 09/10] slackbot unfurl for openid authn --- authn/openid.index.js | 11 ++++++++--- authn/pkce.index.js | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/authn/openid.index.js b/authn/openid.index.js index 2283c65..4b808fc 100644 --- a/authn/openid.index.js +++ b/authn/openid.index.js @@ -71,9 +71,6 @@ function mainProcess(event, context, callback) { // Replace the received URI with the URI that includes the index page request.uri = redirectUrl; - - // Return to CloudFront - return callback(null, request); } if (request.uri.startsWith(config.CALLBACK_PATH)) { @@ -247,6 +244,14 @@ function mainProcess(event, context, callback) { auth.isAuthorized(decoded, request, callback, unauthorized, internalServerError, config); } }); + } else if ("user-agent" in headers + && headers["user-agent"].length > 0 + && headers["user-agent"][0].value + && headers["user-agent"][0].value.includes("Slackbot-LinkExpanding")) { + // Request from slackbot for link unfurl + // TODO only serve up partial page? + console.log("Authorizing Slackbot for link unfurl."); + auth.isAuthorized(null, request, callback, unauthorized, internalServerError, config); } else { console.log("Redirecting to OIDC provider."); redirect(request, headers, callback); diff --git a/authn/pkce.index.js b/authn/pkce.index.js index f8b8bb4..9bb57bc 100755 --- a/authn/pkce.index.js +++ b/authn/pkce.index.js @@ -72,9 +72,6 @@ function mainProcess(event, context, callback) { // Replace the received URI with the URI that includes the index page request.uri = redirectUrl; - - // Return to CloudFront - return callback(null, request); } if (request.uri.startsWith(config.CALLBACK_PATH)) { @@ -253,6 +250,14 @@ function mainProcess(event, context, callback) { auth.isAuthorized(decoded, request, callback, unauthorized, internalServerError, config); } }); + } else if ("user-agent" in headers + && headers["user-agent"].length > 0 + && headers["user-agent"][0].value + && headers["user-agent"][0].value.includes("Slackbot-LinkExpanding")) { + // Request from slackbot for link unfurl + // TODO only serve up partial page? + console.log("Authorizing Slackbot for link unfurl."); + auth.isAuthorized(null, request, callback, unauthorized, internalServerError, config); } else { console.log("Redirecting to OIDC provider."); redirect(request, headers, callback); From 570b8843a7a6d989de9f7d3f2f22b7c2005dc3ab Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Tue, 9 Nov 2021 10:37:13 -0500 Subject: [PATCH 10/10] redirect to expected callback domain if not matching on host --- authn/openid.index.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/authn/openid.index.js b/authn/openid.index.js index 4b808fc..0b12012 100644 --- a/authn/openid.index.js +++ b/authn/openid.index.js @@ -63,6 +63,25 @@ function mainProcess(event, context, callback) { config.TOKEN_REQUEST.redirect_uri = event.Records[0].cf.config.test + config.CALLBACK_PATH; } + const actualHost = headers['host'][0].value; + const expectedHost = new URL(config.AUTH_REQUEST.redirect_uri).host; + + if (actualHost !== expectedHost) { + const response = { + "status": "308", + "statusDescription": "Found", + "body": "Redirecting to expected domain", + "headers": { + "location" : [{ + "key": "Location", + "value": 'https://' + new URL(config.AUTH_REQUEST.redirect_uri).host + request.uri + '?' + request.querystring + }] + }, + }; + callback(null, response); + return; + } + if (request.uri.endsWith('/')) { var requestUrl = request.uri;