Java Spring Security

Sample Project

Download a sample project specific to this tutorial configured with your Auth0 API Keys.

System Requirements
  • Java 7 or above
  • Gradle 3.3 or above
  • Spring Boot 1.5.3 or above
Show requirements

This integration guide will walk you through setting up and managing authentication and authorization in your Java Spring Security MVC apps using Auth0.

Get Your Application Keys

When you signed up for Auth0, you created a new client.

Your application needs some details about this client to communicate with Auth0. You can get these details from the Settings section for your client in the Auth0 dashboard.

You need the following information:

  • Client ID
  • Domain

If you download the sample from the top of this page, these details are filled out for you. If you have more than one client in your account, the sample comes with the values for your Default App.

App Dashboard

Configure Callback URLs

A Callback URL is a URL that Auth0 invokes after the authentication process. Auth0 routes your application back to this URL and attaches some details to it including a token. Callback URLs can be manipulated on the fly which could be harmful. For security reasons, you will need to add your application's callback URL in the Allowed Callback URLs box in your app's Client Settings. This will allow Auth0 to recognize the URLs as valid. The same principle applies to Logout URLs. They must be whitelisted in the Auth0 Dashboard.

If you are following this guide directly, set the following for your Callback and Logout URLs:

  • Allowed Callback URLs: http://localhost:8080/callback
  • Allowed Logout URLs: http://localhost:8080/logout

Setup Dependencies

You'll need to configure Spring Boot in your project first. You can generate the base project in this link, choosing Web in the dependencies and clicking the button "Generate Project". The downloaded project has the Spring Boot dependencies and plugin applied. You then need to add a Server dependency like Tomcat or Gretty, which one is up to you. Check our sample code for more information. The next step is to add the auth0-java-mvc-commons library. This one allows you to use Auth0 with Java for server-side MVC web apps. It generates the Authorize URL that you need to call in order to authenticate and validates the result received on the way back to finally obtain the Auth0 Tokens that identify the user. You can always check the latest version in the library's GitHub.

If you are using Gradle, add it to your build.gradle:

compile 'com.auth0:mvc-auth-commons:1.+'

If you are using Maven, add it to your pom.xml:

<dependency>
  <groupId>com.auth0</groupId>
  <artifactId>mvc-auth-commons</artifactId>
  <version>1.+</version>
</dependency>

Configure your Java Spring Security App

Your Java Spring Security App needs some information in order to authenticate against your Auth0 account. The samples read this information from the properties file src/main/resources/auth0.properties, but you could store them anywhere else. The required information is:

com.auth0.domain: YOUR_AUTH0_DOMAIN
com.auth0.clientId: YOUR_CLIENT_ID
com.auth0.clientSecret: YOUR_CLIENT_SECRET

The library we're using has this default behavior:

  • Request the scope openid, needed to call the /userinfo endpoint later to verify the User's identity.
  • Request the code Response Type and later perform a Code Exchange to obtain the tokens.
  • Use the HS256 Algorithm along with the Client Secret to verify the tokens.

But it also allows us to customize it's behavior:

  • To use the RS256 Algorithm along with the Public Key obtained dynamically from the Auth0 hosted JWKs file, pass a JwkProvider instance to the AuthenticationController builder.
  • To use a different Response Type, set the desired value in the AuthenticationController builder. Any combination of code token id_token is allowed.
  • To request a different scope, set the desired value in the AuthorizeUrl received after calling AuthenticationController#buildAuthorizeUrl().
  • To specify the audience, set the desired value in the AuthorizeUrl received after calling AuthenticationController#buildAuthorizeUrl().

Check populated attributes

If you download the seed using our Download Sample button then the domain, clientId and clientSecret attributes will be populated for you, unless you are not logged in or you do not have at least one registered client. In any case, you should verify that the values are correct if you have multiple clients in your account and you might want to use another than the one we set the information for.

Project Structure

The Login project sample has the following structure:

- src
-- main
---- java
------ com
-------- auth0
---------- example
------------ mvc
-------------- CallbackController.java
-------------- ErrorController.java
-------------- HomeController.java
-------------- LoginController.java
-------------- LogoutController.java
------------ security
-------------- AppConfig.java
-------------- TokenAuthentication.java
------------ App.java
---- resources
------ application.properties
------ auth0.properties
---- webapp
------ WEB-INF
-------- jsp
---------- home.jsp
- build.gradle

The project contains a single JSP: the home.jsp which will display the user information associated to the token after a successful login and provide the option to logout.

