How to include Spring Security in a spring boot application - maven

I am working of a spring boot application. After developing the application, we are now trying to include spring security in our application.
I have included the following code:
html code:
<li th:if="${#authorization.expression('!isAuthenticated()')}">
<a th:href="#{/login}" th:text="#{navbar.login.text}" />
</li>
Java code:
package com.devopsbuddy.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final String[] PUBLIC_MATCHERS = {
"/webjars/**",
"/css/**",
"/js/**",
"/images/**",
"/",
"/about/**",
"/contact/**",
"/error/**/*"
};
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(PUBLIC_MATCHERS).permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").defaultSuccessUrl("/payload")
.failureUrl("/login?error").permitAll()
.and()
.logout().permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password")
.roles("USER");
}
}
when I try to hit the url:
http://localhost:8080/
I am getting the below error on screen:
**36673 [http-nio-8080-exec-2] ERROR org.thymeleaf.TemplateEngine - [THYMELEAF][http-nio-8080-exec-2] Exception processing template "user/login": Exception evaluating SpringEL expression: "#authorization.expression('!isAuthenticated()')" (template: "common/navbar" - line 24, col 25)
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "#authorization.expression('!isAuthenticated()')" (template: "common/navbar" - line 24, col 25)
at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:290)
at org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:166)
at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:66)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:125)
...
...
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1011E: Method call: Attempted to call method expression(java.lang.String) on null context object
at org.springframework.expression.spel.ast.MethodReference.throwIfNotNullSafe(MethodReference.java:153)
at org.springframework.expression.spel.ast.MethodReference.getValueRef(MethodReference.java:82)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:67)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:111)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:328)
at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:263)
... 102 common frames omitted
36673 [http-nio-8080-exec-2] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "#authorization.expression('!isAuthenticated()')" (template: "common/navbar" - line 24, col 25)] with root cause
org.springframework.expression.spel.SpelEvaluationException: EL1011E: Method call: Attempted to call method expression(java.lang.String) on null context object
at org.springframework.expression.spel.ast.MethodReference.throwIfNotNullSafe(MethodReference.java:153)
at org.springframework.expression.spel.ast.MethodReference.getValueRef(MethodReference.java:82)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:67)**
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
I am new to Thymeleaf and Spring security. So not sure why the Spring security is failing.
If i comment the line with authorization.expression(), it works.
I have shared the code at https://github.com/azaveri7/devopsbuddy in branch security.
Please advise.

please consider this as a suggestion, not an answer. previously I also went through this but hard to figure it out. then I decided to go through spring's automatic configurations. I only used this library -
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
and then spring provided the login URL, login page, logout URL etc.. I only wrote the userdetailsService. and in my case, I also wrote a custom filter also.

The spring security is 5.0.9 in your pom that extend the spring-boot-starter-parent 2.0.6
BUT thymeleaf-extras-springsecurity4 is still spring security 4, so you need to upgrade the thymeleaf-extras to
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>

I have the below to check if user is not logged-in or not
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
....
<span sec:authorize="not isAuthenticated()">
You are not logged in - click <a th:href="#{/login}">login</a>
</span>
...

Related

Start Springboot without any Undertow Configuration

I have a project which mixes 2 dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-installed-adapter</artifactId>
<version>11.0.2</version>
</dependency>
I'm getting a transitiv dependency for Undertow, which comes from
keycloak-installed-adapter
As far as I understood, Undertow is used internally within the KeyCloak libraries.
I don't want my Springboot Application to start with Undertow, nor I want that anything related with Undertow gets configured at Springboot level.
I can't find to completely exclude any Undertow configuration for Springboot. Does anyone have an idea?
Update
I now have the following:
#SpringBootApplication
#EnableAutoConfiguration(exclude = {EmbeddedUndertow.class})
public class SpringbootTest {
public static void main(String[] args) {
SpringApplication.run(SpringbootTest.class, args);
}
}
But i'm getting following exception when starting my service:
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'undertowEmbeddedServletContainerFactory' defined in class path resource [org/springframework/boot/autoconfigure/web/EmbeddedServletContainerAutoConfiguration$EmbeddedUndertow.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory]: Factory method 'undertowEmbeddedServletContainerFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: io/undertow/servlet/api/SessionPersistenceManager
Knowing that the EmbeddedUndertow Class lokks like:
#Configuration
#ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
#ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedUndertow {
#Bean
public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory() {
return new UndertowEmbeddedServletContainerFactory();
}
}
How would you ignore this calss from the scanning?

Spring security and keyclock - ServerHttpSecurity error

