How to disable security on management port in Spring Boot 2 - spring

I have the /actuator/ Endpoints (in my case manage) on Port 6565. Is it possible to disable Security in Spring Boot 2 only for a specific port? At the moment I can only exclude certain paths from security. That would be insecure if I now run Enpoints under the main application port 1337 under /manage/. In the past we used management.security.enabled: false or was that path related too?
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/manage/**").permitAll()
.anyRequest().authenticated().and().httpBasic().realmName("Hay, the Config Server is here");
}
}
application.yml
spring:
cloud:
config:
server:
git:
uri: https://bitbucket.xxx.net/scm/gpi/springconfiguration.git
username: xxx
password: xxx
searchPaths: application-*
force-pull: true
security:
user:
name: xxxUser
password: xxx
server:
port: 1337
address: 0.0.0.0
management:
server:
port: 6565
metrics:
export:
prometheus:
enabled: true
endpoints:
web:
exposure:
include: '*'
base-path: /manage
endpoint:
prometheus:
enabled: true

I ended up with this as a working solution found here How can I tell spring security to apply authorizeRequests just for a specific port?
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Value("${management.server.port}")
private int managementPort;
#Value("${server.port}")
private int apiPort;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.requestMatchers(forPortAndPath(managementPort, "/manage/**")).permitAll()
.anyRequest().authenticated().and().httpBasic().realmName("Hay, the Config Server is here");
}
private RequestMatcher forPortAndPath(final int port, final String pathPattern) {
return new AndRequestMatcher(forPort(port), new AntPathRequestMatcher(pathPattern));
}
private RequestMatcher forPortAndPath(final int port, final HttpMethod method,
final String pathPattern) {
return new AndRequestMatcher(forPort(port), new AntPathRequestMatcher(pathPattern, method.name()));
}
private RequestMatcher forPort(final int port) {
return (HttpServletRequest request) -> port == request.getLocalPort();
}
Another Solution is to add the paths to the WebSecurity
#Value("${management.server.port:6565}")
private int managementPort;
#Value("${management.endpoints.web.base-path:/manage}")
private String managementPath;
#Override
public void configure(WebSecurity web) {
if (securityConfiguration.getAuthenticationScenario()
.equals(HwlPortalAuthenticationScenario.DISABLE_SECURITY)) {
web.ignoring().antMatchers("/**");
} else {
web.ignoring().antMatchers(securityConfiguration.securityDisabledPaths().toArray(new String[]{}))
.requestMatchers(forPortAndPath(managementPort,managementPath + "/**"));
}
}

Related

OAuth2 with Google and Spring Boot - I can't log out

I've been trying to get a successful Oauth2 login with Google and Spring Boot for a while now. This only works partially. Why partly - because I can't manage the logout or when I pressed the logout button I see an empty, white browser page with my URL (http://localhost:8181/ben/"). After a refresh of the page I get error from google, but if I open a new tab, enter my url, I'm still logged in to google, because I can see my user, which I'm outputting to my react application.
#SpringBootApplication
#EnableOAuth2Sso
#RestController
#CrossOrigin
public class SocialApplication extends WebSecurityConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(SocialApplication.class, args);
}
#RequestMapping("/user")
public Principal user(Principal principal) {
return principal;
}
#RequestMapping("/logout")
public String fetchSignoutSite(HttpServletRequest request, HttpServletResponse response) {
Cookie rememberMeCookie = new Cookie("JSESSIONID", "");
rememberMeCookie.setMaxAge(0);
response.addCookie(rememberMeCookie);
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
new SecurityContextLogoutHandler().logout(request, response, auth);
}
auth.getPrincipal();
return "redirect:/ben/login";
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests().antMatchers("/ben/*").permitAll().anyRequest().authenticated().and()
.logout().logoutSuccessUrl("http://localhost:8181/ben/login").invalidateHttpSession(true)
.clearAuthentication(true).deleteCookies("JSESSIONID");
}
My application.yml file looks like this:
# Spring Boot configuration
spring:
profiles:
active: google
# Spring Security configuration
security:
oauth2:
client:
clientId: 415772070383-3sapp4flauo6iqsq8eag7knpcii50v9k.apps.googleusercontent.com
clientSecret: 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
accessTokenUri: https://www.googleapis.com/oauth2/v4/token
userAuthorizationUri: https://accounts.google.com/o/oauth2/v2/auth
clientAuthenticationScheme: form
scope:
- email
- profile
resource:
userInfoUri: https://www.googleapis.com/oauth2/v3/userinfo
preferTokenInfo: true
# Server configuration
server:
port: 8181
servlet:
context-path: /ben
That fetchSignoutSite only emptying the JsessionId and logging out from Spring Security context. So you would still need to add part where you go to google and sign out from there which I have no experience on implementation.

Spring Boot I can't switch keycloak and basic authentication

NB: I'm using Spring Boot 2.1.10 and Keycloak 6.0.1
I wish I could choose between basic authentication and SSO at launch time for a web application (MVC).
So I first integrated Spring Security + Keycloak with keycloak-spring-boot-starter
#SpringBootApplication
#EnableWebSecurity
public class KcApplication {
public static void main(String[] args) {
SpringApplication.run(KcApplication.class, args);
}
}
Then I defined a "sso" Spring profile and a default config:
application.properties goes like this:
spring.application.name=#artifactId#
server.port: 8081
keycloak.enabled=false
spring.main.allow-bean-definition-overriding: true
and application-sso.yml goes like this:
keycloak:
enabled: true
auth-server-url: http://localhost:8180/auth
realm: SpringBootRealm
resource: spring-app
credentials:
secret: 0c8940a4-2065-4810-a366-02877802e762
principal-attribute: preferred_username
Then I got two different security configurers:
#Configuration #Profile("!sso")
public class BasicAuthConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/customers*").authenticated()
.anyRequest().permitAll()
.and().httpBasic() //DEBUG can't force
.and().logout().logoutSuccessUrl("/");
}
}
#Configuration #Profile("sso")
#ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public class KeycloakAuthConfig extends KeycloakWebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/customers*").authenticated()
.anyRequest().permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider authProvider = keycloakAuthenticationProvider();
authProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(authProvider);
}
#Bean
public KeycloakSpringBootConfigResolver keycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
}
Everithing launches smoothly in both cases, and the "sso" profile behaves rightly: entering the /consumers path first turns to a redirection to Keycloak and coming back when authenticated.
But I can't get the default profile to log me in. When entering /consumers I get an anonymousUser, not being asked to form login.
I guess that the issue comes from something I missed, so I put above as many things as possible. Does anyone knows why I can't login, despite the fact that the right configurer was run at debug?
Thank you
Well, it took the weekend for the session to be reset, then it worked!
Proof that it's probably the logout that bugs instead... I'm not even sad :-(

Spring Gateway on localhost:8000

Running a service on localhost:8000. I route to it with Spring Gateway and only get a white page instead of the login page of the service.
I've tried routing using java, and also through a yml file.
Java
#SpringBootApplication
public class GsGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GsGatewayApplication.class, args);
}
#Bean
public RouteLocator myRoutes(RouteLocatorBuilder builder){
return builder.routes()
.route(p->p
.path("/get")
.uri("localhost:8000/login"))
.build();
}
}
application.yml
server:
port: 8080
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: weblogin
uri: localhost:8000/login
predicates:
- Path=/get
I expect a login page, but get only a blank white page.
By your configuration, when you access localhost/get you will be route to localhost:8080/get

SpringBoot2 OAuth2 AuthorizationServer's Login Page is shown infinitely loop after login

I'm implemention OAuth2 System with Spring Boot 2.1.4 and Spring Security OAuth2.
I want to separate All Components Client, ResourceServer, AuthorizationServer)
so i create 3 projects each git repository.
in Client, I requested protected URL.
and Spring Security redirected me to Authorization Server's /oauth/authorize, and i redirected to Authorization Server's login page.
i tried login, and success.
and i redirected to my Client and redirected again to AuthorizationServer's login page agian. (infinitely loop)
following is my 3 Components(Client, AuthorizationServer, ResourceServer)' Configuration.
Client
gradle
plugins {
id 'org.springframework.boot' version '2.1.4.RELEASE'
id 'java'
}
...
dependencies {
...
/** Spring Security **/
implementation 'org.springframework.boot:spring-boot-starter-security'
// https://mvnrepository.com/artifact/org.springframework.security.oauth.boot/spring-security-oauth2-autoconfigure
compile group: 'org.springframework.security.oauth.boot', name: 'spring-security-oauth2-autoconfigure', version: '2.1.4.RELEASE'
// https://mvnrepository.com/artifact/org.springframework.security/spring-security-oauth2-client
compile group: 'org.springframework.security', name: 'spring-security-oauth2-client', version: '5.1.5.RELEASE'
}
application.yml
...
spring:
security:
oauth2:
client:
provider:
teemo:
authorizationUri: http://localhost:8082/oauth/authorize
tokenUri: http://localhost:8082/oauth/token
userInfoUri: http://localhost:8081/me
registration:
teemo:
clientId: foo
clientSecret: bar
provider: teemo
authorizationGrantType: authorization_code
redirectUri: http://localhost:8080/oauth2/authorization/teemo
...
WebSecurityConfigurerAdapter config
#Configuration
#EnableOAuth2Client
public class WebSecurityConfigurerAdapterImpl extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/", "/home", "/error", "/webjars/**", "/resources/**", "/login**").permitAll()
.anyRequest().authenticated()
.and().oauth2Login();
}
}
AuthorizationServer
gradle
plugins {
id 'org.springframework.boot' version '2.1.4.RELEASE'
id 'java'
}
...
dependencies {
...
/** Spring Security **/
implementation 'org.springframework.boot:spring-boot-starter-security'
// https://mvnrepository.com/artifact/org.springframework.security.oauth.boot/spring-security-oauth2-autoconfigure
compile group: 'org.springframework.security.oauth.boot', name: 'spring-security-oauth2-autoconfigure', version: '2.1.4.RELEASE'
...
}
application.yml
spring:
security:
user:
name: user
password: user
...
WebSecurityConfigurerAdapter config
#Configuration
public class WebSecurityConfigurerAdapterImpl extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/oauth/authorize", "/oauth/token", "/login**").permitAll()
.and().formLogin().permitAll();
}
}
AuthorizationServerConfigurerAdapter config
#Component
#EnableAuthorizationServer
public class AuthorizationServerConfigurerAdapterImpl extends AuthorizationServerConfigurerAdapter {
private AuthenticationManager authenticationManager;
public AuthorizationServerConfigurerAdapterImpl(AuthenticationConfiguration authenticationConfiguration) throws Exception {
this.authenticationManager = authenticationConfiguration.getAuthenticationManager();
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("foo")
.secret("bar")
//.authorities("USER")
.authorizedGrantTypes("authorization_code", "implicit", "refresh_token")
.autoApprove(true)
.redirectUris("http://localhost:8080/oauth2/authorization/teemo")
.scopes("read");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)throws Exception {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
}
ResourceServer
gradle
plugins {
id 'org.springframework.boot' version '2.1.4.RELEASE'
id 'java'
}
...
dependencies {
...
/** Spring Security **/
implementation 'org.springframework.boot:spring-boot-starter-security'
// https://mvnrepository.com/artifact/org.springframework.security.oauth.boot/spring-security-oauth2-autoconfigure
compile group: 'org.springframework.security.oauth.boot', name: 'spring-security-oauth2-autoconfigure', version: '2.1.4.RELEASE'
// https://mvnrepository.com/artifact/org.springframework.security/spring-security-oauth2-resource-server
//compile group: 'org.springframework.security', name: 'spring-security-oauth2-resource-server', version: '5.1.5.RELEASE'
}
application.yml
...
security:
oauth2:
resource:
token-info-uri: http://localhost:8082/oauth/check_token
ResourceServerConfigurerAdapter config
#Configuration
#EnableResourceServer
public class ResourceServerConfigurerAdapterImpl extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/me").access("#oauth2.hasScope('read')");
}
#Primary
#Bean
public RemoteTokenServices tokenService() {
RemoteTokenServices tokenService = new RemoteTokenServices();
tokenService.setCheckTokenEndpointUrl("http://localhost:8082/oauth/check_token");
tokenService.setClientId("foo");
tokenService.setClientSecret("bar");
return tokenService;
}
}
and following is screenshot for infinitely looping after login.
infinitely image
how can i fix this? and i'm spring boot & security newbie.
There are several problems with your code. Among them:
You need to have a specific context path for each project (because the session tracking is cookie based and each session cookie must have a unique path)
There is no /me path mapping on resource server
The redirectUri should have the format <client_url>/login/oauth2/code/<provider_name>
I have made a pull request for each or your projects that fixed the issues.
For an example of OAUTH2 with String Boot take a look here
If you find something unclear with the modifications I have made, feel free to ask me.

