Spring websocket (STOMP) registration - java

Good day! I have a simple chat with Spring websocket and STOMP.
In some examples I have seen authentication with spring-security-web and spring-security-config - something like
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
But the problem is - withUser("user") is hardcoded and method is called at whole system start up - what if I wand a dynamic user registration?
So the questions are:
1) How can I make dynamic registration? Something like :
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat", "/registration").withSockJS();
}
And do some #MessageMapping("/registration") ? and inside parce the message with registration data? I quess there is a better way...
2) After user registration from question 1 - how can I dynamically check if user is registered when he connects to web socket and prevent subscribing to my endpoints and sending messages if he is not?

Related

Spring Security - Wildcards/matchers in authorization rules

While configuring the security of my Spring Boot application, I wanted to secure parts of the API depending on the PathVariable that is entered there. My current configuration is as follows:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//not important
#Override
public void configure(HttpSecurity http) throws Exception {
http.cors();
http.authorizeRequests()
.mvcMatchers("/api").authenticated()
.mvcMatchers("/api/TEST").hasAuthority("SCOPE_dep:TEST")
.and().oauth2ResourceServer().jwt();
}
}
In the the 'api/{PathVariable}' endpoint is the one I want to have customized, making sure that someone with the authority 'SCOPE_dep:TEST' can access the 'api/TEST' endpoint, someone with 'SCOPE_dep:TEST2' authority can access the 'api/TEST2' endpoint, even allowing more then one such endpoint for a user which has multiple of these authorities.
Is there a way to do this by using a type of wildcard/matcher that I'm unaware of, or is the only possiblity hardcoding all these different authorities?

What is the purpose of AuthenticationManagerBuilder in Oauth2 resource server

So I have this application that only allow access to its resource when a valid oauth token is provided. I already have an #EnableResourceServer class that handles role based access to different endpoints. But what is the purpose of the block of code below? My app would not start unless I put in this generic block with some generic user name/password. The user/role/password here has no bearing on accessing the resource whatsoever. As long as the role in the oauth token matches the role specified in the #EnableResourcesServer, the caller will get proper response back from the app.
#EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.inMemoryAuthentication() // creating user in memory
.withUser("user")
.password("password").roles("USER")
.and().withUser("admin")
.password("password").authorities("ROLE_ADMIN");
}
}
I found the issue, it was because I separated the access of resources in 2 classes, an #EnableResourceServer and an #EnableWebsecurity. The issue is resolved after removing the #EnableWebSecurity class and moving all access control to #EnableResourceServer.

How to set default #AuthenticationPrincipal on startup

For development purpose, I am trying to configure a development profile for which developers don't need to be authenticated in the application to call REST services.
But, some of these services need an #AuthenticationPrincipal to work.
So I would like to be able to define a mocked #AuthenticationPrincipal on startup to be used by default.
Does anyone have any kind of idea to do so?
Currently the application behavior expected for the user authentication is:
A REST endpoint should send a HTTP code 401 if the user isn't authenticated.
In this case, the Front-end should redirect the user to the back-end URL /login so that he can authenticate itself.
On success, the back-end should then redirect the user to the front-end.
It turn out that it wasn't a good solution, here a list of the different reasons I can think of:
The behavior of the back-end server would be different between the development and the production environments.
This would force the front-end to also have different behaviors between these two environments.
JUnits wouldn't be able to test all expected answers (example: HTTP code 401 if not authenticated) from endpoints.
So in place, I have created a security configuration (enabled only when not using the production profile) emulating the expected behavior from the front-end point of view.
Here the MockAuthenticationSecurityConfiguration class:
#Configuration
#Profile("!PRODUCTION")
public class MockAuthenticationSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final ApplicationProperties applicationProperties;
public MockAuthenticationSecurityConfiguration(final ApplicationProperties applicationProperties) {
this.applicationProperties = applicationProperties;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("swagger-ui.html").permitAll();
// All API REST endpoint can only be accessed by an authenticated user.
http.authorizeRequests().antMatchers("/api/**").authenticated()
// For these REST endpoint to answer HTTP code 401 in place of redirecting the user to /login.
.and().exceptionHandling().defaultAuthenticationEntryPointFor(new Http401UnauthorizedEntryPoint(), new AntPathRequestMatcher("/api/**"))
// On success, we want to redirect the user to a specific URL (the frontend).
.and().formLogin().permitAll().successHandler(new SimpleUrlAuthenticationSuccessHandler(applicationProperties.getRedirectUrl()))
.and().logout().permitAll()
;
http.csrf().disable();
http.cors();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// Add a mocked user to be used to authenticate.
auth.inMemoryAuthentication().withUser(User.withDefaultPasswordEncoder().username("jdoe").password("jdoe").roles("USER"));
}
}
Here the Http401UnauthorizedEntryPoint class:
public class Http401UnauthorizedEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
}
}
And then the ApplicationProperties class:
#Getter
#Setter
#Component
#ConfigurationProperties("application")
public class ApplicationProperties {
/**
* The URL to which we should redirect the user once he is logged in the application.
*/
private String redirectUrl;
}

Spring Security Java Config without Forcing Auth

I am having a difficult time figuring out how to wire up spring security without forcing authentication. My specific app does not require the user to authenticate but the user can authenticate if they want.
I currently have a WebSecurityConfigurerAdapter set up that you can see at the end of this post. With this setup I'm getting a 403 on all /api/* requests and /j_spring_security_check.
Could someone please help me either fix my existing config or point me to a working example that accomplishes this?
Every example I see out there seems to require the user to authenticate and if they don't it throws a 403. In my app, I'm just using it to establish a session and at this point all users should be able to access all end points regardless of if they are authenticated or not.
WebSecurityConfig
#EnableWebSecurity
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private ItAuthenticationProvider customAuthenticationProvider;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(customAuthenticationProvider);
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers("/**").permitAll()
.antMatchers("/j_spring_security_check").permitAll()
.and().formLogin()
.loginProcessingUrl("/j_spring_security_check")
.defaultSuccessUrl("/successful.html")
.loginPage("/#login")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/successful.html");
}
}
You can take a look at this sample Spring Security application we built with Stormpath support. In this example, the home screen does not require authentication. Furthermore, the information that is displayed there is dynamically calculated based on whether the user is authenticated or not.
If I understand your requirement, you can use the anonymous authentication.
The documentation can be found here

How to separate authorization server spring security in java

I have started to learn spring security (Oauth2). I am having a REST API service which is protected by Spring Oauth2. What i want to do is, I want to separate authorization server and resource server, For example,
I am having
Authorization: http://server1:8080/RESTTest/oauth/token/grant_type=client_credentials&client_id=clientt&client_secret=secret
And
Resource
http://server1:8080/RESTTest/api/users/?access_token=2cf682c6-2900-47dc-a468-441fcee0dc18
What i want is,
Authorization : http://Server1:8080/authorizationserver /oauth/token/grant_type=client_credentials&client_id=clientt&client_secret=secret
Resource:
http://server2:8080/RESTTest/api/users/?access_token=2cf682c6-2900-47dc-a468-441fcee0dc18
I am using JDBCTokenstore. I am not sure how to separate it. Can someone help me.
Thanks,
You can map your custom endpoint to defaults provided, fyi http://projects.spring.io/spring-security-oauth/docs/oauth2.html
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
.authenticationManager(authenticationManager);
endpoints.pathMapping("/oauth/token", "/authorizationserver/oauth/token")
}
}

Categories

Resources