I'm trying to add Spring Security to my Spring Boot application. I've created new SecurityConfig class and I've added the code below:
#Configuration
#EnableWebSecurity
public class SecurityConfig {
#Bean
public SecurityWebFilterChain configSecurity(ServerHttpSecurity http) {
return http
.authorizeExchange(exchange -> exchange.matchers(EndpointRequest.toAnyEndpoint()).permitAll().anyExchange().authenticated())
.oauth2ResourceServer(ServerHttpSecurity.OAuth2ResourceServerSpec::jwt)
.build();
}
}
When I try to start the application I get the error:
2021-04-08 08:58:47.828 INFO 3040 --- [ main]
o.s.s.web.DefaultSecurityFilterChain : Will secure any request
with
[org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter#6089c1e3,
org.springframework.security.web.context.SecurityContextPersistenceFilter#4bba628,
org.springframework.security.web.header.HeaderWriterFilter#47b4fcd5,
org.springframework.security.web.csrf.CsrfFilter#439acac0,
org.springframework.security.web.authentication.logout.LogoutFilter#6af447b6,
org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter#5679e464,
org.springframework.security.web.savedrequest.RequestCacheAwareFilter#4420f4d4,
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter#517594dd,
org.springframework.security.web.authentication.AnonymousAuthenticationFilter#67231d8d,
org.springframework.security.web.session.SessionManagementFilter#59b5251d,
org.springframework.security.web.access.ExceptionTranslationFilter#7d6b0636,
org.springframework.security.web.access.intercept.FilterSecurityInterceptor#4b50ebea]
2021-04-08 08:58:47.883 WARN 3040 --- [ main]
ConfigServletWebServerApplicationContext : Exception encountered
during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'configSecurity' defined in class path
resource [it/config/SecurityConfig.class]:
Unsatisfied dependency expressed through method 'configSecurity'
parameter 0; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'org.springframework.security.config.web.server.ServerHttpSecurity'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations: {}
And:
APPLICATION FAILED TO START
Description: Parameter 0 of method configSecurity in
it.config.SecurityConfig required a bean of type
'org.springframework.security.config.web.server.ServerHttpSecurity'
that could not be found.
Action: Consider defining a bean of type
'org.springframework.security.config.web.server.ServerHttpSecurity' in
your configuration.
Do you know how to solve?
Below my dependecy:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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-oauth2-resource-server</artifactId>
</dependency>
Try annotating the class that bean is in with the following:
#Configuration
#EnableWebSecurity
Also, make sure that bean is public - see if all of those fix it? If not - could you provide a Full Stack-Trace of the exception.
Thanks, Ben
try adding all of these annotations at the top.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true, prePostEnabled = true)
Sometimes the #EnableGlobalMethodSecurity helps
I've solved using HttpSecurity instead of ServerHttpSecurity. Below my new code:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests(authorizeRequests -> authorizeRequests.anyRequest().authenticated()).oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
}
}

Spring project with aws cognito

I'm trying to use aws Cognito`s user authentication with my spring project. I configured Cognito and got a jwt token from it. When I pass the token to my api endpoint I'm getting error 401 (unauthorized).
I'm working on a ms that working in my localhost.
I saw a few examples and I feel like my application.properties is missing something but I'm not sure what.
My application properties :
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://cognito-idp.eu-west-2.amazonaws.com/eu-west-2_somecode
spring.security.oauth2.client.registration.app1.client-id=my_app_id_in_cognito
My pom has the following security dependencies :
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
<version>5.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
<version>5.3.3.RELEASE</version>
</dependency>
My configuration class :
#Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.anyRequest().authenticated().and()
.oauth2ResourceServer().jwt();
}
Tried also to change the application properties according to some spring examples :
spring.security.oauth2.client.registration.cognito.client-id=my_app_id_in_cognito
spring.security.oauth2.client.registration.cognito.client-name=app1
spring.security.oauth2.client.provider.cognito.issuer-uri=https://cognito-idp.eu-west-2.amazonaws.com/eu-west-1_somecode
but then I got the following exception because I was missing the spring.security.oauth2.resourceserver.jwt.jwk-set-uri settings in application.properties :
Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a bean of type 'org.springframework.security.oauth2.jwt.JwtDecoder' that could not be found.
The following candidates were found but could not be injected:
- Bean method 'jwtDecoderByIssuerUri' in 'OAuth2ResourceServerJwtConfiguration.JwtDecoderConfiguration' not loaded because OpenID Connect Issuer URI Condition did not find issuer-uri property
- Bean method 'jwtDecoderByJwkKeySetUri' in 'OAuth2ResourceServerJwtConfiguration.JwtDecoderConfiguration' not loaded because #ConditionalOnProperty (spring.security.oauth2.resourceserver.jwt.jwk-set-uri) did not find property 'spring.security.oauth2.resourceserver.jwt.jwk-set-uri'
- Bean method 'jwtDecoderByPublicKeyValue' in 'OAuth2ResourceServerJwtConfiguration.JwtDecoderConfiguration' not loaded because Public Key Value Condition did not find public-key-location property
Action:
Consider revisiting the entries above or defining a bean of type 'org.springframework.security.oauth2.jwt.JwtDecoder' in your configuration.
What am I missing ?
I found this article and tried to use the same setting in the application.properties :
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://cognito-idp.{REGION}.amazonaws.com/{POOL_ID}

