diff --git a/README.md b/README.md index 170f312..f047766 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[Google Apps (G Suite)](https://developers.google.com/identity/protocols/OpenIDConnect), [Microsoft Azure AD](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code), [GitHub](https://developer.github.com/apps/building-oauth-apps/authorization-options-for-oauth-apps/), and [OKTA](https://www.okta.com/) authentication for [CloudFront](https://aws.amazon.com/cloudfront/) using [Lambda@Edge](http://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html). The primary use case for `cloudfront-auth` is to serve private S3 content over HTTPS without running a proxy server to authenticate requests. +[Google Apps (G Suite)](https://developers.google.com/identity/protocols/OpenIDConnect), [Microsoft Azure AD](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code), [GitHub](https://developer.github.com/apps/building-oauth-apps/authorization-options-for-oauth-apps/), [OKTA](https://www.okta.com/) and [Auth0](https://auth0.com/) authentication for [CloudFront](https://aws.amazon.com/cloudfront/) using [Lambda@Edge](http://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html). The primary use case for `cloudfront-auth` is to serve private S3 content over HTTPS without running a proxy server to authenticate requests. ## Description Upon successful authentication, a cookie (named `TOKEN`) with the value of a signed JWT is set and the user redirected back to the originally requested path. Upon each request, Lambda@Edge checks the JWT for validity (signature, expiration date, audience and matching hosted domain) and will redirect the user to configured provider's login when their session has timed out. @@ -66,6 +66,18 @@ Session duration is defined as the number of hours that the JWT is valid for. Af 1. Choose `OKTA` as the authorization method and enter the values for Base URL, Client ID, Client Secret, Redirect URI, and Session Duration 1. Upload the resulting `zip` file found in your distribution folder using the AWS Lambda console and jump to the [configuration step](#configure-lambda-and-cloudfront) +#### Login using Auth0 + +1. Clone or download this repo +1. Go to the **Dashboard** of your Auth0 admin page + 1. Click **New Application** + 1. Select **Regular Web App** and click **Create**. + 1. Now select an application type and follow the steps for 'Quick Start' or use your own app. + 1. Go to application **Settings** and enter required details. In **Allowed Callback URLs** enter your Cloudfront hostname with your preferred path value for the authorization callback. Example: `https://my-cloudfront-site.example.com/_callback` +1. Execute `./build.sh` in the downloaded directory. NPM will run to download dependencies and a RSA key will be generated. +1. Choose `AUTH0` as the authorization method and enter the values for Base URL, Client ID, Client Secret, Redirect URI, and Session Duration +1. Upload the resulting `zip` file found in your distribution folder using the AWS Lambda console and jump to the [configuration step](#configure-lambda-and-cloudfront) + ### Configure Lambda and CloudFront 1. Upload **cloudfront-auth.zip** to Lambda using the [AWS Console](https://console.aws.amazon.com/lambda/home): diff --git a/authz/auth0.js b/authz/auth0.js new file mode 100644 index 0000000..5015fbe --- /dev/null +++ b/authz/auth0.js @@ -0,0 +1,10 @@ +function isAuthorized(decoded, request, callback, unauthorized, internalServerError, config) { + callback(null, request); +} + +function getSubject(decoded) { + return decoded.payload.email; +} + +exports.isAuthorized = isAuthorized; +exports.getSubject = getSubject; diff --git a/build/build.js b/build/build.js index d756258..0125a44 100644 --- a/build/build.js +++ b/build/build.js @@ -18,7 +18,7 @@ prompt.get({ required: true }, method: { - description: colors.red("Authentication methods:\n (1) Google\n (2) Microsoft\n (3) GitHub\n (4) OKTA\n\n Select an authentication method") + description: colors.red("Authentication methods:\n (1) Google\n (2) Microsoft\n (3) GitHub\n (4) OKTA\n (5) Auth0\n\n Select an authentication method") } } }, function (err, result) { @@ -60,6 +60,13 @@ prompt.get({ config.AUTHN = "OKTA"; oktaConfiguration(); break; + case '5': + if (R.pathOr('', ['AUTHN'], oldConfig) != "AUTH0") { + oldConfig = undefined; + } + config.AUTHN = "AUTH0"; + auth0Configuration(); + break; default: console.log("Method not recognized. Stopping build..."); process.exit(1); @@ -415,6 +422,72 @@ function githubConfiguration() { }); } +// Auth0 configuration +function auth0Configuration() { + prompt.message = colors.blue(">>"); + prompt.start(); + prompt.get({ + properties: { + BASE_URL: { + message: colors.red("Base URL"), + required: true, + default: R.pathOr('', ['BASE_URL'], oldConfig) + }, + CLIENT_ID: { + message: colors.red("Client ID"), + required: true, + default: R.pathOr('', ['AUTH_REQUEST', 'client_id'], oldConfig) + }, + CLIENT_SECRET: { + message: colors.red("Client Secret"), + required: true, + default: R.pathOr('', ['TOKEN_REQUEST', 'client_secret'], oldConfig) + }, + REDIRECT_URI: { + message: colors.red("Redirect URI"), + required: true, + default: R.pathOr('', ['AUTH_REQUEST', 'redirect_uri'], oldConfig) + }, + SESSION_DURATION: { + pattern: /^[0-9]*$/, + description: colors.red("Session Duration (hours)"), + message: colors.green("Entry must only contain numbers"), + required: true, + default: R.pathOr('', ['SESSION_DURATION'], oldConfig)/60/60 + } + } + }, function(err, result) { + config.PRIVATE_KEY = fs.readFileSync('distributions/' + config.DISTRIBUTION + '/id_rsa', 'utf8'); + config.PUBLIC_KEY = fs.readFileSync('distributions/' + config.DISTRIBUTION + '/id_rsa.pub', 'utf8'); + config.DISCOVERY_DOCUMENT = result.BASE_URL + '/.well-known/openid-configuration'; + config.SESSION_DURATION = parseInt(result.SESSION_DURATION, 10) * 60 * 60; + + config.BASE_URL = result.BASE_URL; + config.CALLBACK_PATH = url.parse(result.REDIRECT_URI).pathname; + + config.AUTH_REQUEST.client_id = result.CLIENT_ID; + config.AUTH_REQUEST.response_type = 'code'; + config.AUTH_REQUEST.scope = 'openid email'; + config.AUTH_REQUEST.redirect_uri = result.REDIRECT_URI; + + config.TOKEN_REQUEST.client_id = result.CLIENT_ID; + config.TOKEN_REQUEST.client_secret = result.CLIENT_SECRET; + config.TOKEN_REQUEST.redirect_uri = result.REDIRECT_URI; + config.TOKEN_REQUEST.grant_type = 'authorization_code'; + + config.AUTHZ = "AUTH0"; + + shell.cp('./authn/openid.index.js', './distributions/' + config.DISTRIBUTION + '/index.js'); + + fs.writeFileSync('distributions/' + config.DISTRIBUTION + '/config.json', JSON.stringify(result, null, 4)); + + shell.cp('./authz/auth0.js', './distributions/' + config.DISTRIBUTION + '/auth.js'); + writeConfig(config, zip, ['config.json', 'index.js', 'auth.js']); + }); +} + + + function zip(files) { var filesString = ''; for (var i = 0; i < files.length; i++) { diff --git a/package.json b/package.json index b124aff..e4730e8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "cloudfront-auth", "version": "1.0.0", - "description": "An AWS Cloudfront Lambda@Edge function to authenticate requests using Google Apps, Microsoft, and GitHub login", + "description": "An AWS Cloudfront Lambda@Edge function to authenticate requests using Google Apps, Microsoft, GitHub login, OKTA & Auth0", "main": "index.js", "scripts": { "test": "cd tests && npm install && cd .. && node tests/tests.js",