Showing posts with label authorization. Show all posts
Showing posts with label authorization. Show all posts

Wednesday, November 28, 2018

Setup Keycloak with Docker


Introduction of Keycloak
Open Source Identity and Access Management For Modern Applications and Services. It 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.

You'll even get advanced features such as User Federation, Identity Brokering and Social Login.
Prerequisites:
Docker:
Since we are using Docker to install Keycloak; it should be installed on your machine. If it is not you can download and install it from the link given below, it’s pretty straight forward.
Create docker compose file
  1. We use keycloak with mysql database to persist the user data.
  2. Use the below docker-compose.yml file to pull and start the docker server

docker-compose.yml


In docker compose file we povide default user name and password for the keycloak use and described in the docker hub for the keycloak image.
  • Our mysql and keycloak server are running on the docker network “Keycloak-network”.
Start keycloak and mysql server
  • Run “docker-compose up” command on the terminal, once the server up you can see the output as below -

  • Go the browser and type the url - http: //localhost:9001 Note: remember we expose the port in the docker-compose file ?

You can now login keycloak from the username and password you provided in docker-compose file. In our case we use username “admin” and password also ‘admin’



After login you will see the default realm ‘master’ as below -

Core concept and terms of keycloak -
Realms:
A realm manages a set of users, credentials, roles, and groups. A user belongs to and logs into a realm. Realms are isolated from one another and can only manage and authenticate the users that they control.

Groups:
Groups manage groups of users. Attributes can be defined for a group. You can map roles to a group as well. Users that become members of a group inherit the attributes and role mappings that group defines.

Clients:
Clients are entities that can request Keycloak to authenticate a user. Most often, clients are applications and services that want to use Keycloak to secure themselves and provide a single sign-on solution. Clients can also be entities that just want to request identity information or an access token so that they can securely invoke other services on the network that are secured by Keycloak.

Client scopes:
When a client is registered, you must define protocol mappers and role scope mappings for that client. It is often useful to store a client scope, to make creating new clients easier by sharing some common settings. This is also useful for requesting some claims or roles to be conditionally based on the value of scope parameter. Keycloak provides the concept of a client scope for this.

Client role:
Clients can define roles that are specific to them. This is basically a role namespace dedicated to the client.

Identity token:
A token that provides identity information about the user. Part of the OpenID Connect specification. You can get more details about this terms here !
Conclusion:
In this blog we learn how to setup keycloak using docker, in next blog we will create an application and secure it using keycloak.

Reference https:

Friday, February 23, 2018

Spring Security with JWT and Oauth2 with Spring Boot

Introduction-

In this article we shall see example of how to secure a spring boot rest application with Spring Boot2, Spring Security, Oauth2, and JWT token.


1. Source Code Repository -

The code used in this article is available in this repository GitHub.


2. Dependencies -


2.1. Versions -

  1. Spring Boot: 2.1.3.RELEASE
  2. Java: 1.8

3. Entity Class -


We create two Entity Classes, one is User and another is Role. User entity class contains user details like name, password, roles details, and role entity contains the role details. One User may have many roles hence we to create many-to-many relationship between User and Role Entity.


3.1. User Entity.java


Entity class that contains the user details.


3.2. Role.java


Entity class that contains the user role data.

4. Create CRUD Repository -


We create spring CRUD repository class, to access user credentials from the database.
Note: we create repository only for User entity class, because in User entity class we specify Many to Many relationship between User and Role entity, and @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) at line number 35 in User.java, will ensure that when new record save in User entity it will also save in Role entity.

4.1. UserRepository.java



5. Create a Spring boot Initialize class


This will boot the spring application.


Now we need to create initial data for users create data.sql file and put it into resource directory.




6. Controller class


Now create controller class to access the resources.


Now our basic application is created, just the start the application server to see the output.

use mvn spring-boot:run to run the application

After the server start just curl the below URL to check if everything is working correct or not

curl http://localhost:8080/app/listAll

Response -

[
  {
    "id": 1,
    "username": "vikas",
    "password": "$2a$04$lZj8KgBFkcPwgRWjH8DwBeCIR7HE6AsIZqTXu2VyeEw5sYLySNAGe",
    "firstName": "vikas",
    "lastName": "verma",
    "roles": [
      {
        "id": 1,
        "roleName": "ADMIN",
        "description": "admin role"
      }
    ]
  },
  {
    "id": 2,
    "username": "james",
    "password": "$2a$04$P2GbxPDh1MYNYyNn/bj.4.QxwDC2jze0xPQF4u6/cNpdkrPq3OdPy",
    "firstName": "james",
    "lastName": "james",
    "roles": [
      {
        "id": 1,
        "roleName": "ADMIN",
        "description": "admin role"
      },
      {
        "id": 2,
        "roleName": "USER",
        "description": "user role"
      }
    ]
  }

]

7. Authentication and Authorization


Now since our basic application is working, it’s time to add authentication and authorization to our application.
Add Dependencies for the Oauth2 Security


7.1. Set the properties related to security


The detail of the properties is as below -
1. security.encoding-strength=256 size of the encoding.
2. security.signing-key is the sign key used to encode the token.
3. security.security-realm realm of the authentication. see
4. security.jwt.client-id=client Client Id.
5. security.jwt.client-secret= It should be BCrypt format you can use this tool to encode any string to BCrypt
6. security.jwt.grant-type=password Grant type, it can be "password", "refresh-token".
7. security.jwt.scope-read=read read scope.
8. security.jwt.scope-write=write write scope.
9. security.jwt.resource-ids=testresource resource id.


7.3. JWTConfigProperties.java


Create a class to access the properties set in application property file.


7.4. UserDetailServiceImpl.java


