Securing REST API with Grails 3 and Spring Security Rest

by Didin J. on Feb 16, 2017 Securing REST API with Grails 3 and Spring Security Rest

How to securing REST API with Grails 3, Spring Security Core and Spring Security Rest Plugin in quick and easy steps.

This tutorial describes how to securing REST API with Grails 3 (latest version 3.2.6), Spring Security Core and Spring Security Rest plugin which very good for mobile apps backend. As usually, we will begin this tutorial from scratch.

This application use as a backend for our mobile apps. We will create a resource that accessible only to authenticated user. If non-authenticated user access this resource using REST API it will response "forbidden".


1. Create Grails 3 Application

We assume that you already installing Java 8 and Grails 3. So we will jump to Grails 3 project creation. For that, just open terminal or cmd then type this command.

grails create-app MySecureRest

Go to a newly created project folder.

cd MySecureRest

To make sure everything is working smoothly during this tutorial, run Grails 3 interactive console.

grails

And then run the application.

run-app

If everything working fine and you see Grails 3 application homepage in the browser, you can continue to the next step. For now, stop the app first.

stop-app

Now, create a RESTful domain class that will be secured later. There's is a tutorial for creating REST API on this site.

create-domain-class com.mysecurerest.Product

Open and edit this generated file with your favorite text editor or IDE. Make this domain like this.

package com.mysecurerest
import grails.rest.*

@Resource(uri='/api/product')
class Product {

    String prodName
    String prodDesc
    Double prodPrice
    Date createDate = new Date()

    static constraints = {
    }
}

Create initial data for this Product domain class. Open and edit "grails-app/init/mysecurerest/Bootstrap.groovy" the add this lines inside init function.

package mysecurerest

import com.mysecurerest.Product

class BootStrap {

    def init = { servletContext ->
      def prod1 = new Product(prodName:"iPhone 7",prodDesc:"New iPhone 7 32GB",prodPrice:780).save flush:true
      def prod2 = new Product(prodName:"iPhone 7 Plus",prodDesc:"New iPhone 7 Plus 128GB",prodPrice:990).save flush:true
      def prod3 = new Product(prodName:"iPhone 7 SE",prodDesc:"New iPhone 7 SE 64GB",prodPrice:520).save flush:true
    }
    def destroy = {
    }
}

Run again this application for testing the Rest API.

run-app

Open another terminal or command to test the REST API with this command.

curl -i -H "Accept: application/json" localhost:8080/api/product

2. Add and Configure Grails 3 Spring Security Core Plugin

Open and edit file "build.gradle" at the root of the project. Add this line in dependencies section.

compile "org.grails.plugins:spring-security-core:3.1.1"

Compile the application in Grails 3 interactive console by type this command.

compile

Create a user, role, and relation using this command. Before doing that, we should exit from Grails 3 interactive command because this command does not activate yet in the interactive console.

exit
grails s2-quickstart com.mysecurerest User Authority

Which "s2-quickstart" is a command from Spring Security plugin and this command will generate User, Authority (Role) and UserAuthority domain class. You will see below messages if successfully generate that domain classes.

CONFIGURE SUCCESSFUL

| Creating User class 'User' and Role class 'Authority' in package 'com.mysecurerest'
| Rendered template Person.groovy.template to destination grails-app/domain/com/mysecurerest/User.groovy
| Rendered template Authority.groovy.template to destination grails-app/domain/com/mysecurerest/Authority.groovy
| Rendered template PersonAuthority.groovy.template to destination grails-app/domain/com/mysecurerest/UserAuthority.groovy
|
************************************************************
* Created security-related domain classes. Your            *
* grails-app/conf/application.groovy has been updated with *
* the class names of the configured domain classes;        *
* please verify that the values are correct.               *
************************************************************

That command also creates configuration files with "groovy" extension in code style of Groovy. Later, in this file will put configuration related to Spring Security.

 


3. Add and Configuring Grails 3 Spring Security Rest Plugin

This time to add and configuring Grails 3 Spring Security Rest plugin. Open and edit file "build.gradle" again then add this line inside dependencies section.

compile "org.grails.plugins:spring-security-rest:2.0.0.M2"

To make this plugin works and configurable, first compile the application.

compile

Next, open and edit "grails-app/conf/application.groovy" to configure Grails Spring Security Rest plugin. First, change "staticRules" to "interceptUrlMap". Add login, logout, and product endpoints and also add "/**". Change "filterChain" with new filters. Add another configuration lines for logout endpoint, token and token storage. At the end configuration file will look like this.

// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.mysecurerest.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.mysecurerest.UserAuthority'
grails.plugin.springsecurity.authority.className = 'com.mysecurerest.Authority'
grails.plugin.springsecurity.securityConfigType = "InterceptUrlMap"
grails.plugin.springsecurity.interceptUrlMap = [
    [pattern: '/',               access: ['permitAll']],
    [pattern: '/error',          access: ['permitAll']],
    [pattern: '/index',          access: ['permitAll']],
    [pattern: '/index.gsp',      access: ['permitAll']],
    [pattern: '/shutdown',       access: ['permitAll']],
    [pattern: '/assets/**',      access: ['permitAll']],
    [pattern: '/**/js/**',       access: ['permitAll']],
    [pattern: '/**/css/**',      access: ['permitAll']],
    [pattern: '/**/images/**',   access: ['permitAll']],
    [pattern: '/**/favicon.ico', access: ['permitAll']],
    [pattern: '/api/login',          access: ['permitAll']],
    [pattern: '/api/logout',        access: ['isFullyAuthenticated()']],
    [pattern: '/api/product',    access: ['isFullyAuthenticated()']],
    [pattern: '/**',             access: ['isFullyAuthenticated()']]
]

