Secure springboot app without any code

Secure springboot app using keycloak

1. Why not code our own security?

  • As humans, we are not safe from making mistakes.
  • Coding security features is time consuming and requires a lot of tests.
  • Coding security features can become complex and difficult.
  • Often Security features are repeatable and reusable(why not use a good one time solution)

2. Keycloak

Keycloak is an open source Identity and Access Management solution aimed at modern applications and services. It makes it easy to secure applications and services with little to no code.

3. Advantages of Keycloak

  • Sponsored by Redhat.
  • Opensource
  • Add authentication to applications and secure services with minimum fuss.
  • No need to deal with storing users or authenticating users. It’s all available out of the box.
  • Get advanced features such as User Federation, Identity Brokering and Social Login.
  • Can be easily implemented to spring based applications.

4. A Keycloak explanation

Keycloak mainly consists of Realms and Clients

1. Realms
  • Realms basically represents your application or solution.
  • Realms contain all authentication/authorization configuration details.
  • A realm can be divided in clients.
2. Clients
  • Clients form part of a realm.
  • A client represents a security part of your application.
  • For example we can have a front client for your angular application and a back client for your springboot application

5. Architecture of a springboot application using keycloak

1. Architecture explanation

  • Users access their front end client.
  • The front client redirects the user to the keycloak login page.
  • The user credentials are checked by the keycloak AuthServer client.
  • Once the user logins successfully, keycloak redirects the user back to the front end client with an access token(jwt).
  • The front end client will then use this access token in all subsequent rest requests to the springboot backend application as a bearer token in the header.
  • The springboot backend application will then contact the keycloak ResourceServer client for authorization checks.

2. Configure Keycloak

1. Create a realm
  1. Hover on the Master realm and click on the Add realm button.
  2. Add realm details and click on create button, here we will call our realm myrealm.
2. Create roles
  • Create ROLE_USER and ROLE_ADMIN roles.
  • Go to roles screen and click on add role button.
Example
3. Create users
  • Create users juser and jadmin
  • Go to users screen and click on add user button.
Example
4. Set user password
  • In the created user screen, go to the credentials tab.
  • Set the password
5. Add role to user
  • In the user screen go to the Role Mappings tab.
  • For user juser, add role ROLE_USER
  • For user jadmin, Add role ROLE_ADMIN
  • Chose the role and click on the add selected button.
6. Create auth-server client
  • Create auth-server client for our front end application.
  • Go to clients page and click on create button.
  • Add the below details and click on save.
7. Create resource-server client
  • Create resource-server client for springboot application.
  • Go to clients page and click on create button.
  • Add the below details and click on save.
8. Configure resource-server client
  • Set resource-server client access type to confidential.
  • To use a client as a resource server, we have to set access type to confidential.
  • Enable Service accounts and Authorization options and click on save.
9. Configure resource server permissions

Keycloak uses policies and permissions for securing resources.

  • One permission will be connected on one resource(uri)
  • The permission can have multiple policies.
10. Create Resources

Resources are uri that matches your path uri in your spring controllers.

  • Go to clients > resource-server > Authorization > Resources and click on the create button.
  • Here we will create two resources, admin and user.
  • Set the resource details and click save.
11. Create policy
  • Go to clients > resource-server > Authorization > Policies and click on the create policy dropdown button.
  • Chose Role based policy.
  • Here we will use security based on roles.
  • Add details and click on save.
  • Here we are creating two policies, admin and user
12. Create permissions
  • Create admin_permission and user_permission
  • Add details and click save.
13. Find resource-server client secret key
  • Go to clients > resource-server > credentials
  • Copy the secret key.
  • We will use this secret in our springboot application to connect it to keycloak resource-server client.

6. Spring boot application

  • Here we have a controller class with two functions to test authorization.
  • We have two controller functions, one for user and one for admin.
  • We do not have any additional java configurations or codes to define security.
  • Only thing we need to do is to add keycloak settings in the application.yml
1. Spring controller
@RestController
public class UsersController {

    @GetMapping("/user/fetch")
    public String fetch() {
        return "Hello user. Any user can view this";
    }

    @GetMapping("/admin/fetch")
    public String adminStatus() {
        return "Hello Admin. Only admin can view this";
    }
}
2. application.yml
  • Enable cors as our application is running on port 8081 and keycloak on 8080.
  • For keycloak we will set properties like auth-server-url, realm(realm name), resource(resource-server client name)
  • For the client resource-server client to work as a resource server, we have to set the property policy-enforcer-config with attribute enforcement-mode: ENFORCING.
  • We set security-constraints.auth-roles to "*" and security-constraints.patterns to "/*" so that all resources authorization are taken care by keycloak only.
server:
  port: 8081
  cors:
    origins:
      - http://localhost:8080

keycloak:
  auth-server-url: http://localhost:8080/auth
  realm: myrealm
  resource: resource-server
  credentials:
    secret: 0da76edf-e2df-49a9-a336-6b9bc35afa7e
  policy-enforcer-config:
    enforcement-mode: ENFORCING

  security-constraints:
    - auth-roles:
        - "*"
      security-collections:
        - name:
          patterns:
            - /*
logging:
  level:
    org.keycloak: DEBUG

3. pom.xml

Add keycloak dependencies

<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.keycloak.bom</groupId>
				<artifactId>keycloak-adapter-bom</artifactId>
				<version>${keycloak.version}</version>
				<type>pom</type>
			</dependency>
		</dependencies>
</dependencyManagement>
<dependencies>
        <dependency>
			<groupId>org.keycloak</groupId>
			<artifactId>keycloak-spring-boot-starter</artifactId>
			<version>${keycloak.version}</version>
		</dependency>
</dependencies>

7. Test the application

  • For the front end part i will use postman to get the jwt access token. In real life situation, you will use a front end application like angular or react js.
  • For the rest consumption, i will also use postman.

1. Get an jwt access token

  • Use postman to get access token.
  • in body, set username, password and client_id which is auth-server client name
  • The url will be http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token
  • In Body of postman chose x-www-form-urlencoded
  • set the client_id,username,password and grant_type
  • set grant_type to password

2. User Fetch resource

  • juser with role ROLE_USER accesssing resource /user/fetch
  • Action is successful
  • juser with role ROLE_USER accesssing resource /admin/fetch
  • Action fails with a 403 forbidden error as ROLE_ADMIN does not have access to /admin/*

3. Admin Fetch resource

  • jadmin with role ROLE_ADMIN accesssing resource /admin/fetch
  • Action is successful

8. References

  • https://www.keycloak.org/
  • https://www.keycloak.org/docs/latest/getting_started/index.html
  • https://www.keycloak.org/getting-started/getting-started-docker

Leave a Reply