├── .github ├── CODEOWNERS └── stale.yml ├── 01-Login ├── settings.gradle ├── .dockerignore ├── src │ ├── main │ │ ├── resources │ │ │ ├── auth0.properties.example │ │ │ ├── public │ │ │ │ └── logo.png │ │ │ ├── application.properties │ │ │ └── templates │ │ │ │ ├── fragments │ │ │ │ ├── footer.html │ │ │ │ ├── header.html │ │ │ │ ├── scripts.html │ │ │ │ └── navbar.html │ │ │ │ ├── layouts │ │ │ │ └── default.html │ │ │ │ ├── profile.html │ │ │ │ └── index.html │ │ └── java │ │ │ └── com │ │ │ └── auth0 │ │ │ └── example │ │ │ ├── App.java │ │ │ ├── mvc │ │ │ ├── ErrorController.java │ │ │ ├── HomeController.java │ │ │ ├── ProfileController.java │ │ │ ├── LoginController.java │ │ │ ├── LogoutController.java │ │ │ └── CallbackController.java │ │ │ ├── security │ │ │ ├── TokenAuthentication.java │ │ │ └── AppConfig.java │ │ │ └── util │ │ │ └── TokenUtils.java │ └── test │ │ └── java │ │ └── com │ │ └── auth0 │ │ └── example │ │ ├── security │ │ └── SecurityIntegrationTest.java │ │ └── util │ │ └── TokenUtilsTest.java ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── exec.ps1 ├── Dockerfile ├── exec.sh ├── build.gradle ├── gradlew.bat ├── README.md └── gradlew ├── README.md ├── LICENSE ├── .gitignore └── .circleci └── config.yml /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @auth0-samples/dx-sdks-approver 2 | -------------------------------------------------------------------------------- /01-Login/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'auth0-spring-security-mvc' 2 | 3 | -------------------------------------------------------------------------------- /01-Login/.dockerignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .gradle/ 3 | .idea/ 4 | build/ 5 | exec.sh 6 | exec.ps1 7 | README.md 8 | -------------------------------------------------------------------------------- /01-Login/src/main/resources/auth0.properties.example: -------------------------------------------------------------------------------- 1 | com.auth0.domain: {DOMAIN} 2 | com.auth0.clientId: {CLIENT_ID} 3 | com.auth0.clientSecret: {CLIENT_SECRET} -------------------------------------------------------------------------------- /01-Login/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auth0-samples/auth0-spring-security-mvc-sample/HEAD/01-Login/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /01-Login/src/main/resources/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auth0-samples/auth0-spring-security-mvc-sample/HEAD/01-Login/src/main/resources/public/logo.png -------------------------------------------------------------------------------- /01-Login/exec.ps1: -------------------------------------------------------------------------------- 1 | docker build -t auth0-samples/auth0-spring-security-mvc-01-login . 2 | docker run -p 3000:3000 -it auth0-samples/auth0-spring-security-mvc-01-login 3 | -------------------------------------------------------------------------------- /01-Login/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gradle:5.4.1-jdk8 2 | 3 | WORKDIR /tmp 4 | ADD . /tmp 5 | 6 | RUN gradle build 7 | 8 | CMD ["gradle", "clean", "bootRun"] 9 | EXPOSE 3000 10 | -------------------------------------------------------------------------------- /01-Login/exec.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | docker build -t auth0-samples/auth0-spring-security-mvc-01-login . 3 | docker run -p 3000:3000 -it auth0-samples/auth0-spring-security-mvc-01-login 4 | -------------------------------------------------------------------------------- /01-Login/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port: 3000 2 | logging.level.com.auth0.example: INFO 3 | logging.level.org.springframework.web: DEBUG 4 | logging.level.org.springframework.security: DEBUG 5 | logging.level.org.springframework.boot: DEBUG 6 | -------------------------------------------------------------------------------- /01-Login/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Auth0 Spring Boot 1 Login Sample [DEPRECATED] 2 | 3 | ## Deprecation Notice 4 | This repository has been deprecated and is no longer maintained. 5 | 6 | See the [Spring Boot 2 Login Samples](https://github.com/auth0-samples/auth0-spring-boot-login-samples) to see how to add authentication to your Spring Boot 2 application. -------------------------------------------------------------------------------- /01-Login/src/main/resources/templates/fragments/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Footer 5 | 6 | 13 | -------------------------------------------------------------------------------- /01-Login/src/main/resources/templates/layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 14 | -------------------------------------------------------------------------------- /01-Login/src/main/java/com/auth0/example/App.java: -------------------------------------------------------------------------------- 1 | package com.auth0.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.annotation.ComponentScan; 7 | import org.springframework.context.annotation.PropertySource; 8 | import org.springframework.context.annotation.PropertySources; 9 | 10 | @SpringBootApplication 11 | @PropertySources({ 12 | @PropertySource("classpath:application.properties"), 13 | @PropertySource("classpath:auth0.properties") 14 | }) 15 | public class App { 16 | 17 | public static void main(final String[] args) throws Exception { 18 | SpringApplication.run(App.class, args); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /01-Login/src/main/resources/templates/fragments/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Spring MVC Security Quickstart 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.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! 🙇‍♂️ -------------------------------------------------------------------------------- /01-Login/src/main/resources/templates/fragments/scripts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Scripts 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | -------------------------------------------------------------------------------- /01-Login/src/main/java/com/auth0/example/mvc/ErrorController.java: -------------------------------------------------------------------------------- 1 | package com.auth0.example.mvc; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 8 | 9 | import java.io.IOException; 10 | 11 | @SuppressWarnings("unused") 12 | @Controller 13 | public class ErrorController implements org.springframework.boot.autoconfigure.web.ErrorController { 14 | 15 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 16 | 17 | private static final String PATH = "/error"; 18 | 19 | @RequestMapping("/error") 20 | protected String error(final RedirectAttributes redirectAttributes) throws IOException { 21 | logger.error("Handling error"); 22 | redirectAttributes.addFlashAttribute("error", true); 23 | return "redirect:/login"; 24 | } 25 | 26 | @Override 27 | public String getErrorPath() { 28 | return PATH; 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /01-Login/src/main/resources/templates/profile.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 |
9 |
10 |
11 |
12 |
13 |
14 | 15 |
16 |
17 |