grails.plugin.springsecurity.filterChain.chainMap = [
    [pattern: '/api/**', filters:'JOINED_FILTERS,-anonymousAuthenticationFilter,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter'],
  [pattern: '/**', filters:'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter']
]

grails.plugin.springsecurity.rest.logout.endpointUrl = '/api/logout'
grails.plugin.springsecurity.rest.token.validation.useBearerToken = false
grails.plugin.springsecurity.rest.token.validation.headerName = 'X-Auth-Token'
grails.plugin.springsecurity.rest.token.storage.memcached.hosts = 'localhost:11211'
grails.plugin.springsecurity.rest.token.storage.memcached.username = ''
grails.plugin.springsecurity.rest.token.storage.memcached.password = ''
grails.plugin.springsecurity.rest.token.storage.memcached.expiration = 86400

Next, add initial user data in "grails-app/init/mysecurerest/Bootstrap.groovy".

def role1 = new Authority(authority:"ROLE_USER").save flush:true
def user1 = new User(username:"user1",password:"pwd1").save flush:true
UserAuthority.create(user1,role1)

Don't forget to change import for all domain class.

import com.mysecurerest.*


4. Test Secured REST API

Right now, we will use third party tools for testing REST API. We are using "Postman" the chrome extension for testing our REST API. Open "postman" chrome app/extension.

Grails 3 Spring Security REST - Postman

In the main text box enter endpoint URL for getting product data. On the left of text box change to "GET", then click "SEND" button.

Grails 3 Spring Security Rest - GET data

If the response shows like below, it means product REST API is secured.

{
  "timestamp": 1487220350104,
  "status": 403,
  "error": "Forbidden",
  "message": "Access Denied",
  "path": "/api/product"
}

Next, we have to test login endpoint by entering end login endpoint in the text box, on the left change to "POST". Under the text box click "body" tab and choose "raw" radio button then filled raw data like below. Then click "SEND" button.

Grails 3 Spring Security REST - POST Login

You should see a response like this if login is successful.

{
  "username": "user1",
  "roles": [
    "ROLE_USER"
  ],
  "access_token": "eyJhbGciOiJIUzI1NiJ9.eyJwcmluY2lwYWwiOiJINHNJQUFBQUFBQUFBSlZTUDBcL2JRQlJcL0Rva0FJVkdvQkJJRFhRb2Jja1E3Wmlvb0lDRUxFR2tXa0lvdTlzTTlPTitadXpNa0M4b0VBd01JaWxTMVg0RnYwaTc5QUFpR3JzeGQrODRRbkxLZzNtU1wvK1wvbjM3XC9uNkhpcEd3XC90WU15Nk1uNG9zNXRJM3FlWXlOaGhtbXR1T254blVFZG9jc1p3RG16U0JoK09Wd0F1Z3hDTUxyNE5kZHNDcWdzbTR1dGJheGREVzJocmVLUjBcL011NW9sdUNoMG52K0UzZW9OUDRqVUZCNzMwb3d1QW5qTEF4Vkp1MnFrdlYyeWpWR216Qld6QUlWN3JuUlJFZzNLQzFud3ZSREIxR3lsc0FvZ0JHVzJjK0tWRGthQzY4ZXpHYVdpMm9EYlMyQW9aUVpRKzZlSldsWVo5M2RPNXVTRXV6REVaVGJxVWVIdXB0MVVOXC94K0l0S0NFck5sVFF6VFptb2lPOXdKMDc4M2VtTFgyZmZ1ODBTQUhVeTlcL0kzeFh4cUFib1wvUHYxNWt4ZnRoUlltKzZ3WHNGbzdKVGZqQmZOSGpVNzU1dXY2NWRYOXlkWUFLVHZFMHZcL3ZZK2JEWTNPZFJaV2tURE9yK25aRXRJZGw5MHprQ3krVDk3YlE4UnM4U1FYU0h5VXRSazhTQlRIRkxXc2xlbjFiR041WUMrcmJ6VVo5dzcxVm5NMTVFaDNOTTd0bCtZR2lWWjMrUHY5NTl2YVdDRmFnY3NCRWhsVDVXQUZhelpJVzZ1UHJxK21STDNlbmVZRGV6XC93WDdpTU1IUkFEQUFBPSIsInN1YiI6InVzZXIxIiwicm9sZXMiOlsiUk9MRV9VU0VSIl0sImV4cCI6MTQ4NzIyNDQxNSwiaWF0IjoxNDg3MjIwODE1fQ.w1ODU8pqw3uWEz1pz1K5he5AiCSKQgvOB4D40yCeG0g"
}

Copy the "access_token" from the response. Do the step for getting product data then click Header tab below "textbox". In the key field fill with "X-Auth-Token" and value field paste from "access_token" that previously copied.

Grails 3 Spring Security REST - Get data with auth token

Now, you will see a response like this.

[
  {
    "id": 1,
    "createDate": "2017-02-16T04:20:22Z",
    "prodDesc": "New iPhone 7 32GB",
    "prodName": "iPhone 7",
    "prodPrice": 780
  },
  {
    "id": 2,
    "createDate": "2017-02-16T04:20:22Z",
    "prodDesc": "New iPhone 7 Plus 128GB",
    "prodName": "iPhone 7 Plus",
    "prodPrice": 990
  },
  {
    "id": 3,
    "createDate": "2017-02-16T04:20:22Z",
    "prodDesc": "New iPhone 7 SE 64GB",
    "prodName": "iPhone 7 SE",
    "prodPrice": 520
  }
]

This mean, we are creating secured Grails 3 REST API successfully.

Thanks.

The following resources might be useful for you:

Loading…