Keycloak: Failed to load URLs in Spring Boot Application

I'm currently trying to develop a Spring Boot Rest Api which is secured with keycloak.
I get an error when I try to call a api which the user has to be identify.
The error message is following:
2020-04-10 16:09:00.324 WARN 44525 --- [nio-8080-exec-7]
o.keycloak.adapters.KeycloakDeployment : Failed to load URLs from
https://{{keycloakserver}}.de/auth/realms/{{realm}}/.well-known/openid-configuration
java.lang.RuntimeException: java.lang.RuntimeException: Stub!
at org.keycloak.adapters.KeycloakDeployment.getClient(KeycloakDeployment.java:327) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.KeycloakDeployment.getOidcConfiguration(KeycloakDeployment.java:219) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.KeycloakDeployment.resolveUrls(KeycloakDeployment.java:178) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.KeycloakDeployment.getRealmInfoUrl(KeycloakDeployment.java:232) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.rotation.AdapterTokenVerifier.createVerifier(AdapterTokenVerifier.java:107) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.rotation.AdapterTokenVerifier.verifyToken(AdapterTokenVerifier.java:47) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.BearerTokenRequestAuthenticator.authenticateToken(BearerTokenRequestAuthenticator.java:103) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.BearerTokenRequestAuthenticator.authenticate(BearerTokenRequestAuthenticator.java:88) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.RequestAuthenticator.authenticate(RequestAuthenticator.java:67) [keycloak-adapter-core-9.0.2.jar:9.0.2]
at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.attemptAuthentication(KeycloakAuthenticationProcessingFilter.java:154) [keycloak-spring-security-adapter-9.0.2.jar:9.0.2]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96) [keycloak-spring-security-adapter-9.0.2.jar:9.0.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:97) [spring-web-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.1.10.RELEASE.jar:5.1.10.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
I don't know what Failed to load URLs from means. I can access this side when I click on the link and the configuration file is shown.
Setup
Keycloak:
Keycloak Server is in the web, so no localhost.
I have a realm (test-realm) created
I have a client (test-client) created
I have a user (test-user) created
I have a role in the client (ADMIN) created
I have assigned the role (ADMIN) to the user (test-user)
The client protocol for the client is openid-connect and the access type is confidental.
Spring Boot:
The Spring Boot rest application is running on localhost:8080.
I added in the applications.properties following keycloak configs.
keycloak.realm={{test-realm}}
keycloak.auth-server-url = https://{{keycloakserver}}.de/auth
keycloak.resource = {{test-client}}
keycloak.ssl-required=external
keycloak.bearer-only=true
keycloak.principal-attribute=preferred_username
keycloak.use-resource-role-mappings = true
To make sure the test-user can only access one api call I use following config.
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/getTest")
.hasRole("ADMIN")
.anyRequest()
.authenticated();
}
Tests
When I call http://localhost:8080/getTest with Postman I get a correct 401 Unauthorized.
Then I called the same URL with Authorization and the access token of the logged in test-user.
With this second call I get the error message above.
Does anybody know anything about this?
If I missed a config value that you need to know, just ask.
Thanks for your help.
Edit:
SecurityConfig.java
import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springboot.KeycloakSpringBootProperties;
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
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.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
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;
/**
* Created by johannes on 07.04.20 for test App.
*/
#EnableWebSecurity
#ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
#Configuration
#KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
auth.authenticationProvider(keycloakAuthenticationProvider);
}
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(
new SessionRegistryImpl());
}
#Bean
#Primary
public KeycloakConfigResolver keycloakConfigResolver(KeycloakSpringBootProperties properties) {
return new CustomKeycloakSpringBootConfigResolver(properties);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/getTest")
.hasRole("ADMIN")
.anyRequest()
.authenticated();
}
}
CustomKeycloakSpringBootConfigResolver:
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springboot.KeycloakSpringBootProperties;
import org.springframework.context.annotation.Configuration;
/**
* Created by johannes on 10.04.20 for test App.*/
#Configuration
public class CustomKeycloakSpringBootConfigResolver extends KeycloakSpringBootConfigResolver {
private final KeycloakDeployment keycloakDeployment;
public CustomKeycloakSpringBootConfigResolver(KeycloakSpringBootProperties properties) {
keycloakDeployment = KeycloakDeploymentBuilder.build(properties);
}
#Override
public KeycloakDeployment resolve(HttpFacade.Request facade) {
return keycloakDeployment;
}
}
TestController.java (this is just the test getter):
#GetMapping("/getTest")
public #ResponseBody ResponseEntity getTest() {
return ResponseEntity.status(ResponseValues.ITEMDELETEFAILED.getResponseCode()).body(ResponseValues.ITEMDELETEFAILED.getResponseMessage());
}
Request was made with postman, this is the code:
curl --location --request GET 'http://localhost:8080/getTest' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUI...' \
--header 'Cookie: JSESSIONID=41E8E82178FA181817...'
In my case: Realm name was not correct. It is case sensitive. It worked when I change it to:
keycloak.realm = demo
I had written
keycloak.realm = Demo
I have the same problem, and I try a lot to find the answer at google, stackoverflow etc...
Finally, I catch the clue, to make it work, just remove the path of the keycloak.auth-server-url as http://192.168.0.119:8080 instead of http://192.168.0.119:8080/auth or something else.
... : Loaded URLs from http://192.168.0.119:8080/realms/spmia-realm/.well-known/openid-configuration
keycloak.realm=spmia-realm
keycloak.auth-server-url=http://192.168.0.119:8080
keycloak.ssl-required=external
keycloak.resource=ostock
keycloak.credentials.secret=FnUBprsgArHa7PkmR9HPWeXY0nJ22Ks1
keycloak.use-resource-role-mappings=true
keycloak.bearer-only=true
...
keycloak:
image: quay.io/keycloak/keycloak:18.0
restart: on-failure
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
KC_DB: postgres
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: keycloak
KC_DB_URL: jdbc:postgresql://database:5432/keycloak
command:
- "start-dev"
depends_on:
database:
condition: service_healthy
ports:
- "8080:8080"
...
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak.bom</groupId>
<artifactId>keycloak-adapter-bom</artifactId>
<version>18.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
...
I had the same issue, for me it was also connected to a flawed config value.
keycloak.auth-server-url = https://{{keycloakserver}}.de/auth
First I forgot the /auth and then I used http instead of https.
I have been through this issue and solved it as follows
1- make sure of your yaml or properties file in the spring boot application
the following property should be configured based on the keycloak version you use. in my case i used v 17.0.1 and the issue arose because i added it this way
keycloak.auth-server-url=http://localhost:8080/auth rather than this keycloak.auth-server-url=http://localhost:8080
but if you use a lower version than 17 it must be
keycloak.auth-server-url=http://localhost:8080/auth
please make sure that you mentioned the right host and the right port,i just mentioned localhost and the port 8080 because this my case.
I solved the Issue own my own.
I noticed that my spring boot sdk was a android sdk. I don't know how this could happen.
I changed it to the java sdk, and it worked like a charm.
I had a similar issue. In my case, I didn't recognize that there was a single whitespace at the end of my "keycloak.auth-server-url" in my application.properties file.
This way, the keycloak adapter tried to access an invalid URL.
Maybe this helps someone who has a similar issue and finds this thread.
try to change hasRole to hasAuthority or add prefix ROLE_ before the role like this hasRole("ROLE_ADMIN")
I had entered the wrong value for keycloak.auth-server-url.

