├── .circleci └── config.yml ├── .github └── stale.yml ├── .gitignore ├── 01-Login ├── .dockerignore ├── .gitignore ├── Dockerfile ├── README.md ├── app.js ├── assets │ └── loading.svg ├── auth0-variables.js.example ├── exec.ps1 ├── exec.sh ├── index.html ├── package.json └── style.css ├── 02-User-Profile ├── .dockerignore ├── .gitignore ├── Dockerfile ├── README.md ├── app.js ├── assets │ └── loading.svg ├── auth0-variables.js.example ├── exec.ps1 ├── exec.sh ├── index.html ├── package.json └── style.css ├── 03-Calling-an-API ├── .dockerignore ├── .env.example ├── .gitignore ├── Dockerfile ├── README.md ├── app.js ├── assets │ └── loading.svg ├── auth0-variables.js.example ├── exec.ps1 ├── exec.sh ├── index.html ├── package.json ├── server.js └── style.css ├── 04-Authorization ├── .dockerignore ├── .env.example ├── .gitignore ├── Dockerfile ├── README.md ├── app.js ├── assets │ └── loading.svg ├── auth0-variables.js.example ├── exec.ps1 ├── exec.sh ├── index.html ├── package.json ├── server.js └── style.css ├── 05-Token-Renewal ├── .dockerignore ├── .gitignore ├── Dockerfile ├── README.md ├── app.js ├── assets │ └── loading.svg ├── auth0-variables.js.example ├── exec.ps1 ├── exec.sh ├── index.html ├── package.json └── style.css ├── LICENSE └── README.md /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Environment variables to be defined in the build configuration: 2 | # AUTH0_TEST_CLIENT_ID = Client id to use in test 3 | # AUTH0_TEST_DOMAIN = Domain to use in test 4 | # AUTH0_TEST_API_IDENTIFIER = API Audience to use in test 5 | 6 | # Common logic 7 | defaults: &defaults 8 | steps: 9 | - attach_workspace: 10 | at: ~/ 11 | - run: 12 | name: Replace Auth0 test credentials 13 | command: | 14 | echo "var AUTH0_CLIENT_ID='$AUTH0_TEST_CLIENT_ID';" >> $AUTH0_CFG 15 | echo "var AUTH0_DOMAIN='$AUTH0_TEST_DOMAIN';" >> $AUTH0_CFG 16 | echo "var AUTH0_AUDIENCE='$AUTH0_TEST_AUDIENCE';" >> $AUTH0_CFG 17 | echo "var AUTH0_CALLBACK_URL=location.href;" >> $AUTH0_CFG 18 | 19 | - run: 20 | name: Build pull request 21 | command: | 22 | docker build -t $CIRCLE_JOB ./$SAMPLE_PATH 23 | docker run -d -p 3000:3000 --name $CIRCLE_SHA1 -e AUTH0_DOMAIN=$AUTH0_TEST_DOMAIN -e AUTH0_AUDIENCE=$AUTH0_TEST_API_IDENTIFIER $CIRCLE_JOB 24 | - run: 25 | name: Wait for app to be available 26 | command: | 27 | sleep 10 28 | docker run --network host --rm appropriate/curl --retry 8 --retry-connrefused -v localhost:3000 29 | - run: 30 | name: Run tests 31 | command: | 32 | docker create --network host --name tester codeception/codeceptjs codeceptjs run-multiple --all --steps --verbose 33 | docker cp $(pwd)/lock_login_test.js tester:/tests/lock_login_test.js 34 | docker cp $(pwd)/codecept.conf.js tester:/tests/codecept.conf.js 35 | docker start -i tester 36 | working_directory: scripts 37 | - run: 38 | name: Copy app container logs 39 | command: | 40 | mkdir -p /tmp/out 41 | docker logs $CIRCLE_SHA1 > /tmp/out/app_logs.log 42 | docker cp tester:/tests/out /tmp/ 43 | when: on_fail 44 | - store_artifacts: 45 | path: /tmp/out 46 | 47 | # Jobs and Workflows 48 | version: 2 49 | jobs: 50 | checkout: 51 | machine: true 52 | steps: 53 | - checkout 54 | - run: git clone https://github.com/auth0-samples/spa-quickstarts-tests scripts 55 | - persist_to_workspace: 56 | root: ~/ 57 | paths: 58 | - project 59 | - scripts 60 | 01-login: 61 | machine: true 62 | environment: 63 | - AUTH0_CFG: 01-Login/auth0-variables.js 64 | - SAMPLE_PATH: 01-Login 65 | <<: *defaults 66 | 02-user-profile: 67 | machine: true 68 | environment: 69 | - AUTH0_CFG: 02-User-Profile/auth0-variables.js 70 | - SAMPLE_PATH: 02-User-Profile 71 | <<: *defaults 72 | 03-calling-an-api: 73 | machine: true 74 | environment: 75 | - AUTH0_CFG: 03-Calling-an-API/auth0-variables.js 76 | - SAMPLE_PATH: 03-Calling-an-API 77 | <<: *defaults 78 | 04-authorization: 79 | machine: true 80 | environment: 81 | - AUTH0_CFG: 04-Authorization/auth0-variables.js 82 | - SAMPLE_PATH: 04-Authorization 83 | <<: *defaults 84 | 05-token-renewal: 85 | machine: true 86 | environment: 87 | - AUTH0_CFG: 05-Token-Renewal/auth0-variables.js 88 | - SAMPLE_PATH: 05-Token-Renewal 89 | <<: *defaults 90 | 91 | workflows: 92 | version: 2 93 | quickstarts_login: 94 | jobs: 95 | - checkout: 96 | context: Quickstart SPA Test 97 | - 01-login: 98 | context: Quickstart SPA Test 99 | requires: 100 | - checkout 101 | - 02-user-profile: 102 | context: Quickstart SPA Test 103 | requires: 104 | - checkout 105 | - 03-calling-an-api: 106 | context: Quickstart SPA Test 107 | requires: 108 | - checkout 109 | - 04-authorization: 110 | context: Quickstart SPA Test 111 | requires: 112 | - checkout 113 | - 05-token-renewal: 114 | context: Quickstart SPA Test 115 | requires: 116 | - checkout 117 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | # Number of days of inactivity before an Issue or Pull Request becomes stale 4 | daysUntilStale: 90 5 | 6 | # Number of days of inactivity before an Issue or Pull Request with the stale label is closed. 7 | daysUntilClose: 7 8 | 9 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable 10 | exemptLabels: [] 11 | 12 | # Set to true to ignore issues with an assignee (defaults to false) 13 | exemptAssignees: true 14 | 15 | # Label to use when marking as stale 16 | staleLabel: closed:stale 17 | 18 | # Comment to post when marking as stale. Set to `false` to disable 19 | markComment: > 20 | This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you have not received a response for our team (apologies for the delay) and this is still a blocker, please reply with additional information or just a ping. Thank you for your contribution! 🙇‍♂️ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules 3 | auth0-variables.js 4 | .env 5 | npm-debug.log -------------------------------------------------------------------------------- /01-Login/.dockerignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules 3 | .gitignore 4 | exec.sh 5 | exec.ps1 6 | README.md 7 | -------------------------------------------------------------------------------- /01-Login/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules 3 | auth0-variables.js 4 | .env -------------------------------------------------------------------------------- /01-Login/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:8.7-alpine 2 | 3 | WORKDIR /home/app 4 | 5 | RUN npm install -g create-react-app 6 | ADD package.json /home/app 7 | RUN npm install 8 | ADD . /home/app 9 | 10 | CMD ["npm", "start"] 11 | 12 | EXPOSE 3000 13 | -------------------------------------------------------------------------------- /01-Login/README.md: -------------------------------------------------------------------------------- 1 | # Auth0 jQuery Login 2 | 3 | This sample demonstrates how to add authentication to a jQuery application with Auth0. The sample makes use of Auth0's hosted login page which provides centralized authentication. 4 | 5 | ## Getting Started 6 | 7 | If you haven't already done so, [sign up](https://auth0.com) for your free Auth0 account and create a new client in the [dashboard](https://manage.auth0.com). Find the **domain** and **client ID** from the settings area and add the URL for your application to the **Allowed Callback URLs** box. If you are serving the application with the provided `serve` library, that URL is `http://localhost:3000`. 8 | 9 | Clone the repo or download it from the JavaScript quickstart page in Auth0's documentation. 10 | 11 | ```bash 12 | cd 01-Login 13 | npm install 14 | ``` 15 | 16 | ## Set the Client ID and Domain 17 | 18 | If you download the sample from the quickstart page, it will come pre-populated with the **client ID** and **domain** for your application. If you clone the repo directly from Github, rename the `auth0-variables.js.example` file to `auth0-variables.js` and provide the **client ID** and **domain** there. 19 | 20 | ## Run the Application 21 | 22 | The `serve` module provided with this sample can be run with the `start` command. 23 | 24 | ```bash 25 | npm start 26 | ``` 27 | 28 | The application will be served at `http://localhost:3000`. 29 | 30 | ## Run the Application With Docker 31 | 32 | In order to run the example with docker you need to have `docker` installed. 33 | 34 | You also need to set the environment variables as explained [previously](#set-the-client-id-and-domain). 35 | 36 | Execute in command line `sh exec.sh` to run the Docker in Linux, or `.\exec.ps1` to run the Docker in Windows. 37 | 38 | ## What is Auth0? 39 | 40 | Auth0 helps you to: 41 | 42 | * Add authentication with [multiple authentication sources](https://docs.auth0.com/identityproviders), either social like **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce, among others**, or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS or any SAML Identity Provider**. 43 | * Add authentication through more traditional **[username/password databases](https://docs.auth0.com/mysql-connection-tutorial)**. 44 | * Add support for **[linking different user accounts](https://docs.auth0.com/link-accounts)** with the same user. 45 | * Support for generating signed [Json Web Tokens](https://docs.auth0.com/jwt) to call your APIs and **flow the user identity** securely. 46 | * Analytics of how, when and where users are logging in. 47 | * Pull data from other sources and add it to the user profile, through [JavaScript rules](https://docs.auth0.com/rules). 48 | 49 | ## Create a free Auth0 account 50 | 51 | 1. Go to [Auth0](https://auth0.com/signup) and click Sign Up. 52 | 2. Use Google, GitHub or Microsoft Account to login. 53 | 54 | ## Issue Reporting 55 | 56 | If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. 57 | 58 | ## Author 59 | 60 | [Auth0](https://auth0.com) 61 | 62 | ## License 63 | 64 | This project is licensed under the MIT license. See the [LICENSE](LICENSE.txt) file for more info. 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /01-Login/app.js: -------------------------------------------------------------------------------- 1 | $('document').ready(function() { 2 | var content = $('.content'); 3 | var loadingSpinner = $('#loading'); 4 | content.css('display', 'block'); 5 | loadingSpinner.css('display', 'none');; 6 | 7 | var webAuth = new auth0.WebAuth({ 8 | domain: AUTH0_DOMAIN, 9 | clientID: AUTH0_CLIENT_ID, 10 | redirectUri: AUTH0_CALLBACK_URL, 11 | responseType: 'token id_token', 12 | scope: 'openid profile email', 13 | leeway: 60 14 | }); 15 | 16 | var loginStatus = $('.container h4'); 17 | var loginView = $('#login-view'); 18 | var homeView = $('#home-view'); 19 | 20 | // buttons and event listeners 21 | var homeViewBtn = $('#btn-home-view'); 22 | var loginBtn = $('#qsLoginBtn'); 23 | var logoutBtn = $('#qsLogoutBtn'); 24 | 25 | homeViewBtn.click(function() { 26 | homeView.css('display', 'inline-block'); 27 | loginView.css('display', 'none'); 28 | }); 29 | 30 | loginBtn.click(function(e) { 31 | e.preventDefault(); 32 | webAuth.authorize(); 33 | }); 34 | 35 | logoutBtn.click(logout); 36 | 37 | function setSession(authResult) { 38 | // Set the time that the access token will expire at 39 | var expiresAt = JSON.stringify( 40 | authResult.expiresIn * 1000 + new Date().getTime() 41 | ); 42 | localStorage.setItem('access_token', authResult.accessToken); 43 | localStorage.setItem('id_token', authResult.idToken); 44 | localStorage.setItem('expires_at', expiresAt); 45 | } 46 | 47 | function logout() { 48 | // Remove tokens and expiry time from localStorage 49 | localStorage.removeItem('access_token'); 50 | localStorage.removeItem('id_token'); 51 | localStorage.removeItem('expires_at'); 52 | displayButtons(); 53 | } 54 | 55 | function isAuthenticated() { 56 | // Check whether the current time is past the 57 | // access token's expiry time 58 | var expiresAt = JSON.parse(localStorage.getItem('expires_at')); 59 | return new Date().getTime() < expiresAt; 60 | } 61 | 62 | function handleAuthentication() { 63 | webAuth.parseHash(function(err, authResult) { 64 | if (authResult && authResult.accessToken && authResult.idToken) { 65 | window.location.hash = ''; 66 | setSession(authResult); 67 | loginBtn.css('display', 'none'); 68 | homeView.css('display', 'inline-block'); 69 | } else if (err) { 70 | homeView.css('display', 'inline-block'); 71 | console.log(err); 72 | alert( 73 | 'Error: ' + err.error + '. Check the console for further details.' 74 | ); 75 | } 76 | displayButtons(); 77 | }); 78 | } 79 | 80 | function displayButtons() { 81 | if (isAuthenticated()) { 82 | loginBtn.css('display', 'none'); 83 | logoutBtn.css('display', 'inline-block'); 84 | loginStatus.text('You are logged in!'); 85 | } else { 86 | loginBtn.css('display', 'inline-block'); 87 | logoutBtn.css('display', 'none'); 88 | loginStatus.text('You are not logged in! Please log in to continue.'); 89 | } 90 | } 91 | 92 | handleAuthentication(); 93 | }); 94 | -------------------------------------------------------------------------------- /01-Login/assets/loading.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /01-Login/auth0-variables.js.example: -------------------------------------------------------------------------------- 1 | var AUTH0_CLIENT_ID='{CLIENT_ID}'; 2 | var AUTH0_DOMAIN='{DOMAIN}'; 3 | var AUTH0_CALLBACK_URL=location.href; -------------------------------------------------------------------------------- /01-Login/exec.ps1: -------------------------------------------------------------------------------- 1 | docker build -t auth0-jquery-01-login . 2 | docker run -p 3000:3000 -it auth0-jquery-01-login 3 | -------------------------------------------------------------------------------- /01-Login/exec.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | docker build -t auth0-jquery-01-login . 3 | docker run -p 3000:3000 -it auth0-jquery-01-login 4 | -------------------------------------------------------------------------------- /01-Login/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Login 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | Loading spinner 16 |
17 | 18 |
19 | 39 | 40 |
41 | 42 |
43 |