To access the user credentials from database, we need to implement interface UserDetailsService. It is used throughout the framework as a user DAO. The interface requires only one read-only method, which simplifies support for new data-access strategies.


7.5. WebSecurityConfig.java


Configure the web security by extending the WebSecurityConfigurerAdapter class. It provides a convenient base class for creating a WebSecurityConfigurer instance. The implementation allows customization by overriding methods.

Step#1 Configure UserDetailsService to AuthenticationManager class, and add a password encoder.
*Autowire the userDetailsService instance.

Step#2 Now create AuthenticationManager bean

Since we are using password as grant-type we need to provide the AuthenticationManager implementation.

Step#3 Configure the JWT Token related beans -
tokenStore() Create a new JwtTokenStore with this token enhancer(accessTokenConverter).

accessTokenConverter() Configure JWT signing key. It can be either a simple MAC key or an RSA key. . RSA keys should be in OpenSSH format, as produced by ssh-keygen.

tokenServices() it is default implimentation of the tokenServices, it used to configure the resource related properties. In the tokenServices we used the default implementation of the TokeService interface, and set persistence strategy for token storage. the tokenStore, and configure to support the refresh token.

Now enable Web Security in the application, and Global Method security-

@EnableWebSecurity : It allow the Spring Security configuration defined in any WebSecurityConfigurer or more likely by extending the WebSecurityConfigurerAdapter base class and overriding individual methods.

@EnableGlobalMethodSecurity(prePostEnabled = true) : Enables Spring Security global method security.

@Order : Define the order the security filter chain. The priority of the WebSecurityConfigurerAdapter is more than the resourceServerConfigurationAdapter, hence we re-define the order WebSecurityConfigurerAdapter


8. Define Authentication Manager


Create a class AuthenticationServerConfig.java that extends  AuthorizationServerConfigurerAdapter.java to provides the default implementation for the AuthorizationServer. It is used to register the clients that can access the resource of the application, and also endpoints of the authorization server.


8.1. Configure Clients of the application


the code is self-explanatory, we jest configure the client details that are stored in memory. All the clients’ details are store in the application.property file.
*Autowire the jwtConfigProperties instance.


8.2. Configure the Authorization endpoints


*Autowire the jwtConfigProperties, jwtAccessTokenConverter, tokenStore and authenticationManager instance.
Configure the tokenstore, and tokenEnhancer with the AuthorizationServerEndpointsConfigurer
Configure the TokenStore, authenticationManager, and tokenEnhancerChain in the AuthorizationServerEndpointsConfigurer class.


8.3. Enable Authorization Server in the current application context



9. Resource Server Configuration


Create a class ResourceServerConfig.java that extends ResourceServerConfigurerAdapter.java
This class is used to configure the resourceIds, and the http request URLs that are allowed to access the application, and the URLs that need to be authenticated.


9.1. Configure Resource Id


*Autowire the jwtConfigProperties, defaultTokenService bean instances.
Resource id is configured in application.property file. defaultTokenService is created in class WebSecurityConfig.


9.2. Configure HttpSecurity


This configuration says, authenticate all request that contains "/app/**" in there URL.

9.3. Enable the resource server configuration


10. Modify the controller class


Finally set the roles that can access the application using @PostAuthorize annotation


11. Run The application


11.1 Run MySQL Database

Run below command to run the mysql db in docker

 docker-compose -f docker/docker-compose up


Now all the configurations are done, now we can run the application using below maven command in terminal

 mvn spring-boot:run


11.1 Access Resource with User credentials


After server started, We can get the access token. Run below command to get the access token-


11.1.1. Get Access Token



Result-

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzb3VyY2UiXSwidXNlcl9uYW1lIjoidmlrYXMiLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwiZXhwIjoxNTUyMDA5ODM2LCJhdXRob3JpdGllcyI6WyJBRE1JTiJdLCJqdGkiOiI3YWJkOThhNC1hNjM4LTRmYmQtOWYzMC0zZWJiNDQ0M2FhMTciLCJjbGllbnRfaWQiOiJjbGllbnQifQ.P0UgLpAuswCs8iHsxT4q23TI1infsIMqZ1YtMlbfWe8",
  "token_type": "bearer",
  "expires_in": 43199,
  "scope": "read write",
  "jti": "7abd98a4-a638-4fbd-9f30-3ebb4443aa17"

}

11.2 Access Resource


11.2.1. Get the access token



** "Y2xpZW50OnNlY3JldA==" is Base64 encoded client-id:secret. you can encode and decode in base64 format using this site. The format of client-id and client-secret should be 'client-id:secret'.

Result-

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzb3VyY2UiXSwidXNlcl9uYW1lIjoidmlrYXMiLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwiZXhwIjoxNTUyMDA5ODM2LCJhdXRob3JpdGllcyI6WyJBRE1JTiJdLCJqdGkiOiI3YWJkOThhNC1hNjM4LTRmYmQtOWYzMC0zZWJiNDQ0M2FhMTciLCJjbGllbnRfaWQiOiJjbGllbnQifQ.P0UgLpAuswCs8iHsxT4q23TI1infsIMqZ1YtMlbfWe8",
  "token_type": "bearer",
  "expires_in": 43199,
  "scope": "read write",
  "jti": "7abd98a4-a638-4fbd-9f30-3ebb4443aa17"

}


11.2.2. Access Admin Resources


To access the resource that required admin privilege you need to get the access token with user james/james, because this user have admin privilege



Result-

Access admin resources -
Hello Admin!!!
Access user resources -

Hello User!!!


11.2.3. Access the User resources


Result-
Hello User!!!

That's all for the Authentication and Authorization with Oauth2. You can access the resource from GitHub.