Spring Security with Spring Boot

I am trying to create a Spring Boot REST application. When I deploy my application, it authentication is required and it is asking me for user name and password. How can I bypass this or how can I add a user name and password for authentication?
Do I need to remove security entry in pom?
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
If you don't want to use authentication at all, you should remove the dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
See Spring Boot Reference Guide:
If Spring Security is on the classpath then web applications will be secure by default with ‘basic’ authentication on all HTTP endpoints.
No need of removing security from pom.xml. In your project, you can try something like below. Try to create SecurityConfig which will extend WebSecurityConfigurerAdapter and provide some user name and password and later you can customize it.
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("user")
.roles("USER")
.and()
.withUser("user2")
.password("secret2")
.roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().fullyAuthenticated();
http
.httpBasic();
http
.csrf().disable();
}
}
public #interface EnableWebMvcSecurity {
}
Apart from other two answers - default username is 'user' and password will be printed in the console each time you start your server like below -
2019-08-31 23:58:16.417 INFO 12528 --- [ restartedMain] .s.s.UserDetailsServiceAutoConfiguration :
Using generated security password: 1ab46edf-332a-42de-ae11-70dc138c65db
Simply use these credentials to login.
Note - If you fine-tune your logging configuration, ensure that the org.springframework.boot.autoconfigure.security category is set to log INFO-level messages. Otherwise, the default password is not printed.
if you wish to configure a username/password of your choice then you can do so in application.properties file.
spring.security.user.name=username
spring.security.user.password=password
Now spring security will not generate a new password each time you boot the application.
Note: When using postman to send requests, go to authorization> select "basic auth"> Enter the username and password so authentication details can be sent along with each request. If using browser, there should be a login page.

Resources