44 |
45 | 46 |
47 | 48 |
49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /01-Login/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "custom-login", 3 | "version": "0.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "serve -p 3000" 8 | }, 9 | "author": "Auth0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "auth0-js": "^9.0.0", 13 | "bootstrap": "^3.3.7", 14 | "jquery": "^3.2.1" 15 | }, 16 | "devDependencies": { 17 | "serve": "^6.0.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /01-Login/style.css: -------------------------------------------------------------------------------- 1 | .content { 2 | display: none; 3 | } 4 | 5 | .btn-margin { 6 | margin-top: 7px 7 | } 8 | 9 | #login-view { 10 | display: none; 11 | } 12 | 13 | #loading { 14 | position: absolute; 15 | display: flex; 16 | justify-content: center; 17 | height: 100vh; 18 | width: 100vw; 19 | top: 0; 20 | bottom: 0; 21 | left: 0; 22 | right: 0; 23 | background-color: #fff; 24 | } -------------------------------------------------------------------------------- /02-User-Profile/.dockerignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules 3 | .gitignore 4 | exec.sh 5 | exec.ps1 6 | README.md 7 | -------------------------------------------------------------------------------- /02-User-Profile/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules 3 | auth0-variables.js 4 | .env -------------------------------------------------------------------------------- /02-User-Profile/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:8.7-alpine 2 | 3 | WORKDIR /home/app 4 | 5 | RUN npm install -g create-react-app 6 | ADD package.json /home/app 7 | RUN npm install 8 | ADD . /home/app 9 | 10 | CMD ["npm", "start"] 11 | 12 | EXPOSE 3000 13 | -------------------------------------------------------------------------------- /02-User-Profile/README.md: -------------------------------------------------------------------------------- 1 | # Auth0 jQuery User Profile 2 | 3 | This sample demonstrates how to get a user's profile using Auth0 in a jQuery application. 4 | 5 | ## Getting Started 6 | 7 | If you haven't already done so, [sign up](https://auth0.com) for your free Auth0 account and create a new client in the [dashboard](https://manage.auth0.com). Find the **domain** and **client ID** from the settings area and add the URL for your application to the **Allowed Callback URLs** box. If you are serving the application with the provided `serve` library, that URL is `http://localhost:3000`. 8 | 9 | Clone the repo or download it from the JavaScript quickstart page in Auth0's documentation. 10 | 11 | ```bash 12 | cd 02-User-Profile 13 | npm install 14 | ``` 15 | 16 | ## Set the Client ID and Domain 17 | 18 | If you download the sample from the quickstart page, it will come pre-populated with the **client ID** and **domain** for your application. If you clone the repo directly from Github, rename the `auth0-variables.js.example` file to `auth0-variables.js` and provide the **client ID** and **domain** there. 19 | 20 | ## Run the Application 21 | 22 | The `serve` module provided with this sample can be run with the `start` command. 23 | 24 | ```bash 25 | npm start 26 | ``` 27 | 28 | The application will be served at `http://localhost:3000`. 29 | 30 | ## Run the Application With Docker 31 | 32 | In order to run the example with docker you need to have `docker` installed. 33 | 34 | You also need to set the environment variables as explained [previously](#set-the-client-id-and-domain). 35 | 36 | Execute in command line `sh exec.sh` to run the Docker in Linux, or `.\exec.ps1` to run the Docker in Windows. 37 | 38 | ## What is Auth0? 39 | 40 | Auth0 helps you to: 41 | 42 | * Add authentication with [multiple authentication sources](https://docs.auth0.com/identityproviders), either social like **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce, among others**, or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS or any SAML Identity Provider**. 43 | * Add authentication through more traditional **[username/password databases](https://docs.auth0.com/mysql-connection-tutorial)**. 44 | * Add support for **[linking different user accounts](https://docs.auth0.com/link-accounts)** with the same user. 45 | * Support for generating signed [Json Web Tokens](https://docs.auth0.com/jwt) to call your APIs and **flow the user identity** securely. 46 | * Analytics of how, when and where users are logging in. 47 | * Pull data from other sources and add it to the user profile, through [JavaScript rules](https://docs.auth0.com/rules). 48 | 49 | ## Create a free Auth0 account 50 | 51 | 1. Go to [Auth0](https://auth0.com/signup) and click Sign Up. 52 | 2. Use Google, GitHub or Microsoft Account to login. 53 | 54 | ## Issue Reporting 55 | 56 | If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. 57 | 58 | ## Author 59 | 60 | [Auth0](https://auth0.com) 61 | 62 | ## License 63 | 64 | This project is licensed under the MIT license. See the [LICENSE](LICENSE.txt) file for more info. 65 | 66 | 67 | -------------------------------------------------------------------------------- /02-User-Profile/app.js: -------------------------------------------------------------------------------- 1 | $('document').ready(function() { 2 | var userProfile; 3 | var content = $('.content'); 4 | var loadingSpinner = $('#loading'); 5 | content.css('display', 'block'); 6 | loadingSpinner.css('display', 'none'); 7 | 8 | var webAuth = new auth0.WebAuth({ 9 | domain: AUTH0_DOMAIN, 10 | clientID: AUTH0_CLIENT_ID, 11 | redirectUri: AUTH0_CALLBACK_URL, 12 | responseType: 'token id_token', 13 | scope: 'openid profile', 14 | leeway: 60 15 | }); 16 | 17 | var loginStatus = $('.container h4'); 18 | var loginView = $('#login-view'); 19 | var homeView = $('#home-view'); 20 | var profileView = $('#profile-view'); 21 | 22 | // buttons and event listeners 23 | var loginBtn = $('#qsLoginBtn'); 24 | var logoutBtn = $('#qsLogoutBtn'); 25 | 26 | var homeViewBtn = $('#btn-home-view'); 27 | var profileViewBtn = $('#btn-profile-view'); 28 | 29 | homeViewBtn.click(function() { 30 | homeView.css('display', 'inline-block'); 31 | profileView.css('display', 'none'); 32 | }); 33 | 34 | profileViewBtn.click(function() { 35 | homeView.css('display', 'none'); 36 | profileView.css('display', 'inline-block'); 37 | getProfile(); 38 | }); 39 | 40 | loginBtn.click(function(e) { 41 | e.preventDefault(); 42 | webAuth.authorize(); 43 | }); 44 | 45 | logoutBtn.click(logout); 46 | 47 | function setSession(authResult) { 48 | // Set the time that the access token will expire at 49 | var expiresAt = JSON.stringify( 50 | authResult.expiresIn * 1000 + new Date().getTime() 51 | ); 52 | localStorage.setItem('access_token', authResult.accessToken); 53 | localStorage.setItem('id_token', authResult.idToken); 54 | localStorage.setItem('expires_at', expiresAt); 55 | } 56 | 57 | function logout() { 58 | // Remove tokens and expiry time from localStorage 59 | localStorage.removeItem('access_token'); 60 | localStorage.removeItem('id_token'); 61 | localStorage.removeItem('expires_at'); 62 | displayButtons(); 63 | } 64 | 65 | function isAuthenticated() { 66 | // Check whether the current time is past the 67 | // access token's expiry time 68 | var expiresAt = JSON.parse(localStorage.getItem('expires_at')); 69 | return new Date().getTime() < expiresAt; 70 | } 71 | 72 | function displayButtons() { 73 | var loginStatus = $('.container h4'); 74 | if (isAuthenticated()) { 75 | loginBtn.css('display', 'none'); 76 | logoutBtn.css('display', 'inline-block'); 77 | profileViewBtn.css('display', 'inline-block'); 78 | loginStatus.text( 79 | 'You are logged in! You can now view your profile area.' 80 | ); 81 | } else { 82 | homeView.css('display', 'inline-block'); 83 | loginBtn.css('display', 'inline-block'); 84 | logoutBtn.css('display', 'none'); 85 | profileViewBtn.css('display', 'none'); 86 | profileView.css('display', 'none'); 87 | loginStatus.text('You are not logged in! Please log in to continue.'); 88 | } 89 | } 90 | 91 | function getProfile() { 92 | if (!userProfile) { 93 | var accessToken = localStorage.getItem('access_token'); 94 | 95 | if (!accessToken) { 96 | console.log('Access token must exist to fetch profile'); 97 | } 98 | 99 | webAuth.client.userInfo(accessToken, function(err, profile) { 100 | if (profile) { 101 | userProfile = profile; 102 | displayProfile(); 103 | } 104 | }); 105 | } else { 106 | displayProfile(); 107 | } 108 | } 109 | 110 | function displayProfile() { 111 | // display the profile 112 | $('#profile-view .nickname').text(userProfile.nickname); 113 | $('#profile-view .full-profile').text(JSON.stringify(userProfile, null, 2)); 114 | $('#profile-view img').attr('src', userProfile.picture); 115 | } 116 | 117 | function handleAuthentication() { 118 | webAuth.parseHash(function(err, authResult) { 119 | if (authResult && authResult.accessToken && authResult.idToken) { 120 | window.location.hash = ''; 121 | setSession(authResult); 122 | loginBtn.css('display', 'none'); 123 | homeView.css('display', 'inline-block'); 124 | } else if (err) { 125 | homeView.css('display', 'inline-block'); 126 | console.log(err); 127 | alert( 128 | 'Error: ' + err.error + '. Check the console for further details.' 129 | ); 130 | } 131 | displayButtons(); 132 | }); 133 | } 134 | 135 | handleAuthentication(); 136 | }); 137 | -------------------------------------------------------------------------------- /02-User-Profile/assets/loading.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /02-User-Profile/auth0-variables.js.example: -------------------------------------------------------------------------------- 1 | var AUTH0_CLIENT_ID='{CLIENT_ID}'; 2 | var AUTH0_DOMAIN='{DOMAIN}'; 3 | var AUTH0_CALLBACK_URL=location.href; 4 | 5 | -------------------------------------------------------------------------------- /02-User-Profile/exec.ps1: -------------------------------------------------------------------------------- 1 | docker build -t auth0-jquery-02-user-profile . 2 | docker run -p 3000:3000 -it auth0-jquery-02-user-profile 3 | -------------------------------------------------------------------------------- /02-User-Profile/exec.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | docker build -t auth0-jquery-02-user-profile . 3 | docker run -p 3000:3000 -it auth0-jquery-02-user-profile 4 | -------------------------------------------------------------------------------- /02-User-Profile/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | User Profile 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | Loading spinner 16 |
17 | 18 |
19 | 43 | 44 |
45 | 46 |
47 |

48 |
49 | 50 | 51 |
52 |

Profile

53 |
54 | avatar 55 |
56 | 57 |

58 |
59 |

60 |           
61 |
62 |
63 |
64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /02-User-Profile/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "user-profile", 3 | "version": "0.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "serve -p 3000" 8 | }, 9 | "author": "Auth0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "auth0-js": "^9.0.0", 13 | "bootstrap": "^3.3.7", 14 | "jquery": "^3.2.1" 15 | }, 16 | "devDependencies": { 17 | "serve": "^6.0.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /02-User-Profile/style.css: -------------------------------------------------------------------------------- 1 | .content { 2 | display: none; 3 | } 4 | 5 | .btn-margin { 6 | margin-top: 7px 7 | } 8 | 9 | #profile-view { 10 | display: none; 11 | } 12 | 13 | .profile-area img { 14 | max-width: 150px; 15 | margin-bottom: 20px; 16 | } 17 | 18 | .panel-body h3 { 19 | margin-top: 0; 20 | } 21 | 22 | #loading { 23 | position: absolute; 24 | display: flex; 25 | justify-content: center; 26 | height: 100vh; 27 | width: 100vw; 28 | top: 0; 29 | bottom: 0; 30 | left: 0; 31 | right: 0; 32 | background-color: #fff; 33 | } -------------------------------------------------------------------------------- /03-Calling-an-API/.dockerignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules 3 | .gitignore 4 | exec.sh 5 | exec.ps1 6 | README.md 7 | -------------------------------------------------------------------------------- /03-Calling-an-API/.env.example: -------------------------------------------------------------------------------- 1 | AUTH0_AUDIENCE={API_IDENTIFIER} 2 | AUTH0_DOMAIN={DOMAIN} 3 | -------------------------------------------------------------------------------- /03-Calling-an-API/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules 3 | auth0-variables.js 4 | .env -------------------------------------------------------------------------------- /03-Calling-an-API/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:8.7-alpine 2 | 3 | WORKDIR /home/app 4 | 5 | RUN npm install -g create-react-app 6 | ADD package.json /home/app 7 | RUN npm install 8 | ADD . /home/app 9 | 10 | CMD ["npm", "start"] 11 | 12 | EXPOSE 3000 3001 13 | -------------------------------------------------------------------------------- /03-Calling-an-API/README.md: -------------------------------------------------------------------------------- 1 | # Auth0 jQuery Calling an API 2 | 3 | This sample demonstrates how to make secure calls to an API after authenticating a user with Auth0. The calls to the API are made with the user's `access_token`. 4 | 5 | ## Getting Started 6 | 7 | If you haven't already done so, [sign up](https://auth0.com) for your free Auth0 account and create a new client in the [dashboard](https://manage.auth0.com). Find the **domain** and **client ID** from the settings area and add the URL for your application to the **Allowed Callback URLs** box. If you are serving the application with the provided `serve` library, that URL is `http://localhost:3000`. 8 | 9 | If you haven't already done so, create a new API in the [APIs section](https://manage.auth0.com/#/apis) and provide an identifier for it. 10 | 11 | Clone the repo or download it from the JavaScript quickstart page in Auth0's documentation. 12 | 13 | ```bash 14 | cd 03-Calling-an-API 15 | npm install 16 | ``` 17 | 18 | ## Set the Client ID, Domain, and API URL 19 | 20 | If you download the sample from the quickstart page, it will come pre-populated with the **client ID** and **domain** for your application. If you clone the repo directly from Github, rename the `auth0-variables.js.example` file to `auth0-variables.js` and provide the **client ID** and **domain** there. 21 | 22 | You should also provide the identifier for the API you create in the Auth0 dashboard as your `apiUrl`. 23 | 24 | ## Set Up the `.env` File 25 | 26 | In addition to the above-mentioned `auth0-variables.js` file, a `.env` file is provided at the root of the application. This file provides your application's credentials to the small Node server located in `server.js`. 27 | 28 | This file has two values, `AUTH0_AUDIENCE` and `AUTH0_DOMAIN`. If you download this sample from the quickstart page, the value for `AUTH0_DOMAIN` will be populated automatically, but you will still need to populate `AUTH0_AUDIENCE` manually. The value for `AUTH0_AUDIENCE` is the identifier used for an API that you create in the Auth0 dashboard. 29 | 30 | ## Run the Application 31 | 32 | The `serve` module provided with this sample can be run with the `start` command. 33 | 34 | ```bash 35 | npm start 36 | ``` 37 | 38 | The application will be served at `http://localhost:3000`. 39 | 40 | ## Run the Application With Docker 41 | 42 | In order to run the example with docker you need to have `docker` installed. 43 | 44 | You also need to set the environment variables as explained [previously](#set-the-client-id-domain-and-api-url). 45 | 46 | Execute in command line `sh exec.sh` to run the Docker in Linux, or `.\exec.ps1` to run the Docker in Windows. 47 | 48 | ## What is Auth0? 49 | 50 | Auth0 helps you to: 51 | 52 | * Add authentication with [multiple authentication sources](https://docs.auth0.com/identityproviders), either social like **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce, among others**, or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS or any SAML Identity Provider**. 53 | * Add authentication through more traditional **[username/password databases](https://docs.auth0.com/mysql-connection-tutorial)**. 54 | * Add support for **[linking different user accounts](https://docs.auth0.com/link-accounts)** with the same user. 55 | * Support for generating signed [Json Web Tokens](https://docs.auth0.com/jwt) to call your APIs and **flow the user identity** securely. 56 | * Analytics of how, when and where users are logging in. 57 | * Pull data from other sources and add it to the user profile, through [JavaScript rules](https://docs.auth0.com/rules). 58 | 59 | ## Create a free Auth0 account 60 | 61 | 1. Go to [Auth0](https://auth0.com/signup) and click Sign Up. 62 | 2. Use Google, GitHub or Microsoft Account to login. 63 | 64 | ## Issue Reporting 65 | 66 | If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. 67 | 68 | ## Author 69 | 70 | [Auth0](https://auth0.com) 71 | 72 | ## License 73 | 74 | This project is licensed under the MIT license. See the [LICENSE](LICENSE.txt) file for more info. 75 | 76 | 77 | -------------------------------------------------------------------------------- /03-Calling-an-API/app.js: -------------------------------------------------------------------------------- 1 | $('document').ready(function() { 2 | var content = $('.content'); 3 | var loadingSpinner = $('#loading'); 4 | content.css('display', 'block'); 5 | loadingSpinner.css('display', 'none'); 6 | 7 | var userProfile; 8 | var apiUrl = 'http://localhost:3001/api'; 9 | 10 | var webAuth = new auth0.WebAuth({ 11 | domain: AUTH0_DOMAIN, 12 | clientID: AUTH0_CLIENT_ID, 13 | redirectUri: AUTH0_CALLBACK_URL, 14 | audience: AUTH0_AUDIENCE, 15 | responseType: 'token id_token', 16 | scope: 'openid profile read:messages', 17 | leeway: 60 18 | }); 19 | 20 | var homeView = $('#home-view'); 21 | var profileView = $('#profile-view'); 22 | var pingView = $('#ping-view'); 23 | 24 | // buttons and event listeners 25 | var loginBtn = $('#qsLoginBtn'); 26 | var logoutBtn = $('#qsLogoutBtn'); 27 | 28 | var homeViewBtn = $('#btn-home-view'); 29 | var profileViewBtn = $('#btn-profile-view'); 30 | var pingViewBtn = $('#btn-ping-view'); 31 | 32 | var pingPublic = $('#btn-ping-public'); 33 | var pingPrivate = $('#btn-ping-private'); 34 | var pingPrivateScoped = $('#btn-ping-private-scoped'); 35 | 36 | var callPrivateMessage = $('#call-private-message'); 37 | var pingMessage = $('#ping-message'); 38 | 39 | pingPublic.click(function() { 40 | callAPI('/public', false); 41 | }); 42 | 43 | pingPrivate.click(function() { 44 | callAPI('/private', true); 45 | }); 46 | 47 | pingPrivateScoped.click(function() { 48 | callAPI('/private-scoped', true); 49 | }); 50 | 51 | loginBtn.click(login); 52 | logoutBtn.click(logout); 53 | 54 | homeViewBtn.click(function() { 55 | homeView.css('display', 'inline-block'); 56 | profileView.css('display', 'none'); 57 | pingView.css('display', 'none'); 58 | }); 59 | 60 | profileViewBtn.click(function() { 61 | homeView.css('display', 'none'); 62 | pingView.css('display', 'none'); 63 | profileView.css('display', 'inline-block'); 64 | getProfile(); 65 | }); 66 | 67 | pingViewBtn.click(function() { 68 | homeView.css('display', 'none'); 69 | profileView.css('display', 'none'); 70 | pingView.css('display', 'inline-block'); 71 | }); 72 | 73 | function login() { 74 | webAuth.authorize(); 75 | } 76 | 77 | function setSession(authResult) { 78 | // Set the time that the access token will expire at 79 | var expiresAt = JSON.stringify( 80 | authResult.expiresIn * 1000 + new Date().getTime() 81 | ); 82 | localStorage.setItem('access_token', authResult.accessToken); 83 | localStorage.setItem('id_token', authResult.idToken); 84 | localStorage.setItem('expires_at', expiresAt); 85 | } 86 | 87 | function logout() { 88 | // Remove tokens and expiry time from localStorage 89 | localStorage.removeItem('access_token'); 90 | localStorage.removeItem('id_token'); 91 | localStorage.removeItem('expires_at'); 92 | pingMessage.css('display', 'none'); 93 | displayButtons(); 94 | } 95 | 96 | function isAuthenticated() { 97 | // Check whether the current time is past the 98 | // access token's expiry time 99 | var expiresAt = JSON.parse(localStorage.getItem('expires_at')); 100 | return new Date().getTime() < expiresAt; 101 | } 102 | 103 | function displayButtons() { 104 | var loginStatus = $('.container h4'); 105 | if (isAuthenticated()) { 106 | loginBtn.css('display', 'none'); 107 | logoutBtn.css('display', 'inline-block'); 108 | profileViewBtn.css('display', 'inline-block'); 109 | pingPrivate.css('display', 'inline-block'); 110 | pingPrivateScoped.css('display', 'inline-block'); 111 | callPrivateMessage.css('display', 'none'); 112 | loginStatus.text( 113 | 'You are logged in! You can now send authenticated requests to your server.' 114 | ); 115 | } else { 116 | homeView.css('display', 'inline-block'); 117 | loginBtn.css('display', 'inline-block'); 118 | logoutBtn.css('display', 'none'); 119 | profileViewBtn.css('display', 'none'); 120 | profileView.css('display', 'none'); 121 | pingView.css('display', 'none'); 122 | pingPrivate.css('display', 'none'); 123 | pingPrivateScoped.css('display', 'none'); 124 | callPrivateMessage.css('display', 'block'); 125 | loginStatus.text('You are not logged in! Please log in to continue.'); 126 | } 127 | } 128 | 129 | function getProfile() { 130 | if (!userProfile) { 131 | var accessToken = localStorage.getItem('access_token'); 132 | 133 | if (!accessToken) { 134 | console.log('Access token must exist to fetch profile'); 135 | } 136 | 137 | webAuth.client.userInfo(accessToken, function(err, profile) { 138 | if (profile) { 139 | userProfile = profile; 140 | displayProfile(); 141 | } 142 | }); 143 | } else { 144 | displayProfile(); 145 | } 146 | } 147 | 148 | function displayProfile() { 149 | // display the profile 150 | $('#profile-view .nickname').text(userProfile.nickname); 151 | $('#profile-view .full-profile').text(JSON.stringify(userProfile, null, 2)); 152 | $('#profile-view img').attr('src', userProfile.picture); 153 | } 154 | 155 | function handleAuthentication() { 156 | webAuth.parseHash(function(err, authResult) { 157 | if (authResult && authResult.accessToken && authResult.idToken) { 158 | window.location.hash = ''; 159 | setSession(authResult); 160 | loginBtn.css('display', 'none'); 161 | homeView.css('display', 'inline-block'); 162 | } else if (err) { 163 | homeView.css('display', 'inline-block'); 164 | console.log(err); 165 | alert( 166 | 'Error: ' + err.error + '. Check the console for further details.' 167 | ); 168 | } 169 | displayButtons(); 170 | }); 171 | } 172 | 173 | handleAuthentication(); 174 | 175 | function callAPI(endpoint, secured) { 176 | var url = apiUrl + endpoint; 177 | var accessToken = localStorage.getItem('access_token'); 178 | 179 | var headers; 180 | if (secured && accessToken) { 181 | headers = { Authorization: 'Bearer ' + accessToken }; 182 | } 183 | 184 | $.ajax({ 185 | url: url, 186 | headers: headers 187 | }) 188 | .done(function(result) { 189 | $('#ping-view h2').text(result.message); 190 | }) 191 | .fail(function(err) { 192 | $('#ping-view h2').text('Request failed: ' + err.statusText); 193 | }); 194 | } 195 | 196 | displayButtons(); 197 | }); 198 | -------------------------------------------------------------------------------- /03-Calling-an-API/assets/loading.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /03-Calling-an-API/auth0-variables.js.example: -------------------------------------------------------------------------------- 1 | var AUTH0_CLIENT_ID = '{CLIENT_ID}'; 2 | var AUTH0_DOMAIN = '{DOMAIN}'; 3 | var AUTH0_AUDIENCE = '{API_IDENTIFIER}'; 4 | var AUTH0_CALLBACK_URL = location.href; 5 | 6 | -------------------------------------------------------------------------------- /03-Calling-an-API/exec.ps1: -------------------------------------------------------------------------------- 1 | docker build -t auth0-jquery-03-calling-an-api . 2 | docker run -p 3000:3000 -p 3001:3001 -it auth0-jquery-03-calling-an-api 3 | -------------------------------------------------------------------------------- /03-Calling-an-API/exec.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | docker build -t auth0-jquery-03-calling-an-api . 3 | docker run -p 3000:3000 -p 3001:3001 -it auth0-jquery-03-calling-an-api 4 | -------------------------------------------------------------------------------- /03-Calling-an-API/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Calling an API 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | Loading spinner 16 |
17 | 18 |
19 | 47 | 48 |
49 | 50 |
51 |

52 |
53 | 54 | 55 |
56 |

Profile

57 |
58 | avatar 59 |
60 | 61 |

62 |
63 |

64 |         
65 |
66 | 67 | 68 |
69 |

Make a Call to the Server

70 | 71 |

72 | Log in to call a private (secured) server endpoint. 73 |

74 | 75 | 78 | 79 | 82 | 83 | 86 | 87 |

88 |
89 |
90 |
91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /03-Calling-an-API/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "calling-an-api", 3 | "version": "0.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "start": "npm-run-all --parallel server client", 8 | "server": "node server.js", 9 | "client": "serve -p 3000" 10 | }, 11 | "author": "Auth0", 12 | "license": "MIT", 13 | "dependencies": { 14 | "auth0-js": "^9.0.0", 15 | "bootstrap": "^3.3.7", 16 | "cors": "^2.8.3", 17 | "dotenv": "^4.0.0", 18 | "express": "^4.15.3", 19 | "express-jwt": "^5.3.0", 20 | "express-jwt-authz": "^1.0.0", 21 | "jquery": "^3.2.1", 22 | "jwks-rsa": "^1.2.0", 23 | "npm-run-all": "^4.0.2", 24 | "serve": "^6.0.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /03-Calling-an-API/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const jwt = require('express-jwt'); 4 | const jwtAuthz = require('express-jwt-authz'); 5 | const jwksRsa = require('jwks-rsa'); 6 | const cors = require('cors'); 7 | require('dotenv').config(); 8 | 9 | if (!process.env.AUTH0_DOMAIN || !process.env.AUTH0_AUDIENCE) { 10 | throw 'Make sure you have AUTH0_DOMAIN, and AUTH0_AUDIENCE in your .env file' 11 | } 12 | 13 | app.use(cors()); 14 | 15 | const checkJwt = jwt({ 16 | // Dynamically provide a signing key based on the kid in the header and the singing keys provided by the JWKS endpoint. 17 | secret: jwksRsa.expressJwtSecret({ 18 | cache: true, 19 | rateLimit: true, 20 | jwksRequestsPerMinute: 5, 21 | jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json` 22 | }), 23 | 24 | // Validate the audience and the issuer. 25 | audience: process.env.AUTH0_AUDIENCE, 26 | issuer: `https://${process.env.AUTH0_DOMAIN}/`, 27 | algorithms: ['RS256'] 28 | }); 29 | 30 | const checkScopes = jwtAuthz([ 'read:messages' ]); 31 | 32 | app.get('/api/public', function(req, res) { 33 | res.json({ message: "Hello from a public endpoint! You don't need to be authenticated to see this." }); 34 | }); 35 | 36 | app.get('/api/private', checkJwt, function(req, res) { 37 | res.json({ message: "Hello from a private endpoint! You need to be authenticated to see this." }); 38 | }); 39 | 40 | app.get('/api/private-scoped', checkJwt, checkScopes, function(req, res) { 41 | res.json({ message: "Hello from a private endpoint! You need to be authenticated and have a scope of read:messages to see this." }); 42 | }); 43 | 44 | app.listen(3001); 45 | console.log('Listening on http://localhost:3001'); 46 | -------------------------------------------------------------------------------- /03-Calling-an-API/style.css: -------------------------------------------------------------------------------- 1 | .content { 2 | display: none; 3 | } 4 | 5 | .btn-margin { 6 | margin-top: 7px 7 | } 8 | 9 | #profile-view, 10 | #ping-view { 11 | display: none; 12 | } 13 | 14 | .profile-area img { 15 | max-width: 150px; 16 | margin-bottom: 20px; 17 | } 18 | 19 | .panel-body h3 { 20 | margin-top: 0; 21 | } 22 | 23 | #loading { 24 | position: absolute; 25 | display: flex; 26 | justify-content: center; 27 | height: 100vh; 28 | width: 100vw; 29 | top: 0; 30 | bottom: 0; 31 | left: 0; 32 | right: 0; 33 | background-color: #fff; 34 | } -------------------------------------------------------------------------------- /04-Authorization/.dockerignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules 3 | .gitignore 4 | exec.sh 5 | exec.ps1 6 | README.md 7 | -------------------------------------------------------------------------------- /04-Authorization/.env.example: -------------------------------------------------------------------------------- 1 | AUTH0_AUDIENCE={API_IDENTIFIER} 2 | AUTH0_DOMAIN={DOMAIN} 3 | -------------------------------------------------------------------------------- /04-Authorization/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules 3 | auth0-variables.js 4 | .env -------------------------------------------------------------------------------- /04-Authorization/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:8.7-alpine 2 | 3 | WORKDIR /home/app 4 | 5 | RUN npm install -g create-react-app 6 | ADD package.json /home/app 7 | RUN npm install 8 | ADD . /home/app 9 | 10 | CMD ["npm", "start"] 11 | 12 | EXPOSE 3000 3001 13 | -------------------------------------------------------------------------------- /04-Authorization/README.md: -------------------------------------------------------------------------------- 1 | # Auth0 jQuery Authorization 2 | 3 | This sample demonstrates how to include user authorization in a jQuery application with Auth0. 4 | 5 | ## Getting Started 6 | 7 | If you haven't already done so, [sign up](https://auth0.com) for your free Auth0 account and create a new client in the [dashboard](https://manage.auth0.com). Find the **domain** and **client ID** from the settings area and add the URL for your application to the **Allowed Callback URLs** box. If you are serving the application with the provided `serve` library, that URL is `http://localhost:3000`. 8 | 9 | If you haven't already done so, create a new API in the [APIs section](https://manage.auth0.com/#/apis) and provide an identifier for it. 10 | 11 | Clone the repo or download it from the JavaScript quickstart page in Auth0's documentation. 12 | 13 | ```bash 14 | cd 04-Authorization 15 | npm install 16 | ``` 17 | 18 | ## Set the Client ID, Domain, and API URL 19 | 20 | If you download the sample from the quickstart page, it will come pre-populated with the **client ID** and **domain** for your application. If you clone the repo directly from Github, rename the `auth0-variables.js.example` file to `auth0-variables.js` and provide the **client ID** and **domain** there. 21 | 22 | You should also provide the identifier for the API you create in the Auth0 dashboard as your `apiUrl`. 23 | 24 | ## Set Up the `.env` File 25 | 26 | In addition to the above-mentioned `auth0-variables.js` file, a `.env` file is provided at the root of the application. This file provides your application's credentials to the small Node server located in `server.js`. 27 | 28 | This file has two values, `AUTH0_AUDIENCE` and `AUTH0_DOMAIN`. If you download this sample from the quickstart page, the value for `AUTH0_DOMAIN` will be populated automatically, but you will still need to populate `AUTH0_AUDIENCE` manually. The value for `AUTH0_AUDIENCE` is the identifier used for an API that you create in the Auth0 dashboard. 29 | 30 | ## Run the Application 31 | 32 | The `serve` module provided with this sample can be run with the `start` command. 33 | 34 | ```bash 35 | npm start 36 | ``` 37 | 38 | The application will be served at `http://localhost:3000`. 39 | 40 | ## Run the Application With Docker 41 | 42 | In order to run the example with docker you need to have `docker` installed. 43 | 44 | You also need to set the environment variables as explained [previously](#set-the-client-id-and-domain). 45 | 46 | Execute in command line `sh exec.sh` to run the Docker in Linux, or `.\exec.ps1` to run the Docker in Windows. 47 | 48 | ## What is Auth0? 49 | 50 | Auth0 helps you to: 51 | 52 | * Add authentication with [multiple authentication sources](https://docs.auth0.com/identityproviders), either social like **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce, among others**, or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS or any SAML Identity Provider**. 53 | * Add authentication through more traditional **[username/password databases](https://docs.auth0.com/mysql-connection-tutorial)**. 54 | * Add support for **[linking different user accounts](https://docs.auth0.com/link-accounts)** with the same user. 55 | * Support for generating signed [Json Web Tokens](https://docs.auth0.com/jwt) to call your APIs and **flow the user identity** securely. 56 | * Analytics of how, when and where users are logging in. 57 | * Pull data from other sources and add it to the user profile, through [JavaScript rules](https://docs.auth0.com/rules). 58 | 59 | ## Create a free Auth0 account 60 | 61 | 1. Go to [Auth0](https://auth0.com/signup) and click Sign Up. 62 | 2. Use Google, GitHub or Microsoft Account to login. 63 | 64 | ## Issue Reporting 65 | 66 | If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. 67 | 68 | ## Author 69 | 70 | [Auth0](https://auth0.com) 71 | 72 | ## License 73 | 74 | This project is licensed under the MIT license. See the [LICENSE](LICENSE.txt) file for more info. 75 | 76 | 77 | -------------------------------------------------------------------------------- /04-Authorization/app.js: -------------------------------------------------------------------------------- 1 | $('document').ready(function() { 2 | var content = $('.content'); 3 | var loadingSpinner = $('#loading'); 4 | content.css('display', 'block'); 5 | loadingSpinner.css('display', 'none'); 6 | 7 | var userProfile; 8 | var apiUrl = 'http://localhost:3001/api'; 9 | var requestedScopes = 'openid profile read:messages write:messages'; 10 | 11 | var webAuth = new auth0.WebAuth({ 12 | domain: AUTH0_DOMAIN, 13 | clientID: AUTH0_CLIENT_ID, 14 | redirectUri: AUTH0_CALLBACK_URL, 15 | audience: AUTH0_AUDIENCE, 16 | responseType: 'token id_token', 17 | scope: requestedScopes, 18 | leeway: 60 19 | }); 20 | 21 | var homeView = $('#home-view'); 22 | var profileView = $('#profile-view'); 23 | var pingView = $('#ping-view'); 24 | var adminView = $('#admin-view'); 25 | 26 | // buttons and event listeners 27 | var loginBtn = $('#qsLoginBtn'); 28 | var logoutBtn = $('#qsLogoutBtn'); 29 | 30 | var homeViewBtn = $('#btn-home-view'); 31 | var profileViewBtn = $('#btn-profile-view'); 32 | var pingViewBtn = $('#btn-ping-view'); 33 | var adminViewBtn = $('#btn-admin-view'); 34 | 35 | var pingPublic = $('#btn-ping-public'); 36 | var pingPrivate = $('#btn-ping-private'); 37 | var pingPrivateScoped = $('#btn-ping-private-scoped'); 38 | var pingAdmin = $('#btn-ping-admin'); 39 | 40 | var callPrivateMessage = $('#call-private-message'); 41 | var pingMessage = $('#ping-message'); 42 | var adminMessage = $('#admin-message'); 43 | 44 | pingPublic.click(function() { 45 | callAPI('/public', false, 'GET', function(err, message) { 46 | if (err) { 47 | alert(err); 48 | return; 49 | } 50 | pingMessage.text(message); 51 | }); 52 | }); 53 | 54 | pingPrivate.click(function() { 55 | callAPI('/private', true, 'GET', function(err, message) { 56 | if (err) { 57 | alert(err); 58 | return; 59 | } 60 | pingMessage.text(message); 61 | }); 62 | }); 63 | 64 | pingPrivateScoped.click(function() { 65 | callAPI('/private-scoped', true, 'GET', function(err, message) { 66 | if (err) { 67 | alert(err); 68 | return; 69 | } 70 | pingMessage.text(message); 71 | }); 72 | }); 73 | 74 | pingAdmin.click(function() { 75 | callAPI('/admin', true, 'POST', function(err, message) { 76 | if (err) { 77 | alert(err); 78 | return; 79 | } 80 | adminMessage.text(message); 81 | }); 82 | }); 83 | 84 | loginBtn.click(login); 85 | logoutBtn.click(logout); 86 | 87 | homeViewBtn.click(function() { 88 | homeView.css('display', 'inline-block'); 89 | profileView.css('display', 'none'); 90 | pingView.css('display', 'none'); 91 | adminView.css('display', 'none'); 92 | }); 93 | 94 | profileViewBtn.click(function() { 95 | homeView.css('display', 'none'); 96 | pingView.css('display', 'none'); 97 | adminView.css('display', 'none'); 98 | profileView.css('display', 'inline-block'); 99 | getProfile(); 100 | }); 101 | 102 | pingViewBtn.click(function() { 103 | homeView.css('display', 'none'); 104 | profileView.css('display', 'none'); 105 | adminView.css('display', 'none'); 106 | pingView.css('display', 'inline-block'); 107 | }); 108 | 109 | adminViewBtn.click(function() { 110 | homeView.css('display', 'none'); 111 | profileView.css('display', 'none'); 112 | pingView.css('display', 'none'); 113 | adminView.css('display', 'inline-block'); 114 | }); 115 | 116 | function login() { 117 | webAuth.authorize(); 118 | } 119 | 120 | function setSession(authResult) { 121 | // Set the time that the access token will expire at 122 | var expiresAt = JSON.stringify( 123 | authResult.expiresIn * 1000 + new Date().getTime() 124 | ); 125 | 126 | // If there is a value on the `scope` param from the authResult, 127 | // use it to set scopes in the session for the user. Otherwise 128 | // use the scopes as requested. If no scopes were requested, 129 | // set it to nothing 130 | const scopes = authResult.scope || requestedScopes || ''; 131 | 132 | localStorage.setItem('access_token', authResult.accessToken); 133 | localStorage.setItem('id_token', authResult.idToken); 134 | localStorage.setItem('expires_at', expiresAt); 135 | localStorage.setItem('scopes', JSON.stringify(scopes)); 136 | } 137 | 138 | function logout() { 139 | // Remove tokens and expiry time from localStorage 140 | localStorage.removeItem('access_token'); 141 | localStorage.removeItem('id_token'); 142 | localStorage.removeItem('expires_at'); 143 | localStorage.removeItem('scopes'); 144 | pingMessage.css('display', 'none'); 145 | adminMessage.css('display', 'none'); 146 | displayButtons(); 147 | } 148 | 149 | function isAuthenticated() { 150 | // Check whether the current time is past the 151 | // access token's expiry time 152 | var expiresAt = JSON.parse(localStorage.getItem('expires_at')); 153 | return new Date().getTime() < expiresAt; 154 | } 155 | 156 | function displayButtons() { 157 | var loginStatus = $('.container h4'); 158 | if (isAuthenticated()) { 159 | loginBtn.css('display', 'none'); 160 | logoutBtn.css('display', 'inline-block'); 161 | profileViewBtn.css('display', 'inline-block'); 162 | pingViewBtn.css('display', 'inline-block'); 163 | callPrivateMessage.css('display', 'none'); 164 | loginStatus.text( 165 | 'You are logged in! You can now send authenticated requests to your server.' 166 | ); 167 | } else { 168 | homeView.css('display', 'inline-block'); 169 | loginBtn.css('display', 'inline-block'); 170 | logoutBtn.css('display', 'none'); 171 | profileViewBtn.css('display', 'none'); 172 | profileView.css('display', 'none'); 173 | pingView.css('display', 'none'); 174 | pingViewBtn.css('display', 'none'); 175 | adminView.css('display', 'none'); 176 | callPrivateMessage.css('display', 'block'); 177 | loginStatus.text('You are not logged in! Please log in to continue.'); 178 | } 179 | if (!isAuthenticated() || !userHasScopes(['write:messages'])) { 180 | adminViewBtn.css('display', 'none'); 181 | } else { 182 | adminViewBtn.css('display', 'inline-block'); 183 | } 184 | } 185 | 186 | function getProfile() { 187 | if (!userProfile) { 188 | var accessToken = localStorage.getItem('access_token'); 189 | 190 | if (!accessToken) { 191 | console.log('Access token must exist to fetch profile'); 192 | } 193 | 194 | webAuth.client.userInfo(accessToken, function(err, profile) { 195 | if (profile) { 196 | userProfile = profile; 197 | displayProfile(); 198 | } 199 | }); 200 | } else { 201 | displayProfile(); 202 | } 203 | } 204 | 205 | function displayProfile() { 206 | // display the profile 207 | $('#profile-view .nickname').text(userProfile.nickname); 208 | $('#profile-view .full-profile').text(JSON.stringify(userProfile, null, 2)); 209 | $('#profile-view img').attr('src', userProfile.picture); 210 | } 211 | 212 | function handleAuthentication() { 213 | webAuth.parseHash(function(err, authResult) { 214 | if (authResult && authResult.accessToken && authResult.idToken) { 215 | window.location.hash = ''; 216 | setSession(authResult); 217 | loginBtn.css('display', 'none'); 218 | homeView.css('display', 'inline-block'); 219 | } else if (err) { 220 | homeView.css('display', 'inline-block'); 221 | console.log(err); 222 | alert( 223 | 'Error: ' + err.error + '. Check the console for further details.' 224 | ); 225 | } 226 | displayButtons(); 227 | }); 228 | } 229 | 230 | function userHasScopes(scopes) { 231 | var savedScopes = JSON.parse(localStorage.getItem('scopes')); 232 | if (!savedScopes) return false; 233 | var grantedScopes = savedScopes.split(' '); 234 | for (var i = 0; i < scopes.length; i++) { 235 | if (grantedScopes.indexOf(scopes[i]) < 0) { 236 | return false; 237 | } 238 | } 239 | return true; 240 | } 241 | 242 | handleAuthentication(); 243 | 244 | function callAPI(endpoint, secured, method, cb) { 245 | var url = apiUrl + endpoint; 246 | var accessToken = localStorage.getItem('access_token'); 247 | 248 | var headers; 249 | if (secured && accessToken) { 250 | headers = { Authorization: 'Bearer ' + accessToken }; 251 | } 252 | 253 | $.ajax({ 254 | method: method, 255 | url: url, 256 | headers: headers 257 | }) 258 | .done(function(result) { 259 | cb(null, result.message); 260 | }) 261 | .fail(function(err) { 262 | cb(err); 263 | }); 264 | } 265 | 266 | displayButtons(); 267 | }); 268 | -------------------------------------------------------------------------------- /04-Authorization/assets/loading.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /04-Authorization/auth0-variables.js.example: -------------------------------------------------------------------------------- 1 | var AUTH0_CLIENT_ID = '{CLIENT_ID}'; 2 | var AUTH0_DOMAIN = '{DOMAIN}'; 3 | var AUTH0_AUDIENCE = '{API_IDENTIFIER}'; 4 | var AUTH0_CALLBACK_URL = location.href; 5 | 6 | -------------------------------------------------------------------------------- /04-Authorization/exec.ps1: -------------------------------------------------------------------------------- 1 | docker build -t auth0-jquery-04-authorization . 2 | docker run -p 3000:3000 -p 3001:3001 -it auth0-jquery-04-authorization 3 | -------------------------------------------------------------------------------- /04-Authorization/exec.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | docker build -t auth0-jquery-04-authorization . 3 | docker run -p 3000:3000 -p 3001:3001 -it auth0-jquery-04-authorization 4 | -------------------------------------------------------------------------------- /04-Authorization/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Authorization 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | Loading spinner 16 |
17 | 18 |
19 | 51 | 52 |
53 | 54 |
55 |

56 |
57 | 58 | 59 |
60 |

Profile

61 |
62 | avatar 63 |
64 | 65 |

66 |
67 |

 68 |         
69 |
70 | 71 | 72 |
73 |

Make a Call to the Server

74 | 75 |

76 | Log in to call a private (secured) server endpoint. 77 |

78 | 79 | 82 | 83 | 86 | 87 | 90 | 91 |

92 |
93 | 94 | 95 |
96 |

You are an Admin!

97 |

Only users who have a scope of write:messages in their access_token can see this area.

98 | 99 |
100 | 101 |

Call an Admin endpoint

102 | 103 | 106 | 107 |

108 |
109 |
110 |
111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /04-Authorization/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "authorization", 3 | "version": "0.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "start": "npm-run-all --parallel server client", 8 | "server": "node server.js", 9 | "client": "serve -p 3000" 10 | }, 11 | "author": "Auth0", 12 | "license": "MIT", 13 | "dependencies": { 14 | "auth0-js": "^9.0.0", 15 | "bootstrap": "^3.3.7", 16 | "cors": "^2.8.3", 17 | "dotenv": "^4.0.0", 18 | "express": "^4.15.3", 19 | "express-jwt": "^5.3.0", 20 | "express-jwt-authz": "^1.0.0", 21 | "jquery": "^3.2.1", 22 | "jwks-rsa": "^1.2.0", 23 | "npm-run-all": "^4.0.2", 24 | "serve": "^6.0.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /04-Authorization/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const jwt = require('express-jwt'); 4 | const jwtAuthz = require('express-jwt-authz'); 5 | const jwksRsa = require('jwks-rsa'); 6 | const cors = require('cors'); 7 | require('dotenv').config(); 8 | 9 | if (!process.env.AUTH0_DOMAIN || !process.env.AUTH0_AUDIENCE) { 10 | throw 'Make sure you have AUTH0_DOMAIN, and AUTH0_AUDIENCE in your .env file' 11 | } 12 | 13 | app.use(cors()); 14 | 15 | const checkJwt = jwt({ 16 | // Dynamically provide a signing key based on the kid in the header and the singing keys provided by the JWKS endpoint. 17 | secret: jwksRsa.expressJwtSecret({ 18 | cache: true, 19 | rateLimit: true, 20 | jwksRequestsPerMinute: 5, 21 | jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json` 22 | }), 23 | 24 | // Validate the audience and the issuer. 25 | audience: process.env.AUTH0_AUDIENCE, 26 | issuer: `https://${process.env.AUTH0_DOMAIN}/`, 27 | algorithms: ['RS256'] 28 | }); 29 | 30 | const checkScopes = jwtAuthz([ 'read:messages' ]); 31 | const checkScopesAdmin = jwtAuthz([ 'write:messages' ]); 32 | 33 | app.get('/api/public', function(req, res) { 34 | res.json({ message: "Hello from a public endpoint! You don't need to be authenticated to see this." }); 35 | }); 36 | 37 | app.get('/api/private', checkJwt, function(req, res) { 38 | res.json({ message: "Hello from a private endpoint! You need to be authenticated to see this." }); 39 | }); 40 | 41 | app.get('/api/private-scoped', checkJwt, checkScopes, function(req, res) { 42 | res.json({ message: "Hello from a private endpoint! You need to be authenticated and have a scope of read:messages to see this." }); 43 | }); 44 | 45 | app.post('/api/admin', checkJwt, checkScopesAdmin, function(req, res) { 46 | res.json({ message: "Hello from an admin endpoint! You need to be authenticated and have a scope of write:messages to see this." }); 47 | }); 48 | 49 | app.listen(3001); 50 | console.log('Listening on http://localhost:3001'); 51 | -------------------------------------------------------------------------------- /04-Authorization/style.css: -------------------------------------------------------------------------------- 1 | .content { 2 | display: none; 3 | } 4 | 5 | .btn-margin { 6 | margin-top: 7px 7 | } 8 | 9 | #profile-view, 10 | #ping-view, 11 | #admin-view { 12 | display: none; 13 | } 14 | 15 | .profile-area img { 16 | max-width: 150px; 17 | margin-bottom: 20px; 18 | } 19 | 20 | .panel-body h3 { 21 | margin-top: 0; 22 | } 23 | 24 | #loading { 25 | position: absolute; 26 | display: flex; 27 | justify-content: center; 28 | height: 100vh; 29 | width: 100vw; 30 | top: 0; 31 | bottom: 0; 32 | left: 0; 33 | right: 0; 34 | background-color: #fff; 35 | } -------------------------------------------------------------------------------- /05-Token-Renewal/.dockerignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules 3 | .gitignore 4 | exec.sh 5 | exec.ps1 6 | README.md 7 | -------------------------------------------------------------------------------- /05-Token-Renewal/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules 3 | auth0-variables.js 4 | .env -------------------------------------------------------------------------------- /05-Token-Renewal/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:8.7-alpine 2 | 3 | WORKDIR /home/app 4 | 5 | RUN npm install -g create-react-app 6 | ADD package.json /home/app 7 | RUN npm install 8 | ADD . /home/app 9 | 10 | CMD ["npm", "start"] 11 | 12 | EXPOSE 3000 13 | -------------------------------------------------------------------------------- /05-Token-Renewal/README.md: -------------------------------------------------------------------------------- 1 | # Auth0 jQuery Token Renewal 2 | 3 | This sample demonstrates how to silently renew `access_token`s in a jQuery application with Auth0. 4 | 5 | ## Getting Started 6 | 7 | Create a new API in the [APIs section](https://manage.auth0.com/#/apis) and provide an identifier for it. 8 | 9 | Clone the repo or download it from the jQuery quickstart page in Auth0's documentation. 10 | 11 | ```bash 12 | cd 05-Token-Renewal 13 | npm install 14 | ``` 15 | 16 | ## Set the Client ID, Domain, and API URL 17 | 18 | If you download the sample from the quickstart page, it will come pre-populated with the **client ID** and **domain** for your application. If you clone the repo directly from Github, rename the `auth0-variables.js.example` file to `auth0-variables.js` and provide the **client ID** and **domain 19 | 20 | ## Set Up `Allowed Web Origins` in the dashboard 21 | In order to make `checkSession` work, you need to add the URL where the authorization request originates from, to the Allowed Web Origins list of your Auth0 client in the Dashboard under your client's Settings. 22 | 23 | ## Run the Application 24 | 25 | The `serve` module provided with this sample can be run with the `start` command. 26 | 27 | ```bash 28 | npm start 29 | ``` 30 | 31 | The application will be served at `http://localhost:3000`. 32 | 33 | ## Troubleshooting 34 | 35 | If you see an error on renewal saying `login_required`, that means you may be using the Auth0 dev keys for whichever social login you're testing. You'll need to add your own keys for this to work. 36 | 37 | ## Run the Application With Docker 38 | 39 | In order to run the example with docker you need to have `docker` installed. 40 | 41 | You also need to set the environment variables as explained [previously](#set-the-client-id-domain-and-api-url). 42 | 43 | Execute in command line `sh exec.sh` to run the Docker in Linux, or `.\exec.ps1` to run the Docker in Windows. 44 | 45 | ## What is Auth0? 46 | 47 | Auth0 helps you to: 48 | 49 | * Add authentication with [multiple authentication sources](https://docs.auth0.com/identityproviders), either social like **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce, among others**, or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS or any SAML Identity Provider**. 50 | * Add authentication through more traditional **[username/password databases](https://docs.auth0.com/mysql-connection-tutorial)**. 51 | * Add support for **[linking different user accounts](https://docs.auth0.com/link-accounts)** with the same user. 52 | * Support for generating signed [Json Web Tokens](https://docs.auth0.com/jwt) to call your APIs and **flow the user identity** securely. 53 | * Analytics of how, when and where users are logging in. 54 | * Pull data from other sources and add it to the user profile, through [JavaScript rules](https://docs.auth0.com/rules). 55 | 56 | ## Create a free Auth0 account 57 | 58 | 1. Go to [Auth0](https://auth0.com/signup) and click Sign Up. 59 | 2. Use Google, GitHub or Microsoft Account to login. 60 | 61 | ## Issue Reporting 62 | 63 | If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. 64 | 65 | ## Author 66 | 67 | [Auth0](https://auth0.com) 68 | 69 | ## License 70 | 71 | This project is licensed under the MIT license. See the [LICENSE](LICENSE.txt) file for more info. 72 | -------------------------------------------------------------------------------- /05-Token-Renewal/app.js: -------------------------------------------------------------------------------- 1 | $('document').ready(function() { 2 | var userProfile; 3 | var content = $('.content'); 4 | var loadingSpinner = $('#loading'); 5 | content.css('display', 'block'); 6 | loadingSpinner.css('display', 'none'); 7 | 8 | var tokenRenewalTimeout; 9 | 10 | var webAuth = new auth0.WebAuth({ 11 | domain: AUTH0_DOMAIN, 12 | clientID: AUTH0_CLIENT_ID, 13 | redirectUri: AUTH0_CALLBACK_URL, 14 | responseType: 'token id_token', 15 | scope: 'openid profile', 16 | leeway: 60 17 | }); 18 | 19 | var loginStatus = $('.container h4'); 20 | var loginView = $('#login-view'); 21 | var homeView = $('#home-view'); 22 | var profileView = $('#profile-view'); 23 | 24 | // buttons and event listeners 25 | var loginBtn = $('#qsLoginBtn'); 26 | var logoutBtn = $('#qsLogoutBtn'); 27 | 28 | var homeViewBtn = $('#btn-home-view'); 29 | var profileViewBtn = $('#btn-profile-view'); 30 | 31 | var checkSessionBtn = $('#btn-renew-token'); 32 | var accessTokenMessage = $('#access-token-message'); 33 | var tokenExpiryDate = $('#token-expiry-date'); 34 | 35 | homeViewBtn.click(function() { 36 | homeView.css('display', 'inline-block'); 37 | profileView.css('display', 'none'); 38 | }); 39 | 40 | profileViewBtn.click(function() { 41 | homeView.css('display', 'none'); 42 | profileView.css('display', 'inline-block'); 43 | getProfile(); 44 | }); 45 | 46 | loginBtn.click(function(e) { 47 | e.preventDefault(); 48 | webAuth.authorize(); 49 | }); 50 | 51 | logoutBtn.click(logout); 52 | 53 | checkSessionBtn.click(function() { 54 | renewToken(); 55 | }); 56 | 57 | function setSession(authResult) { 58 | // Set the time that the access token will expire at 59 | var expiresAt = JSON.stringify( 60 | authResult.expiresIn * 1000 + new Date().getTime() 61 | ); 62 | localStorage.setItem('access_token', authResult.accessToken); 63 | localStorage.setItem('id_token', authResult.idToken); 64 | localStorage.setItem('expires_at', expiresAt); 65 | scheduleRenewal(); 66 | } 67 | 68 | function logout() { 69 | // Remove tokens and expiry time from localStorage 70 | localStorage.removeItem('access_token'); 71 | localStorage.removeItem('id_token'); 72 | localStorage.removeItem('expires_at'); 73 | clearTimeout(tokenRenewalTimeout); 74 | displayButtons(); 75 | } 76 | 77 | function isAuthenticated() { 78 | // Check whether the current time is past the 79 | // access token's expiry time 80 | var expiresAt = JSON.parse(localStorage.getItem('expires_at')); 81 | return new Date().getTime() < expiresAt; 82 | } 83 | 84 | function displayButtons() { 85 | var loginStatus = $('.container h4'); 86 | if (isAuthenticated()) { 87 | var expiresAt = JSON.parse(localStorage.getItem('expires_at')); 88 | loginBtn.css('display', 'none'); 89 | logoutBtn.css('display', 'inline-block'); 90 | profileViewBtn.css('display', 'inline-block'); 91 | checkSessionBtn.css('display', 'inline-block'); 92 | accessTokenMessage.css('display', 'inline-block'); 93 | loginStatus.text( 94 | 'You are logged in! You can now view your profile area.' 95 | ); 96 | tokenExpiryDate.text(JSON.stringify(new Date(expiresAt))); 97 | } else { 98 | homeView.css('display', 'inline-block'); 99 | loginBtn.css('display', 'inline-block'); 100 | logoutBtn.css('display', 'none'); 101 | profileViewBtn.css('display', 'none'); 102 | profileView.css('display', 'none'); 103 | checkSessionBtn.css('display', 'none'); 104 | accessTokenMessage.css('display', 'none'); 105 | loginStatus.text('You are not logged in! Please log in to continue.'); 106 | } 107 | } 108 | 109 | function getProfile() { 110 | if (!userProfile) { 111 | var accessToken = localStorage.getItem('access_token'); 112 | 113 | if (!accessToken) { 114 | console.log('Access token must exist to fetch profile'); 115 | } 116 | 117 | webAuth.client.userInfo(accessToken, function(err, profile) { 118 | if (profile) { 119 | userProfile = profile; 120 | displayProfile(); 121 | } 122 | }); 123 | } else { 124 | displayProfile(); 125 | } 126 | } 127 | 128 | function displayProfile() { 129 | // display the profile 130 | $('#profile-view .nickname').text(userProfile.nickname); 131 | $('#profile-view .full-profile').text(JSON.stringify(userProfile, null, 2)); 132 | $('#profile-view img').attr('src', userProfile.picture); 133 | } 134 | 135 | function handleAuthentication() { 136 | webAuth.parseHash(function(err, authResult) { 137 | if (authResult && authResult.accessToken && authResult.idToken) { 138 | window.location.hash = ''; 139 | setSession(authResult); 140 | loginBtn.css('display', 'none'); 141 | homeView.css('display', 'inline-block'); 142 | } else if (err) { 143 | homeView.css('display', 'inline-block'); 144 | console.log(err); 145 | alert( 146 | 'Error: ' + err.error + '. Check the console for further details.' 147 | ); 148 | } 149 | displayButtons(); 150 | }); 151 | } 152 | 153 | function renewToken() { 154 | webAuth.checkSession({}, 155 | function(err, result) { 156 | if (err) { 157 | alert( 158 | 'Could not get a new token. ' + 159 | err.description 160 | ); 161 | } else { 162 | setSession(result); 163 | alert('Successfully renewed auth!'); 164 | } 165 | } 166 | ); 167 | } 168 | 169 | function scheduleRenewal() { 170 | var expiresAt = JSON.parse(localStorage.getItem('expires_at')); 171 | var delay = expiresAt - Date.now(); 172 | if (delay > 0) { 173 | tokenRenewalTimeout = setTimeout(function() { 174 | renewToken(); 175 | }, delay); 176 | } 177 | } 178 | 179 | handleAuthentication(); 180 | scheduleRenewal(); 181 | }); 182 | -------------------------------------------------------------------------------- /05-Token-Renewal/assets/loading.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /05-Token-Renewal/auth0-variables.js.example: -------------------------------------------------------------------------------- 1 | var AUTH0_CLIENT_ID='{CLIENT_ID}'; 2 | var AUTH0_DOMAIN='{DOMAIN}'; 3 | var AUTH0_CALLBACK_URL=location.href; -------------------------------------------------------------------------------- /05-Token-Renewal/exec.ps1: -------------------------------------------------------------------------------- 1 | docker build -t auth0-jquery-05-token-renewal . 2 | docker run -p 3000:3000 -it auth0-jquery-05-token-renewal 3 | -------------------------------------------------------------------------------- /05-Token-Renewal/exec.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | docker build -t auth0-jquery-05-token-renewal . 3 | docker run -p 3000:3000 -it auth0-jquery-05-token-renewal 4 | -------------------------------------------------------------------------------- /05-Token-Renewal/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | User Profile 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | Loading spinner 16 |
17 | 18 |
19 | 47 | 48 |
49 | 50 |
51 |

52 |
53 |

About Your Access Token

54 |

Your access_token has an expiry date of:

55 |

The token has been scheduled for renewal, but you can also renew it manually from the 56 | navbar if you don't want to wait. This manual renewal button is really just for demonstration and you probably 57 | won't want such a control in your actual application.

58 |
59 |
60 | 61 | 62 |
63 |

Profile

64 |
65 | avatar 66 |
67 | 68 |

69 |
70 |

71 |           
72 |
73 |
74 |
75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /05-Token-Renewal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "token-renewal", 3 | "version": "0.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "start": "serve -p 3000" 8 | }, 9 | "author": "Auth0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "auth0-js": "^9.0.0", 13 | "bootstrap": "^3.3.7", 14 | "jquery": "^3.2.1", 15 | "serve": "^6.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /05-Token-Renewal/style.css: -------------------------------------------------------------------------------- 1 | .content { 2 | display: none; 3 | } 4 | 5 | .btn-margin { 6 | margin-top: 7px 7 | } 8 | 9 | #profile-view { 10 | display: none; 11 | } 12 | 13 | .profile-area img { 14 | max-width: 150px; 15 | margin-bottom: 20px; 16 | } 17 | 18 | .panel-body h3 { 19 | margin-top: 0; 20 | } 21 | 22 | #loading { 23 | position: absolute; 24 | display: flex; 25 | justify-content: center; 26 | height: 100vh; 27 | width: 100vw; 28 | top: 0; 29 | bottom: 0; 30 | left: 0; 31 | right: 0; 32 | background-color: #fff; 33 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Auth0 Samples 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Auth0 jQuery Samples [DEPRECATED] 2 | 3 | ## Deprecation notice 4 | 5 | This repository has been deprecated and is no longer maintained. 6 | --------------------------------------------------------------------------------