├── public_html ├── auth0_logo_final_blue_RGB.png ├── README.md ├── index.html ├── app.css └── app.js ├── .gitignore ├── LICENSE └── README.md /public_html/auth0_logo_final_blue_RGB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyric/auth0-sso-sample/master/public_html/auth0_logo_final_blue_RGB.png -------------------------------------------------------------------------------- /public_html/README.md: -------------------------------------------------------------------------------- 1 | # app1.com 2 | 3 | This is the starting point for the SSO example. Remember to start all 3 apps to try everything out and to [configure `/etc/hosts` correctly](https://github.com/auth0/auth0-sso-sample#running) 4 | 5 | ## Running the example 6 | 7 | In order to run the example you need to just start a server. What we suggest is doing the following: 8 | 9 | 1. Install node 10 | 2. run `npm install -g serve` 11 | 3. run `serve` in the directory of this project. 12 | 13 | Go to `http://app1.com:3000` and you'll see the app running :). 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Commenting this out is preferred by some people, see 24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 25 | node_modules 26 | 27 | # Users Environment Variables 28 | .lock-wscript 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Auth0 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SSO sample 2 | 3 | This is the example for the [SSO article](https://docs.auth0.com/sso/single-sign-on). In here, you'll see how to implement SSO between Single Page Apps and Regular Web Apps using Auth0. 4 | 5 | ## Structure 6 | 7 | In this example, we have 3 applications: 8 | 9 | * app1.com (single page app) 10 | * app2.com (single page app) 11 | * app3.com (regular web app) 12 | 13 | Each application has its own folder in this repository with its own instructions on how to run it. 14 | 15 | ## Running 16 | 17 | In order to be able to test SSO correctly, each application must have its own domain. For that, you can edit your `/etc/hosts` and make app1.com, app2.com and app3.com all point to `127.0.0.1`. 18 | 19 | For that, open `/etc/hosts` and edits as follows: 20 | 21 | ```` 22 | ## 23 | # Host Database 24 | # 25 | # localhost is used to configure the loopback interface 26 | # when the system is booting. Do not change this entry. 27 | ## 28 | 127.0.0.1 localhost 29 | 255.255.255.255 broadcasthost 30 | ::1 localhost 31 | # ... 32 | 127.0.0.1 app1.com 33 | 127.0.0.1 app2.com 34 | 127.0.0.1 app3.com 35 | ```` 36 | 37 | Once that's done, just run all 3 applications (See specific instructions on each README) and go to [`app1.com:3000`](http://app1.com:3000) to start using the applications :). 38 | 39 | ## Learning 40 | 41 | To learn more about how this 3 apps work with SSO, please read the [SSO article](https://docs.auth0.com/sso/single-sign-on) from our docs. 42 | -------------------------------------------------------------------------------- /public_html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |
23 | 29 | 37 |
38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /public_html/app.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: "proxima-nova", sans-serif; 3 | text-align: center; 4 | font-size: 300%; 5 | font-weight: 100; 6 | } 7 | input[type=checkbox], 8 | input[type=radio] { 9 | position: absolute; 10 | opacity: 0; 11 | } 12 | input[type=checkbox] + label, 13 | input[type=radio] + label { 14 | display: inline-block; 15 | } 16 | input[type=checkbox] + label:before, 17 | input[type=radio] + label:before { 18 | content: ""; 19 | display: inline-block; 20 | vertical-align: -0.2em; 21 | width: 1em; 22 | height: 1em; 23 | border: 0.15em solid #0074d9; 24 | border-radius: 0.2em; 25 | margin-right: 0.3em; 26 | background-color: white; 27 | } 28 | input[type=radio] + label:before { 29 | border-radius: 50%; 30 | } 31 | input[type=radio]:checked + label:before, 32 | input[type=checkbox]:checked + label:before { 33 | background-color: #0074d9; 34 | box-shadow: inset 0 0 0 0.15em white; 35 | } 36 | input[type=radio]:focus + label:before, 37 | input[type=checkbox]:focus + label:before { 38 | outline: 0; 39 | } 40 | .btn { 41 | font-size: 140%; 42 | text-transform: uppercase; 43 | letter-spacing: 1px; 44 | border: 0; 45 | background-color: #16214D; 46 | color: white; 47 | } 48 | .btn:hover { 49 | background-color: #44C7F4; 50 | } 51 | .btn:focus { 52 | outline: none !important; 53 | } 54 | .btn.btn-lg { 55 | padding: 20px 30px; 56 | } 57 | .btn:disabled { 58 | background-color: #333; 59 | color: #666; 60 | } 61 | h1, 62 | h2, 63 | h3 { 64 | font-weight: 100; 65 | } 66 | #logo img { 67 | width: 300px; 68 | margin-bottom: 60px; 69 | } 70 | .home-description { 71 | font-weight: 100; 72 | margin: 100px 0; 73 | } 74 | h2 { 75 | margin-top: 30px; 76 | margin-bottom: 40px; 77 | font-size: 200%; 78 | } 79 | label { 80 | font-size: 100%; 81 | font-weight: 300; 82 | } 83 | .btn-next { 84 | margin-top: 30px; 85 | } 86 | .answer { 87 | width: 70%; 88 | margin: auto; 89 | text-align: left; 90 | padding-left: 10%; 91 | margin-bottom: 20px; 92 | } 93 | .login-page .login-box { 94 | padding: 100px 0; 95 | } 96 | 97 | .url { 98 | display: none; 99 | } 100 | 101 | .bold { 102 | font-weight: bold; 103 | } 104 | -------------------------------------------------------------------------------- /public_html/app.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | 3 | // hide the page in case there is an SSO session (to avoid flickering) 4 | document.body.style.display = 'none'; 5 | 6 | // instantiate Lock 7 | var lock = new Auth0Lock('BUIJSW9x60sIHBw8Kd9EmCbj8eDIFxDC', 'samples.auth0.com'); 8 | 9 | 10 | 11 | // sso requires redirect mode, hence we need to parse 12 | // the response from Auth0 that comes on location hash 13 | var hash = lock.parseHash(window.location.hash); 14 | if (hash && hash.id_token) { 15 | // the user came back from the login (either SSO or regular login), 16 | // save the token 17 | localStorage.setItem('userToken', hash.id_token); 18 | // redirect to "targetUrl" if any 19 | // This would go to a different route like 20 | // window.location.href = hash.state || '#home'; 21 | // But in this case, we just hide and show things 22 | goToHomepage(hash.state, hash.id_token); 23 | return; 24 | } 25 | 26 | // Get the user token if we've saved it in localStorage before 27 | var idToken = localStorage.getItem('userToken'); 28 | if (idToken) { 29 | // This would go to a different route like 30 | // window.location.href = '#home'; 31 | // But in this case, we just hide and show things 32 | goToHomepage(getQueryParameter('targetUrl'), idToken); 33 | return; 34 | } 35 | 36 | // user is not logged, check whether there is an SSO session or not 37 | lock.$auth0.getSSOData(function(err, data) { 38 | if (!err && data.sso) { 39 | // there is! redirect to Auth0 for SSO 40 | lock.$auth0.signin({ 41 | // If the user wanted to go to some other URL, you can track it with `state` 42 | state: getQueryParameter('targetUrl'), 43 | callbackOnLocationHash: true, 44 | scope: 'openid name picture' 45 | }); 46 | } else { 47 | // regular login 48 | document.body.style.display = 'inline'; 49 | } 50 | }); 51 | 52 | // Showing Login 53 | $('.btn-login').click(function(e) { 54 | e.preventDefault(); 55 | lock.show({ 56 | authParams: { 57 | scope: 'openid name picture' 58 | } 59 | }); 60 | }); 61 | 62 | 63 | // Sending token in header if available 64 | $.ajaxSetup({ 65 | 'beforeSend': function(xhr) { 66 | if (localStorage.getItem('userToken')) { 67 | xhr.setRequestHeader('Authorization', 68 | 'Bearer ' + localStorage.getItem('userToken')); 69 | } 70 | } 71 | }); 72 | 73 | $('.btn-api').click(function(e) { 74 | // Just call your API here. The header will be sent 75 | }); 76 | 77 | function goToHomepage(state, token) { 78 | // Instead of redirect, we just show boxes 79 | document.body.style.display = 'inline'; 80 | $('.login-box').hide(); 81 | $('.logged-in-box').show(); 82 | var profile = jwt_decode(token); 83 | $('.name').text(profile.name); 84 | if (state) { 85 | $('.url').show(); 86 | $('.url span').text(state); 87 | } 88 | } 89 | 90 | function getQueryParameter(name) { 91 | name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); 92 | var regex = new RegExp("[\\?&]" + name + "=([^&]*)"), 93 | results = regex.exec(location.search); 94 | return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); 95 | } 96 | 97 | 98 | }); 99 | --------------------------------------------------------------------------------