Saturday, January 22, 2022

Securing Grails Application with Spring Security Rest | Rest API | Grails 3.x

How to Secure Grails Application with Spring Security Rest in Grails 3


In this tutorial, we are going to secure our grails application with spring security simply refer to spring security rest login. Here we are using grails version 3.3.0 and Java 8. This tutorial describes the configuration of Spring Security Core, Spring Security Rest with Grails 3 to secure the application.

  1. Running Java
  2. Running Grails
Create Grails Application:

1. Create App

In order to create grails application, open your terminal or cmd and type following command to create an app.
grails create-app spring-security-rest --profile rest-api

// Application created at (path of app)
Open your favorite text editor or IDE and open the project that we recently created.

Go to a created project folder.
cd spring-security-rest
Run grails interactive mode.
In order to run and stop an application simply type "run-app" and "stop-app"

2. Create Domain Class

Let's create a dummy class to test security called "Product". You can use either terminal or your IDE.
create-domain-class Product
Add some properties in the domain class.
class Product {
    String name
    Double price
    String companyName
    String description
    Date dateCreated = new Date()
    static constraints = {
Add some data using BootStrap.groovy
class BootStrap {

    def init = { servletContext ->
        if (Product.count() == 0){
            new Product(name: "product1", price: 10, companyName: "company1", description:"description1").save(flush:true)
            new Product(name: "product2", price: 100, companyName: "company2", description:"description2").save(flush:true)
            new Product(name: "product3", price: 1000, companyName: "company3", description:"description3").save(flush:true)
            new Product(name: "product4", price: 10000, companyName: "company4", description:"description4").save(flush:true)
    def destroy = {
Create Controller for product domain.
create-restful-controller Product
It will create controller like this:
class ProductController extends RestfulController {
    static responseFormats = ['json', 'xml']
    ProductController() {
Run application. And simply make get request, as following endpoint will results "product" data in Json format that we created in BootStrap.groovy.

Spring Security Core Plugin Configuration:

Under build.gradle file within dependencies add the following configuration and run command "compile"
dependencies {
    compile 'org.grails.plugins:spring-security-core:3.2.0'
Now its time to create user related tables,  for this exit from the interactive console.
grails s2-quickstart User Role
You can see:
Total time: 2.965 secs
| Creating User class 'User' and Role class 'Role' in package ''
| Rendered template PersonWithoutInjection.groovy.template to destination grails-app/domain/spring/security/rest/User.groovy
| Rendered template PersonPasswordEncoderListener.groovy.template to destination src/main/groovy/spring/security/rest/UserPasswordEncoderListener.groovy
| Rendered template Authority.groovy.template to destination grails-app/domain/spring/security/rest/Role.groovy
| Rendered template PersonAuthority.groovy.template to destination grails-app/domain/spring/security/rest/UserRole.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.               *
Which will create User.groovy, Role.groovy, and UserRole.groovy Domain classes.

Now let's create a user data for testing purpose using BootStrap.groovy.
def role1 = new Role(authority:"ROLE_USER").save flush:true
        def user1 = new User(username:"",password:"pwd@123").save flush:true
Spring Security Rest Plugin Configuration:
Under build.gradle file within dependencies add the following configuration and run command "compile"
dependencies {
    compile "org.grails.plugins:spring-security-rest:2.0.0.M2"
Go to application.groovy and add chainMap configuration:
grails.plugin.springsecurity.filterChain. chainMap = [
  [pattern: '/**',filters: 'JOINED_FILTERS,-anonymousAuthenticationFilter,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter'],
  [pattern: '/**', filters: 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter'] 
Note: If your endpoint start with or /othername then your chainMap look like
grails.plugin.springsecurity.filterChain. chainMap = [
  [pattern: '/api**',filters: 'JOINED_FILTERS,-anonymousAuthenticationFilter,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter'],
  [pattern: '/**', filters: 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter'] 

The final configuration looks like

// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.userLookup.userDomainClassName = ''
grails.plugin.springsecurity.userLookup.authorityJoinClassName = ''
grails.plugin.springsecurity.authority.className = ''
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
 [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: '/**',             access: ['isFullyAuthenticated()']]

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

Testing Secured REST API:
Now re-run the application and request the endpoint "http://localhost:8080/product"

which is our application is secured. I will make a tutorial for customizing this message format.

Next test the login endpoint with our existing user created in BootStrap.groovy. Here I am using Post-man.
Now access data via authorization.

Here, for authorization key use "Bearer access_token". You can see data as shown above. Because in our application.groovy we configure in such a way that all the login users can access data.
[pattern: '/**',             access: ['isFullyAuthenticated()']]
In the next tutorial I am going to create different customization for configuration and describe about different annotations.


1 comment:

  1. OMG! THis is a pain in the ass. There must be an easier way to do this. Didn't anyone build a plugin to auto-configure Spring security with the api's?? Oh wait, they did...


Blog Archive