Spring Security Java API Authorization

You can get started by either downloading the seed project or if you would like to add Auth0 to an existing application you can follow the tutorial steps.

Sample Project

Download this sample project configured with your Auth0 API Keys.

System Requirements
  • Java 7 or above
  • Maven 3.0.x or above
Show requirements

In this step we will see how we can add role based authorization to our API, using Rules.

1. Create a Rule to assign roles

In our example we will create a simple rule that assigns two roles (ROLE_ADMIN and ROLE_USER) to any user. Of course you can change our sample code to match your needs.

To create a new rule, navigate to the new rule page and select the Set Roles To A User template, under Access Control. Then, replace the sample script with the following:

function (user, context, callback) {

  // make this rule run only for a specific CLIENT_ID
   if (context.clientID !== '{{YOUR_CLIENT_ID}}') {
     return callback(null, user, context);
   }

  user.app_metadata = user.app_metadata || {};
  // Edit the logic of the Roles assignment based on your requirements
  var addRolesToUser = function(user, cb) {
      cb(null, ['ROLE_ADMIN', 'ROLE_USER']);
  };

  addRolesToUser(user, function(err, roles) {
    if (err) {
      callback(err);
    } else {
      user.app_metadata.roles = roles;
      auth0.users.updateAppMetadata(user.user_id, user.app_metadata)
        .then(function(){
          callback(null, user, context);
        })
        .catch(function(err){
          callback(err);
        });
    }
  });
}

The first condition of this rule makes sure that it runs only for a specific CLIENT_ID. Make sure the value matches the CLIENT_ID of the Client you are using for this API.

What this rule does is add a roles property at the app_metadata. To customize your API based on its value, first you need to retrieve this information. This can be retrieved as part of the token.

When you ask for a token you need to add this new property, roles, as part of the scope parameter. For example, if your front-end is using Lock, the code should look like this:

var lock = new Auth0Lock('YOUR_CLIENT_ID', 'YOUR_AUTH0_DOMAIN');
lock.showSignin({
    authParams: {
        scope: 'openid roles'
    },
    // ... other params
});

For more details on the scope parameter refer to: Scopes.

2. Secure the endpoints

For our sample, we will allow anyone to call our ping endpoint. We will also allow both ROLE_USER and ROLE_ADMIN to perform GET operations on our /api/v1/profiles/** endpoints. However, we will restrict the POST, PUT and DELETE operations to strictly ROLE_ADMIN role privilege.

Add the following code at the AppConfig.java:

@Override
protected void authorizeRequests(final HttpSecurity http) throws Exception {
  http.authorizeRequests()
    .antMatchers("/ping", "/pong").permitAll()
    .antMatchers(HttpMethod.GET, "/api/v1/profiles").hasAnyAuthority("ROLE_USER", "ROLE_ADMIN")
    .antMatchers(HttpMethod.GET, "/api/v1/profiles/**").hasAnyAuthority("ROLE_USER", "ROLE_ADMIN")
    .antMatchers(HttpMethod.POST, "/api/v1/profiles/**").hasAnyAuthority("ROLE_ADMIN")
    .antMatchers(HttpMethod.PUT, "/api/v1/profiles/**").hasAnyAuthority("ROLE_ADMIN")
    .antMatchers(HttpMethod.DELETE, "/api/v1/profiles/**").hasAnyAuthority("ROLE_ADMIN")
    .anyRequest().authenticated();
}

3. Call Your API

You can now make requests against your secure API by providing the Authorization header in your requests with a valid JWT id_token.


curl --request GET \
  --url http://localhost:8000/path_to_your_api \
  --header 'authorization: Bearer YOUR_ID_TOKEN_HERE'
var client = new RestClient("http://localhost:8000/path_to_your_api");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Bearer YOUR_ID_TOKEN_HERE");
IRestResponse response = client.Execute(request);
package main

import (
	"fmt"
	"net/http"
	"io/ioutil"
)

func main() {

	url := "http://localhost:8000/path_to_your_api"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("authorization", "Bearer YOUR_ID_TOKEN_HERE")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.get("http://localhost:8000/path_to_your_api")
  .header("authorization", "Bearer YOUR_ID_TOKEN_HERE")
  .asString();
var settings = {
  "async": true,
  "crossDomain": true,
  "url": "http://localhost:8000/path_to_your_api",
  "method": "GET",
  "headers": {
    "authorization": "Bearer YOUR_ID_TOKEN_HERE"
  }
}

$.ajax(settings).done(function (response) {
  console.log(response);
});
var request = require("request");

var options = { method: 'GET',
  url: 'http://localhost:8000/path_to_your_api',
  headers: { authorization: 'Bearer YOUR_ID_TOKEN_HERE' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"authorization": @"Bearer YOUR_ID_TOKEN_HERE" };

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8000/path_to_your_api"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"GET"];
[request setAllHTTPHeaderFields:headers];

NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                if (error) {
                                                    NSLog(@"%@", error);
                                                } else {
                                                    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                    NSLog(@"%@", httpResponse);
                                                }
                                            }];
[dataTask resume];
$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_PORT => "8000",
  CURLOPT_URL => "http://localhost:8000/path_to_your_api",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_HTTPHEADER => array(
    "authorization: Bearer YOUR_ID_TOKEN_HERE"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}
import http.client

conn = http.client.HTTPConnection("localhost:8000")

headers = { 'authorization': "Bearer YOUR_ID_TOKEN_HERE" }

conn.request("GET", "/path_to_your_api", headers=headers)

res = conn.getresponse()
data = res.read()

print(data.decode("utf-8"))
require 'uri'
require 'net/http'

url = URI("http://localhost:8000/path_to_your_api")

http = Net::HTTP.new(url.host, url.port)

request = Net::HTTP::Get.new(url)
request["authorization"] = 'Bearer YOUR_ID_TOKEN_HERE'

response = http.request(request)
puts response.read_body
import Foundation

let headers = ["authorization": "Bearer YOUR_ID_TOKEN_HERE"]

var request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8000/path_to_your_api")!,
                                        cachePolicy: .UseProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.HTTPMethod = "GET"
request.allHTTPHeaderFields = headers

let session = NSURLSession.sharedSession()
let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    println(error)
  } else {
    let httpResponse = response as? NSHTTPURLResponse
    println(httpResponse)
  }
})

dataTask.resume()

Before making the request you should replace the port (8000) with the one on which your app is listening.

If the roles functionality is not working properly for you make sure that the roles property is included in the token. To ensure this you can log your token and use the JWT home page to decode it and review its contents.

4. You're done!

You have configured your Java Spring Security API to use Auth0. Congrats, you're awesome!

Previous Tutorial
2. Authentication
Use Auth0 for FREECreate free Account