18 |

19 |

20 |
21 | 22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | 30 | -------------------------------------------------------------------------------- /01-Login/src/main/java/com/auth0/example/mvc/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.auth0.example.mvc; 2 | 3 | import com.auth0.example.security.TokenAuthentication; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.ui.Model; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | 12 | @SuppressWarnings("unused") 13 | @Controller 14 | public class HomeController { 15 | 16 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 17 | 18 | @RequestMapping(value = "/", method = RequestMethod.GET) 19 | protected String home(final Model model, final Authentication authentication) { 20 | logger.info("Home page"); 21 | 22 | if (authentication instanceof TokenAuthentication) { 23 | TokenAuthentication tokenAuthentication = (TokenAuthentication) authentication; 24 | model.addAttribute("profile", tokenAuthentication.getClaims()); 25 | } 26 | 27 | // If not authenticated, still show home page. 28 | // View will render appropriate login/menu based on authentication status 29 | return "index"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /01-Login/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | } 5 | } 6 | 7 | plugins { 8 | id 'org.springframework.boot' version '1.5.21.RELEASE' 9 | } 10 | 11 | // allow bootRepackage to work with implementation 12 | // https://github.com/spring-projects/spring-boot/issues/9143 13 | configurations { 14 | custom { 15 | it.extendsFrom implementation 16 | } 17 | } 18 | 19 | bootRepackage { 20 | customConfiguration = 'custom' 21 | } 22 | 23 | group = 'com.auth0' 24 | version = '0.0.1-SNAPSHOT' 25 | sourceCompatibility = '1.8' 26 | 27 | // override some Spring Boot dependency versions 28 | ext['jackson.version'] = '2.9.9' 29 | ext['logback.version'] = '1.2.3' 30 | ext['thymeleaf.version'] = '3.0.11.RELEASE' 31 | ext['thymeleaf-extras-springsecurity4.version'] = '3.0.4.RELEASE' 32 | 33 | repositories { 34 | mavenCentral() 35 | } 36 | 37 | dependencies { 38 | implementation 'com.auth0:mvc-auth-commons:1.+' 39 | 40 | implementation 'org.springframework.boot:spring-boot-starter-web' 41 | implementation 'org.springframework.boot:spring-boot-starter-security' 42 | implementation 'org.thymeleaf:thymeleaf-spring4' 43 | implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity4' 44 | implementation 'com.github.zhanhb:thymeleaf-layout-dialect:2.4.1' 45 | 46 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 47 | testImplementation 'org.springframework.security:spring-security-test' 48 | testImplementation 'org.hamcrest:java-hamcrest:2.0.0.0' 49 | } 50 | -------------------------------------------------------------------------------- /01-Login/src/main/java/com/auth0/example/mvc/ProfileController.java: -------------------------------------------------------------------------------- 1 | package com.auth0.example.mvc; 2 | 3 | import com.auth0.example.security.TokenAuthentication; 4 | import com.auth0.example.util.TokenUtils; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.security.core.Authentication; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.ui.Model; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestMethod; 12 | 13 | @SuppressWarnings("unused") 14 | @Controller 15 | public class ProfileController { 16 | 17 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 18 | 19 | @RequestMapping(value = "/profile", method = RequestMethod.GET) 20 | protected String profile(final Model model, final Authentication authentication) { 21 | 22 | // Since we've configured Spring Security to only allow authenticated requests to 23 | // reach this endpoint, and we control the Authentication implementation, we can safely cast. 24 | TokenAuthentication tokenAuthentication = (TokenAuthentication) authentication; 25 | if (tokenAuthentication == null) { 26 | return "redirect:/login"; 27 | } 28 | 29 | String profileJson = TokenUtils.claimsAsJson(tokenAuthentication.getClaims()); 30 | 31 | model.addAttribute("profile", tokenAuthentication.getClaims()); 32 | model.addAttribute("profileJson", profileJson); 33 | return "profile"; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /01-Login/src/main/java/com/auth0/example/mvc/LoginController.java: -------------------------------------------------------------------------------- 1 | package com.auth0.example.mvc; 2 | 3 | import com.auth0.AuthenticationController; 4 | import com.auth0.example.security.AppConfig; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | 15 | @SuppressWarnings("unused") 16 | @Controller 17 | public class LoginController { 18 | 19 | @Autowired 20 | private AuthenticationController controller; 21 | 22 | @Autowired 23 | private AppConfig appConfig; 24 | 25 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 26 | 27 | @RequestMapping(value = "/login", method = RequestMethod.GET) 28 | protected String login(HttpServletRequest request, HttpServletResponse response) { 29 | logger.debug("Performing login"); 30 | String redirectUri = request.getScheme() + "://" + request.getServerName(); 31 | if ((request.getScheme().equals("http") && request.getServerPort() != 80) || 32 | (request.getScheme().equals("https") && request.getServerPort() != 443)) { 33 | redirectUri += ":" + request.getServerPort(); 34 | } 35 | redirectUri += "/callback"; 36 | String authorizeUrl = controller.buildAuthorizeUrl(request, response, redirectUri) 37 | .withScope("openid profile email") 38 | .build(); 39 | return "redirect:" + authorizeUrl; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/osx,gradle,intellij,java-web 3 | 4 | ### Intellij ### 5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 6 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 7 | 8 | .idea/ 9 | *.iws 10 | *.iml 11 | *.ipr 12 | 13 | ### STS ### 14 | .apt_generated 15 | .classpath 16 | .factorypath 17 | .project 18 | .settings 19 | .springBeans 20 | .sts4-cache 21 | 22 | bin/ 23 | out/ 24 | build/ 25 | 26 | # CMake 27 | cmake-build-debug/ 28 | 29 | # mpeltonen/sbt-idea plugin 30 | .idea_modules/ 31 | 32 | # JIRA plugin 33 | atlassian-ide-plugin.xml 34 | 35 | # Crashlytics plugin (for Android Studio and IntelliJ) 36 | com_crashlytics_export_strings.xml 37 | crashlytics.properties 38 | crashlytics-build.properties 39 | fabric.properties 40 | 41 | ### Java-Web ### 42 | ## ignoring target file 43 | target/ 44 | 45 | ### OSX ### 46 | *.DS_Store 47 | .AppleDouble 48 | .LSOverride 49 | 50 | # Icon must end with two \r 51 | Icon 52 | 53 | # Thumbnails 54 | ._* 55 | 56 | # Files that might appear in the root of a volume 57 | .DocumentRevisions-V100 58 | .fseventsd 59 | .Spotlight-V100 60 | .TemporaryItems 61 | .Trashes 62 | .VolumeIcon.icns 63 | .com.apple.timemachine.donotpresent 64 | 65 | # Directories potentially created on remote AFP share 66 | .AppleDB 67 | .AppleDesktop 68 | Network Trash Folder 69 | Temporary Items 70 | .apdisk 71 | 72 | ### Gradle ### 73 | .gradle 74 | /build/ 75 | 76 | # Ignore Gradle GUI config 77 | gradle-app.setting 78 | 79 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 80 | !gradle-wrapper.jar 81 | 82 | # Cache of project 83 | .gradletasknamecache 84 | 85 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 86 | # gradle/wrapper/gradle-wrapper.properties 87 | 88 | # End of https://www.gitignore.io/api/osx,gradle,intellij,java-web 89 | 90 | # Don't version Auth0 properties file 91 | auth0.properties -------------------------------------------------------------------------------- /01-Login/src/main/java/com/auth0/example/mvc/LogoutController.java: -------------------------------------------------------------------------------- 1 | package com.auth0.example.mvc; 2 | 3 | import com.auth0.example.security.AppConfig; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.security.core.Authentication; 8 | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; 9 | import org.springframework.stereotype.Controller; 10 | 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | 15 | @SuppressWarnings("unused") 16 | @Controller 17 | public class LogoutController implements LogoutSuccessHandler { 18 | 19 | @Autowired 20 | private AppConfig appConfig; 21 | 22 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 23 | 24 | @Override 25 | public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse res, Authentication authentication) { 26 | logger.debug("Performing logout"); 27 | invalidateSession(req); 28 | String returnTo = req.getScheme() + "://" + req.getServerName(); 29 | if ((req.getScheme().equals("http") && req.getServerPort() != 80) || (req.getScheme().equals("https") && req.getServerPort() != 443)) { 30 | returnTo += ":" + req.getServerPort(); 31 | } 32 | returnTo += "/"; 33 | String logoutUrl = String.format( 34 | "https://%s/v2/logout?client_id=%s&returnTo=%s", 35 | appConfig.getDomain(), 36 | appConfig.getClientId(), 37 | returnTo); 38 | try { 39 | res.sendRedirect(logoutUrl); 40 | } catch(IOException e){ 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | private void invalidateSession(HttpServletRequest request) { 46 | if (request.getSession() != null) { 47 | request.getSession().invalidate(); 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /01-Login/src/main/java/com/auth0/example/security/TokenAuthentication.java: -------------------------------------------------------------------------------- 1 | package com.auth0.example.security; 2 | 3 | import com.auth0.jwt.interfaces.Claim; 4 | import com.auth0.jwt.interfaces.DecodedJWT; 5 | import org.springframework.security.authentication.AbstractAuthenticationToken; 6 | import org.springframework.security.core.GrantedAuthority; 7 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 8 | 9 | import java.util.*; 10 | 11 | public class TokenAuthentication extends AbstractAuthenticationToken { 12 | 13 | private final DecodedJWT jwt; 14 | private boolean invalidated; 15 | 16 | public TokenAuthentication(DecodedJWT jwt) { 17 | // No authorities by default for this login example. You can use the DecodedJWT to create authorities from 18 | // claims as needed for your particular use case. 19 | super(null); 20 | this.jwt = jwt; 21 | } 22 | 23 | private boolean hasExpired() { 24 | return jwt.getExpiresAt().before(new Date()); 25 | } 26 | 27 | @Override 28 | public String getCredentials() { 29 | return jwt.getToken(); 30 | } 31 | 32 | @Override 33 | public Object getPrincipal() { 34 | return jwt.getSubject(); 35 | } 36 | 37 | @Override 38 | public void setAuthenticated(boolean authenticated) { 39 | if (authenticated) { 40 | throw new IllegalArgumentException("Create a new Authentication object to authenticate"); 41 | } 42 | invalidated = true; 43 | } 44 | 45 | @Override 46 | public boolean isAuthenticated() { 47 | return !invalidated && !hasExpired(); 48 | } 49 | 50 | /** 51 | * Gets the claims for this JWT token. 52 | *
53 | * For an ID token, claims represent user profile information such as the user's name, profile, picture, etc. 54 | *
55 | * @see ID Token Documentation 56 | * @return a Map containing the claims of the token. 57 | */ 58 | public Map getClaims() { 59 | return jwt.getClaims(); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /01-Login/src/main/java/com/auth0/example/util/TokenUtils.java: -------------------------------------------------------------------------------- 1 | package com.auth0.example.util; 2 | 3 | import com.auth0.jwt.interfaces.Claim; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.JsonNode; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.fasterxml.jackson.databind.node.ObjectNode; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.util.Map; 12 | 13 | /** 14 | * Utility class for working with tokens 15 | */ 16 | public class TokenUtils { 17 | 18 | private static final Logger logger = LoggerFactory.getLogger(TokenUtils.class); 19 | 20 | /** 21 | * Get the JWT claims as a JSON string. 22 | * 23 | * @param claims the JWT ID token claims 24 | * @return the claims as JSON 25 | */ 26 | public static String claimsAsJson(Map claims) { 27 | ObjectMapper objectMapper = new ObjectMapper(); 28 | ObjectNode node = objectMapper.createObjectNode(); 29 | 30 | 31 | claims.forEach((key, value) -> { 32 | if (value.asMap() != null) { 33 | node.putPOJO(key, value.asMap()); 34 | } else if (value.asList(String.class) != null) { 35 | JsonNode jsonNode = objectMapper.valueToTree(value.asList(String.class)); 36 | node.set(key, jsonNode); 37 | } else if (value.asBoolean() != null) { 38 | node.put(key, value.asBoolean()); 39 | } else if (value.asInt() != null) { 40 | node.put(key, value.asInt()); 41 | } else if (value.as(String.class) != null) { 42 | node.put(key, value.as(String.class)); 43 | } else if (value.isNull()) { 44 | node.putNull(key); 45 | } 46 | }); 47 | 48 | String json = ""; 49 | try { 50 | json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(node); 51 | } catch (JsonProcessingException jpe) { 52 | logger.error("Error processing json from profile", jpe); 53 | } 54 | 55 | return json; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /01-Login/src/test/java/com/auth0/example/security/SecurityIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.auth0.example.security; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | import org.springframework.test.web.servlet.MockMvc; 11 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 12 | import org.springframework.web.context.WebApplicationContext; 13 | 14 | import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; 15 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 16 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 17 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 18 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 19 | 20 | @RunWith(SpringRunner.class) 21 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 22 | public class SecurityIntegrationTest { 23 | 24 | @Autowired 25 | private WebApplicationContext context; 26 | 27 | private MockMvc mvc; 28 | 29 | @Before 30 | public void setup() { 31 | mvc = MockMvcBuilders 32 | .webAppContextSetup(context) 33 | .apply(springSecurity()) 34 | .build(); 35 | } 36 | 37 | @Test 38 | public void profileRouteForbiddenWhenNotAuthenticated() throws Exception { 39 | mvc.perform(get("/profile")) 40 | .andExpect(status().isForbidden()) 41 | .andDo(print()) 42 | .andReturn(); 43 | } 44 | 45 | @Test 46 | public void homePageAlwaysAvailable() throws Exception { 47 | mvc.perform(get("/") 48 | .accept(MediaType.TEXT_HTML)) 49 | .andExpect(status().isOk()) 50 | .andExpect(view().name("index")) 51 | .andDo(print()) 52 | .andReturn(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Common logic 2 | defaults: &defaults 3 | steps: 4 | - attach_workspace: 5 | at: ~/ 6 | - run: 7 | name: Replace Auth0 test credentials 8 | command: | 9 | mv $AUTH0_CFG.example $AUTH0_CFG 10 | sed -i 's/{CLIENT_ID}/'$AUTH0_TEST_CLIENT_ID'/g' $AUTH0_CFG 11 | sed -i 's/{DOMAIN}/'$AUTH0_TEST_DOMAIN'/g' $AUTH0_CFG 12 | sed -i 's/{CLIENT_SECRET}/'$AUTH0_TEST_CLIENT_SECRET'/g' $AUTH0_CFG 13 | - run: 14 | name: Build pull request 15 | command: | 16 | docker build -t $CIRCLE_JOB ./$SAMPLE_PATH 17 | docker run -d -it -p 3000:3000 --name $CIRCLE_SHA1 $CIRCLE_JOB 18 | background: true 19 | - run: 20 | name: Wait for app to be available 21 | command: | 22 | sleep 80 23 | docker run --network host --rm appropriate/curl --retry 8 --retry-connrefused -v localhost:3000 24 | - run: 25 | name: Run tests 26 | command: | 27 | docker create --network host --name tester codeception/codeceptjs codeceptjs run-multiple --all --steps --verbose 28 | docker cp $(pwd)/lock_login_spa_test.js tester:/tests/lock_login_test.js 29 | docker cp $(pwd)/codecept.conf.js tester:/tests/codecept.conf.js 30 | docker start -i tester 31 | working_directory: scripts 32 | - run: 33 | name: Copy app container logs 34 | command: | 35 | mkdir -p /tmp/out 36 | docker logs $CIRCLE_SHA1 > /tmp/out/app_logs.log 37 | docker cp tester:/tests/out /tmp/ 38 | when: on_fail 39 | - store_artifacts: 40 | path: /tmp/out 41 | 42 | # Jobs and Workflows 43 | version: 2 44 | jobs: 45 | checkout: 46 | machine: true 47 | steps: 48 | - checkout 49 | - run: git clone https://github.com/auth0-samples/spa-quickstarts-tests scripts 50 | - persist_to_workspace: 51 | root: ~/ 52 | paths: 53 | - project 54 | - scripts 55 | 01-login: 56 | machine: true 57 | environment: 58 | - AUTH0_CFG: 01-Login/src/main/resources/auth0.properties 59 | - SAMPLE_PATH: 01-Login 60 | <<: *defaults 61 | 62 | workflows: 63 | version: 2 64 | quickstarts_login: 65 | jobs: 66 | - checkout: 67 | context: Quickstart Web App Test 68 | - 01-login: 69 | context: Quickstart Web App Test 70 | requires: 71 | - checkout 72 | -------------------------------------------------------------------------------- /01-Login/src/main/java/com/auth0/example/mvc/CallbackController.java: -------------------------------------------------------------------------------- 1 | package com.auth0.example.mvc; 2 | 3 | import com.auth0.AuthenticationController; 4 | import com.auth0.IdentityVerificationException; 5 | import com.auth0.Tokens; 6 | import com.auth0.example.security.TokenAuthentication; 7 | import com.auth0.jwt.JWT; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.MediaType; 10 | import org.springframework.security.core.AuthenticationException; 11 | import org.springframework.security.core.context.SecurityContextHolder; 12 | import org.springframework.stereotype.Controller; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RequestMethod; 15 | 16 | import javax.servlet.ServletException; 17 | import javax.servlet.http.HttpServletRequest; 18 | import javax.servlet.http.HttpServletResponse; 19 | import java.io.IOException; 20 | 21 | @SuppressWarnings("unused") 22 | @Controller 23 | public class CallbackController { 24 | 25 | @Autowired 26 | private AuthenticationController controller; 27 | private final String redirectOnFail; 28 | private final String redirectOnSuccess; 29 | 30 | public CallbackController() { 31 | this.redirectOnFail = "/login"; 32 | this.redirectOnSuccess = "/"; 33 | } 34 | 35 | @RequestMapping(value = "/callback", method = RequestMethod.GET) 36 | protected void getCallback(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException { 37 | handle(req, res); 38 | } 39 | 40 | @RequestMapping(value = "/callback", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) 41 | protected void postCallback(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException { 42 | handle(req, res); 43 | } 44 | 45 | private void handle(HttpServletRequest request, HttpServletResponse response) throws IOException { 46 | try { 47 | Tokens tokens = controller.handle(request, response); 48 | TokenAuthentication tokenAuth = new TokenAuthentication(JWT.decode(tokens.getIdToken())); 49 | SecurityContextHolder.getContext().setAuthentication(tokenAuth); 50 | response.sendRedirect(redirectOnSuccess); 51 | } catch (AuthenticationException | IdentityVerificationException e) { 52 | e.printStackTrace(); 53 | SecurityContextHolder.clearContext(); 54 | response.sendRedirect(redirectOnFail); 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /01-Login/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS="-Xmx64m" 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /01-Login/src/test/java/com/auth0/example/util/TokenUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.auth0.example.util; 2 | 3 | import com.auth0.jwt.JWT; 4 | import com.auth0.jwt.interfaces.DecodedJWT; 5 | import com.fasterxml.jackson.databind.JsonNode; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | 10 | import static org.hamcrest.MatcherAssert.assertThat; 11 | import static org.hamcrest.Matchers.is; 12 | 13 | public class TokenUtilsTest { 14 | 15 | private final DecodedJWT jwt = JWT.decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEyMzQ1Njc4OTAsImlhdCI6MTIzNDU2Nzg5MCwibmJmIjoxMjM0NTY3ODkwLCJqdGkiOiJodHRwczovL2p3dC5pby8iLCJhdWQiOiJodHRwczovL2RvbWFpbi5hdXRoMC5jb20iLCJzdWIiOiJsb2dpbiIsImlzcyI6ImF1dGgwIiwiZW1haWwiOiJqb2huLmRvZUBleGFtcGxlLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZXh0cmFDbGFpbSI6IkpvaG4gRG9lIiwiZXh0cmFDbGFpbU51bGwiOm51bGwsImV4dHJhQ2xhaW1BcnJheSI6WyJibHVlIiwiZ3JlZW4iLCJyZWQiXSwiZXh0cmFDbGFpbU9iamVjdCI6eyJmYXZvcml0ZUNvbG9yIjoiYmx1ZSJ9LCJleHRyYUNsYWltTmVzdGVkIjp7ImZvbyI6WzEsMiwzXSwiYmFyIjp7InByb3AiOiJ2YWwifX19.eL18X9B9_mzqAdiLYSDchz_Pa89hcVWiwUj6-ZOrPYI");; 16 | private String json; 17 | private JsonNode jsonNode; 18 | 19 | @Before 20 | public void setup() throws Exception{ 21 | json = TokenUtils.claimsAsJson(jwt.getClaims()); 22 | ObjectMapper objectMapper = new ObjectMapper(); 23 | jsonNode = objectMapper.readTree(json); 24 | } 25 | 26 | @Test 27 | public void claimsArray() { 28 | JsonNode extraClaimArray = jsonNode.get("extraClaimArray"); 29 | 30 | assertThat(extraClaimArray.size(), is(3)); 31 | assertThat(extraClaimArray.isArray(), is(true)); 32 | } 33 | 34 | @Test 35 | public void claimsObject() { 36 | JsonNode extraClaimObject = jsonNode.get("extraClaimObject"); 37 | 38 | assertThat(extraClaimObject.isObject(), is(true)); 39 | assertThat(extraClaimObject.get("favoriteColor").asText(), is("blue")); 40 | } 41 | 42 | @Test 43 | public void claimsNull() { 44 | JsonNode extraClaimNull = jsonNode.get("extraClaimNull"); 45 | 46 | assertThat(extraClaimNull.isNull(), is(true)); 47 | } 48 | 49 | @Test 50 | public void claimsNested() { 51 | JsonNode extraClaimNested = jsonNode.get("extraClaimNested"); 52 | 53 | JsonNode arrayNode = extraClaimNested.get("foo"); 54 | assertThat(arrayNode.size(), is(3)); 55 | assertThat(arrayNode.isArray(), is(true)); 56 | 57 | JsonNode objectNode = extraClaimNested.get("bar"); 58 | assertThat(objectNode.isObject(), is(true)); 59 | assertThat(objectNode.get("prop").asText(), is("val")); 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /01-Login/src/main/java/com/auth0/example/security/AppConfig.java: -------------------------------------------------------------------------------- 1 | package com.auth0.example.security; 2 | 3 | import com.auth0.AuthenticationController; 4 | import com.auth0.example.mvc.LogoutController; 5 | import com.auth0.jwk.JwkProvider; 6 | import com.auth0.jwk.JwkProviderBuilder; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 11 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 12 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 13 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 14 | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; 15 | 16 | import java.io.UnsupportedEncodingException; 17 | 18 | @SuppressWarnings("unused") 19 | @Configuration 20 | @EnableWebSecurity 21 | @EnableGlobalMethodSecurity(prePostEnabled = true) 22 | public class AppConfig extends WebSecurityConfigurerAdapter { 23 | /** 24 | * This is your auth0 domain (tenant you have created when registering with auth0 - account name) 25 | */ 26 | @Value(value = "${com.auth0.domain}") 27 | private String domain; 28 | 29 | /** 30 | * This is the client id of your auth0 application (see Settings page on auth0 dashboard) 31 | */ 32 | @Value(value = "${com.auth0.clientId}") 33 | private String clientId; 34 | 35 | /** 36 | * This is the client secret of your auth0 application (see Settings page on auth0 dashboard) 37 | */ 38 | @Value(value = "${com.auth0.clientSecret}") 39 | private String clientSecret; 40 | 41 | @Bean 42 | public LogoutSuccessHandler logoutSuccessHandler() { 43 | return new LogoutController(); 44 | } 45 | 46 | @Bean 47 | public AuthenticationController authenticationController() throws UnsupportedEncodingException { 48 | JwkProvider jwkProvider = new JwkProviderBuilder(domain).build(); 49 | return AuthenticationController.newBuilder(domain, clientId, clientSecret) 50 | .withJwkProvider(jwkProvider) 51 | .build(); 52 | } 53 | 54 | @Override 55 | protected void configure(HttpSecurity http) throws Exception { 56 | http.csrf().disable(); 57 | 58 | http 59 | .authorizeRequests() 60 | .antMatchers("/callback", "/login", "/", "/*.png", "/css/**", "/js/**").permitAll() 61 | .anyRequest().authenticated() 62 | .and() 63 | .logout().logoutSuccessHandler(logoutSuccessHandler()).permitAll(); 64 | } 65 | 66 | public String getDomain() { 67 | return domain; 68 | } 69 | 70 | public String getClientId() { 71 | return clientId; 72 | } 73 | 74 | public String getClientSecret() { 75 | return clientSecret; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /01-Login/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 |
7 |
8 | 9 |

Spring MVC Security Sample Project

10 |

11 | This is a sample application that demonstrates an authentication flow for a web application using Spring MVC Security. 12 |

13 |
14 | 15 |
16 | 17 |
18 |

What can I do next?

19 | 20 |
21 |
22 |
23 | 24 | Configure other identity providers 25 | 26 |
27 |

Auth0 supports social providers as Facebook, Twitter, Instagram and 100+, Enterprise providers as Microsoft Office 365, Google Apps, Azure, and more. You can also use any OAuth2 Authorization Server.

28 |
29 | 30 |
31 | 32 |
33 |
34 | 35 | Enable Multifactor Authentication 36 | 37 |
38 |

Add an extra layer of security by enabling Multi-factor Authentication, requiring your users to provide more than one piece of identifying information. Push notifications, authenticator apps, SMS, and DUO Security are supported.

39 |
40 |
41 | 42 |
43 |
44 |
45 | 46 | Anomaly Detection 47 | 48 |
49 |

Auth0 can detect anomalies and stop malicious attempts to access your application. Anomaly detection can alert you and your users of suspicious activity, as well as block further login attempts.

50 |
51 | 52 |
53 | 54 |
55 |
56 | 57 | Learn About Rules 58 | 59 |
60 |

Rules are JavaScript functions that execute when a user authenticates to your application. They run once the authentication process is complete, and you can use them to customize and extend Auth0's capabilities.

61 |
62 |
63 |
64 |
65 |
66 |
67 | 68 | -------------------------------------------------------------------------------- /01-Login/README.md: -------------------------------------------------------------------------------- 1 | # Login 2 | 3 | [Full Tutorial](https://auth0.com/docs/quickstart/webapp/java-spring-security-mvc/01-login) 4 | 5 | ## Getting started 6 | 7 | This sample demonstrates how to use Auth0 to perform authentication using the `mvc-auth-commons` library. Download or clone this repository and follow the instructions below to setup the sample. 8 | 9 | ### Auth0 Dashboard 10 | 1. On the [Auth0 Dashboard](https://manage.auth0.com/#/clients) create a new Application of type **Regular Web Application**. 11 | 1. On the **Settings** tab of your application, add the URL `http://localhost:3000/callback` to the **Allowed Callback URLs** field. 12 | 1. On the **Settings** tab of your application, add the URL `http://localhost:3000/` to the **Allowed Logout URLs** field. 13 | 1. Copy the `Domain`, `Client ID` and `Client Secret` values at the top of the page and use them to configure the Java Application. 14 | 15 | ### Application configuration 16 | 17 | Copy `src/main/resources/auth0.properties.example` to `src/main/resources/auth0.properties`: 18 | 19 | ```bash 20 | cp src/main/resources/auth0.properties.example src/main/resources/auth0.properties 21 | ``` 22 | 23 | Set the application values in the `src/main/resources/auth0.properties` file to the values of your Auth0 application. They are read by the `AppConfig` class. 24 | 25 | ```xml 26 | com.auth0.domain: {YOUR_AUTH0_DOMAIN} 27 | com.auth0.clientId: {YOUR_AUTH0_CLIENT_ID} 28 | com.auth0.clientSecret: {YOUR_AUTH0_CLIENT_SECRET} 29 | ``` 30 | 31 | ### Running the sample 32 | 33 | Open a terminal, go to the project root directory and run the following command: 34 | 35 | ```bash 36 | ./gradlew clean bootRun 37 | ``` 38 | 39 | The server will be accessible on https://localhost:3000. 40 | 41 | ### Running the sample with docker 42 | 43 | In order to run the example with [Docker](https://docs.docker.com/install/) you need to have `docker` installed. 44 | 45 | You also need to set the client values as explained [previously](#application-configuration). 46 | 47 | Execute the command to run Docker for your environment: 48 | 49 | Linux or MacOS: 50 | 51 | ```bash 52 | sh exec.sh 53 | ``` 54 | 55 | Windows: 56 | 57 | ```bash 58 | .\exec.ps1 59 | ``` 60 | 61 | 62 | ## Issue Reporting 63 | 64 | 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. 65 | 66 | ## What is Auth0? 67 | 68 | Auth0 helps you to: 69 | 70 | * Add authentication with [multiple authentication sources](https://docs.auth0.com/identityproviders), either social like **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce, amont others**, or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS or any SAML Identity Provider**. 71 | * Add authentication through more traditional **[username/password databases](https://docs.auth0.com/mysql-connection-tutorial)**. 72 | * Add support for **[linking different user accounts](https://docs.auth0.com/link-accounts)** with the same user. 73 | * Support for generating signed [Json Web Tokens](https://docs.auth0.com/jwt) to call your APIs and **flow the user identity** securely. 74 | * Analytics of how, when and where users are logging in. 75 | * Pull data from other sources and add it to the user profile, through [JavaScript rules](https://docs.auth0.com/rules). 76 | 77 | ## Create a free account in Auth0 78 | 79 | 1. Go to [Auth0](https://auth0.com) and click Sign Up. 80 | 2. Use Google, GitHub or Microsoft Account to login. 81 | 82 | ## Issue Reporting 83 | 84 | 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. 85 | 86 | ## Author 87 | 88 | [Auth0](https://auth0.com) 89 | 90 | ## License 91 | 92 | This project is licensed under the MIT license. See the [LICENSE](/LICENSE) file for more info. 93 | -------------------------------------------------------------------------------- /01-Login/src/main/resources/templates/fragments/navbar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Spring MVC Security Quickstart 8 | 9 | 99 | -------------------------------------------------------------------------------- /01-Login/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS='"-Xmx64m"' 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | --------------------------------------------------------------------------------