Spring Boot OAuth2 - Could not obtain user details from token

I searched the web for solution of this problem but didn't find any working solution. I'm trying to setup basic Spring Boot OAuth2 Authorization Provider and Client.
I followed official Spring Boot instructions and created single sign on with Facebook and Github. Then i followed instructions to create Secure Spring Boot Web application.
I wanted to create my own Authorization Server so I added #EnableAuthorizationServer annotation to Secure Web Application as explained here. I also added details of an OAuth2 client as described in a link. I followed further instructions and created a OAuth2 Client.
I start both applications, visit 127.0.0.1:9999 to open a Client, client redirects me to localhost:8080/login, I enter user details and Authentication Provider redirects me to 127.0.0.1:9999/login and I get an error message:
Authentication Failed: Could not obtain user details from token
This is what gets logged:
INFO 2800 --- [nio-9999-exec-3] o.s.b.a.s.o.r.UserInfoTokenServices : Getting user info from: http:// localhost:8080/me
DEBUG 2800 --- [nio-9999-exec-3] o.s.s.oauth2.client.OAuth2RestTemplate : Created GET request for http:// localhost:8080/me
DEBUG 2800 --- [nio-9999-exec-3] o.s.s.oauth2.client.OAuth2RestTemplate : Setting request Accept header to [application/json, application/*+json]
DEBUG 2800 --- [nio-9999-exec-3] o.s.s.oauth2.client.OAuth2RestTemplate : GET request for http:// localhost:8080/me resulted in 200 (OK)
INFO 2800 --- [nio-9999-exec-3] o.s.b.a.s.o.r.UserInfoTokenServices : Could not fetch user details: class org.springframework.web.client.RestClientException, Could not extract response: no suitable HttpMessageConverter found for response type [interface java.util.Map] and content type [text/html;charset=UTF-8]]
This is my Client application:
#EnableAutoConfiguration
#Configuration
#EnableOAuth2Sso
#RestController
public class ClientApplication {
#RequestMapping("/")
public String home(Principal user) {
return "Hello " + user.getName();
}
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
This is client application YML:
server:
port: 9999
security:
oauth2:
client:
client-id: acme
client-secret: acmesecret
access-token-uri: http://localhost:8080/oauth/token
user-authorization-uri: http://localhost:8080/oauth/authorize
resource:
user-info-uri: http://localhost:8080/me
This is my Authorization Provider application:
#SpringBootApplication
public class SecurityApp {
public static void main(String[] args) {
SpringApplication.run(SecurityApp.class, args);
}
}
#Configuration
#EnableWebSecurity
#EnableAuthorizationServer
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/login").setViewName("login");
}
}
#RestController
public class Controller {
#RequestMapping({ "/user", "/me" })
public Map<String, String> user(Principal principal) {
Map<String, String> map = new LinkedHashMap<>();
map.put("name", principal.getName());
return map;
}
}
This is Application Provider YML:
security:
oauth2:
client:
client-id: acme
client-secret: acmesecret
scope: read,write
auto-approve-scopes: '.*'
I solved the issue! I was missing the Resource Server which handles the requests for user endpoint (user-info-uri). To the Authorization Provider application I added this class:
#Configuration
#EnableResourceServer
public class ResourceServer
extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/me")
.authorizeRequests().anyRequest().authenticated();
}
}
The user-info-uri should be in authorization server because all the accounts/users are in it.

Resources