The access control is handled by the Spring Security framework. A few rules in the AppConfig.java class will suffice to check for existing tokens before giving the user access to our protected /portal/* path. If the tokens don't exist, the request will be redirected by the ErrorController to the LoginController.

The project contains also five Controllers:

  • LoginController.java: Invoked when the user attempts to login. The controller uses the client_id and domain parameters to create a valid Authorize URL and redirects the user there.
  • CallbackController.java: The controller captures requests to our Callback URL and processes the data to obtain the credentials. After a successful login, the credentials are then saved to the request's HttpSession.
  • HomeController.java: The controller reads the previously saved tokens and shows them on the home.jsp resource.
  • LogoutController.java: Invoked when the user clicks the logout link. The controller invalidates the user session and redirects the user to the login page, handled by the LoginController.
  • ErrorController.java: The controller triggers upon any non-handled exception and redirects the user to the /login path.

Authenticate the User

Let's begin by making your Auth0 credentials available on the App. In the AppConfig class we tell Spring to map the properties defined in the auth0.properties file to the corresponding fields by using the @Configuration and @Value annotations.


@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppConfig extends WebSecurityConfigurerAdapter {

    @Value(value = "${com.auth0.domain}")
    private String domain;
    @Value(value = "${com.auth0.clientId}")
    private String clientId;
    @Value(value = "${com.auth0.clientSecret}")
    private String clientSecret;

    //...
}

Next, define the rules that will prevent unauthenticated users to access our protected resources. You do that by allowing anyone to access the /login and /callback endpoints in order to be able to complete the login flow, and blocking them from accessing any other endpoint if they are not authenticated:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
    http
            .authorizeRequests()
            .antMatchers("/callback", "/login").permitAll()
            .antMatchers("/**").authenticated()
            .and()
            .logout().permitAll();
    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
}

Now create the AuthenticationController instance that will create the Authorize URLs and handle the request received in the callback. Do that by defining a method that returns the Bean in the same AppConfig class. Any customization on the behavior of the component should be done here. i.e. requesting a different response type or using a different signature verification algorithm.

@Bean
public AuthenticationController authenticationController() throws UnsupportedEncodingException {
    return AuthenticationController.newBuilder(domain, clientId, clientSecret)
            .build();
}

To authenticate the users you will redirect them to the Auth0 Hosted Login Page which uses the best version available of Lock. This page is accessible from what we call the "Authorize URL". By using this library you can generate it with a simple method call. It will require a HttpServletRequest to store the call context in the session and the URI to redirect the authentication result to. This URI is normally the address where your app is running plus the path where the result will be parsed, which happens to be also the "Callback URL" whitelisted before. Finally, request the "User Info" audience in order to obtain an Open ID Connect compliant response. After you create the Authorize URL, you redirect the request there so the user can enter their credentials. The following code snippet is located on the LoginController class of our sample.

@RequestMapping(value = "/login", method = RequestMethod.GET)
protected String login(final HttpServletRequest req) {
    String redirectUri = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/callback";
    String authorizeUrl = controller.buildAuthorizeUrl(req, redirectUri)
        .withAudience(String.format("https://%s/userinfo", appConfig.getDomain()))
        .build();
    return "redirect:" + authorizeUrl;
}

After the user logs in the result will be received in our CallbackController, either via a GET or a POST Http method. The request holds the call context that the library have previously set by generating the Authorize URL with the controller. When you pass it to the controller, you get back either a valid Tokens instance or an Exception indicating what went wrong. In the case of a successful call, you need to create a new TokenAuthentication instance with the id_token and set it to the SecurityContextHolder. You can modify this class to accept access_token as well, but this is not covered in this tutorial. If an exception is raised instead, you need to clear any existing Authentication from the SecurityContextHolder.

@RequestMapping(value = "/callback", method = RequestMethod.GET)
protected void getCallback(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException {
  try {
      Tokens tokens = controller.handle(req);
      TokenAuthentication tokenAuth = new TokenAuthentication(JWT.decode(tokens.getIdToken()));
      SecurityContextHolder.getContext().setAuthentication(tokenAuth);
      res.sendRedirect(redirectOnSuccess);
  } catch (AuthenticationException | IdentityVerificationException e) {
      e.printStackTrace();
      SecurityContextHolder.clearContext();
      res.sendRedirect(redirectOnFail);
  }
}

Display the Home Page

Now that the user is authenticated (the tokens exists), the framework will allow them to access our protected resources. In the HomeController you can get the existing Authentication object and even the Principal that represents it. Let's set that as the userId attribute so it can be used from the JSP code:

@RequestMapping(value = "/portal/home", method = RequestMethod.GET)
protected String home(final Map<String, Object> model, final Principal principal) {
    if (principal == null) {
        return "redirect:/logout";
    }
    model.put("userId", principal);
    return "home";
}

Run the Sample

To run the sample from a terminal, change the directory to the root folder of the project and execute the following line:

./gradlew clean bootRun

After a few seconds, the application will be accessible on http://localhost:8080/. Try to access the protected resource http://localhost:8080/portal/home and note how you're redirected by the framework to the Auth0 Hosted Login Page. The widget displays all the social and database connections that you have defined for this application in the dashboard.

Login using Lock

After a successful authentication you'll be able to see the home page contents.

Display Token

Log out by clicking the Logout button at the top right of the home page.

Use Auth0 for FREECreate free Account