Generally in live application we want our microservice or springboot application relam/method need to accessed based the perticular role i.e. we want some method to be specific access with role as manager and some method that can be accessed on if the user is have role as employee we can do this using keycloak Spring Security Adapter
Lets try to do the live example.
First we will configure our Keycloak server as shown below.
i am going to provide a redirect url here this is an endpoint of my application once authentication is successful the user will be redirected to this url i also provide an admin url this is usedby key clock to push revocation policies such as single logout normally this url is the base url of the client application this url is implicitly supported by key clock client adapters if you are not using an adapter you need to manually implement it but it is an optional feature.
Now copy the credential this will be used in our sprigboot application from here.
client id – spring-security-adaptor-client
Client secret – HSU2EJoTQHVOM80GJn3DxAPQc11TSTxh
now lets create a three role as shwon belwo.
1- ROLE_MANAGER
2- ROLE_EMPLOYEE
3- ROLE_USER
now lets assign few of this role to user
1- MANAGER user with ROLE_MANAGER
2- Employee user with ROLE_EMPLOYEE
2- USER user with ROLE_USER
lets create credential and assign above role created to them.
We are done with the keycloak configuration part now let move to the spring boot application.
Please follow the below step to create a spring boot application we are using STS.
Now lets add few more dependecies in our project
i.e.
spring-boot-starter-web,spring-boot-starter-security,keycloak-spring-boot-starter and keycloak-spring-security-adapter
our final pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.0.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <groupId>com.siddhu</groupId> <artifactId>siddhu-keycloak-sprintboot-adaptor</artifactId> <version>0.0.1-SNAPSHOT</version> <name>siddhu-springsecurity-keycloak-adaptor</name> <description>This example shows spring security with keycloak server</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.keycloak</groupId> <artifactId>keycloak-spring-security-adapter</artifactId> </dependency> <dependency> <groupId>org.keycloak</groupId> <artifactId>keycloak-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.keycloak.bom</groupId> <artifactId>keycloak-adapter-bom</artifactId> <version>7.0.1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> |
Note we are using spring 2.2.0.RELEASE and keycloakVersion 7.0.1 here.
lets create our controller class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | package com.siddhu.keycloak; import java.util.Date; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class SimpleController { private static final Logger LOGGER = LoggerFactory.getLogger(SimpleController.class); @GetMapping("/public") public String publicEndpoint(){ return "Response from public endpoint"; } @GetMapping("/private/manager") String manager(HttpServletRequest request){ /* * KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) * request.getUserPrincipal(); KeycloakPrincipal principal=(KeycloakPrincipal) * token.getPrincipal(); KeycloakSecurityContext session = * principal.getKeycloakSecurityContext(); AccessToken accessToken = * session.getToken(); * * LOGGER.info("username: {}", accessToken.getPreferredUsername()); * LOGGER.info("emailId: {}", accessToken.getEmail()); * LOGGER.info("lastname: {}",accessToken.getFamilyName()); * LOGGER.info("firstname: {}", accessToken.getGivenName()); * LOGGER.info("realmName: {}", accessToken.getIssuer()); * * return "manager"; */ return "Manager:" + (new Date()).toString(); } @GetMapping("/private/user") String user(HttpServletRequest request){ /* * KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) * request.getUserPrincipal(); KeycloakPrincipal principal=(KeycloakPrincipal) * token.getPrincipal(); KeycloakSecurityContext session = * principal.getKeycloakSecurityContext(); AccessToken accessToken = * session.getToken(); * * LOGGER.info("username: {}", accessToken.getPreferredUsername()); * LOGGER.info("emailId: {}", accessToken.getEmail()); * LOGGER.info("lastname: {}",accessToken.getFamilyName()); * LOGGER.info("firstname: {}", accessToken.getGivenName()); * LOGGER.info("realmName: {}", accessToken.getIssuer()); * * return "user"; */ return "User:" + (new Date()).toString(); } @GetMapping("/private/employee") String employee(HttpServletRequest request){ /* * KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) * request.getUserPrincipal(); KeycloakPrincipal principal=(KeycloakPrincipal) * token.getPrincipal(); KeycloakSecurityContext session = * principal.getKeycloakSecurityContext(); AccessToken accessToken = * session.getToken(); * * LOGGER.info("username: {}", accessToken.getPreferredUsername()); * LOGGER.info("emailId: {}", accessToken.getEmail()); * LOGGER.info("lastname: {}",accessToken.getFamilyName()); * LOGGER.info("firstname: {}", accessToken.getGivenName()); * LOGGER.info("realmName: {}", accessToken.getIssuer()); * * return "employee"; */ return "Employee:" + (new Date()).toString(); } } |
one configuration class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | package com.siddhu.keycloak; import org.keycloak.adapters.springsecurity.KeycloakConfiguration; import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper; import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy; import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; @KeycloakConfiguration class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter { /** * Registers the KeycloakAuthenticationProvider with the authentication manager. */ @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) { KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider(); // adding proper authority mapper for prefixing role with "ROLE_" keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); auth.authenticationProvider(keycloakAuthenticationProvider); } /** * Provide a session authentication strategy bean which should be of type * RegisterSessionAuthenticationStrategy for public or confidential applications * and NullAuthenticatedSessionStrategy for bearer-only applications. */ @Bean @Override protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); } /** * Secure appropriate endpoints */ @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); http.authorizeRequests() .antMatchers("/private/user").hasRole("USER") // only user with role user are allowed to access .antMatchers("/private/employee").hasRole("EMPLOYEE") // only employee with role employee are allowed to access .antMatchers("/private/manger").hasRole("MANAGER") // only manager with role manager are allowed to access .anyRequest().permitAll(); } } |
our main class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package com.siddhu.keycloak; import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; @SpringBootApplication @EnableGlobalMethodSecurity(prePostEnabled = true) public class SiddhuSpringsecurityKeycloakAdaptorApplication { /** * Use properties in application.yml instead of keycloak.json */ @Bean public KeycloakSpringBootConfigResolver keycloakConfigResolver() { return new KeycloakSpringBootConfigResolver(); } public static void main(String[] args) { SpringApplication.run(SiddhuSpringsecurityKeycloakAdaptorApplication.class, args); } } |
Lets now access the url
http://localhost:8081/private/user
Source Code :- https://github.com/shdhumale/siddhu-springsecurity-keycloak-adaptor.git