How can i specify the user ID in the URL after the validation of the login spring security? - spring

i have been stuck in a problem usign spring security.
I need to specify the user id in the URL once he validates the login.
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests().antMatchers(HttpMethod.GET, "/users/?").authenticated().anyRequest().permitAll()
.and().formLogin().usernameParameter("email").defaultSuccessUrl("/user/**/pictures").permitAll()
.and().logout().logoutSuccessUrl("/").permitAll();
}
What i need is once the user enters the validated credentials,i want to appear his ID in the URL :

Related

Adding support for multi-tenancy in Spring Boot application using Spring Security

I am new to Spring Security and Oauth2. In my Spring Boot application, I have implemented authentication with OAuth2 for one tenant. Now I am trying to multi-tenancy in my Spring Boot application. From the answer to the previous post: OAUTH2 user service with Custom Authentication Providers, I have implemented two security configurations in order to support two tenants: Tenant1 and Tenant2 as follows:
Custom OAuth2 user service is as follows:
#Component
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
private UserRepository userRepository;
#Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
...
}
}
Tenant 1 security configuration is as follows:
#Configuration
public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final CustomOAuth2UserService customOAuth2UserService;
public SecurityConfiguration(CustomOAuth2UserService customOAuth2UserService) {
this.customOAuth2UserService = customOAuth2UserService;
}
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login**").permitAll()
.antMatchers("/manage/**").permitAll()
.antMatchers("/api/auth-info").permitAll()
.antMatchers("/api/**").authenticated()
.antMatchers("/management/health").permitAll()
.antMatchers("/management/info").permitAll()
.antMatchers("/management/prometheus").permitAll()
.antMatchers("/management/**").hasAuthority("ADMIN")
.antMatchers("/tenant1/**").authenticated()
.and()
.oauth2Login()
.userInfoEndpoint().userService(oauth2UserService());
http
.cors().disable();
}
private OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService() {
return customOAuth2UserService;
}
}
Tenant 2 security configuration is as follows:
#Order(90)
#Configuration
public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(new AntPathRequestMatcher("/tenant2/**"))
.csrf().disable()
.authorizeRequests()
.antMatchers("/tenant2/**").hasAuthority("USER")
.and()
.httpBasic();
http
.cors().disable();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("password")
.roles("USER");
}
}
application properties are as given below:
clientApp.name=myapp
spring.security.oauth2.client.registration.keycloak.client-id=abcd
spring.security.oauth2.client.registration.keycloak.client-name=Auth Server
spring.security.oauth2.client.registration.keycloak.scope=api
spring.security.oauth2.client.registration.keycloak.provider=keycloak
spring.security.oauth2.client.registration.keycloak.client-authentication-method=basic
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
myapp.oauth2.path=https://my.app.com/oauth2/
spring.security.oauth2.client.provider.keycloak.token-uri=${myapp.oauth2.path}token
spring.security.oauth2.client.provider.keycloak.authorization-uri=${myapp.oauth2.path}authorize
spring.security.oauth2.client.provider.keycloak.user-info-uri=${myapp.oauth2.path}userinfo
spring.security.oauth2.client.provider.keycloak.user-name-attribute=name
Basically, the intent of my application is B2B. So if I want to onboard a new business entity B as a tenant of my application, plugin its authentication provider, all its existing users should get authenticated seamlessly.
So, in view of the above, I have thought of the approach (though I am not sure if it's the best approach) as follows:
There can be a single endpoint for all the tenants i.e. there can be a common login page for all the users regardless of the tenant. On this login page, there can be the provision for the users to enter only email IDs.
The tenant ID can be determined from the email ID entered by the user.
Based on tenant ID, authentication provider of associated tenant ID gets invoked in order to authenticate the user of associated tenant.
On successful authentication, redirect to the home page for the associated tenant as: https://my.app.com/<tenant-id>/
In addition to the above, I would like to build a setup, where my application has quite a few, say, 40 tenants, out of which say 20 tenants use OAuth2, 10 uses basic auth and 10 uses form login.
Here in order to implement the above type of functionality, from Multi tenancy for spring security, it seems I have to support one authentication method, add tenant ID to authentication token and then create an adapter to other authentication methods, as needed.
But, in this regard, I did not find any concrete idea in any post so far on what changes should I do in the existing code base in order to achieve this.
Could anyone please help here?

Spring Security that needs username and password on every request

What I wanted to do is build a Rest backend application that needs the Authorization header on every request, validate and return the data or 401 Unauthorized if the user or password is wrong.
I have Spring Security in my classpath with this simple configuration:
#EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.withUser("user")
.password("pass")
.roles("USER");
}
}
But one thing is not working correctly: when I make a request with valid username and password with Postman, the server responds the data correctly, but if I change the password to a wrong password and keep the correct username, the server stills responds with the data and OK status, as if it is using a JSESSIONID Cookie to check the further requests.
Is that a way of using spring security only for checking the header Authorization (with no cookies, sessions nor saving user informations or login and logout pages), or is better to just use Filters for doing that instead?
Thank you for any help !
Just add the following to your configuration:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
}
This will configure spring security to never create a cookie, every request must reauthenticate.

How does spring boot authorisation and authentication work

I took over my current project from my colleague. And he is using Spring Boot. Now I wonder how login and Roles work. All I can see is namely this.
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
Environment env;
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/tester/**").hasAnyRole("TESTER", "AUTHOR", "ADMIN")
.antMatchers("/api/author/**").hasAnyRole("AUTHOR", "ADMIN")
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().fullyAuthenticated()
.and().
formLogin();
}
In the database there is a authorities table with a column authority. It seems Spring boot knows this and goes there. Also I found a login.html . It looks like also Spring Boot uses this automatically and provides appropriate attribute object ${param} . Also I cannot find a controller. URL to login is simply /login . If you were not using a framework then on every page you would need to check if user is currently logged in and has appropriate Role. So in user table you would have a column loggedIn and if loggedIn then you would set it to true. I suppose.

SpringBoot + Spring Security + LDAP login without UID

I am new to LDAP, and I am trying to figure out how to use spring security with ldap for login. All the examples/guides/tutorials that I read, are using the UID as a log in form. I have no UID.
This is the structure:
LDAP structure
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.userDnPatterns("mail={0},ou=group")
.groupSearchBase("ou=group")
.contextSource()
.url("ldap://localhost:8389/dc=ad,dc=company,dc=com")
.and()
.passwordCompare()
.passwordEncoder(new LdapShaPasswordEncoder())
.passwordAttribute("userPassword");
}
Here I tried to replace the UID with MAIL , but it does not work.
error:
Reason: Uncategorized exception occured during LDAP processing; nested exception is javax.naming.NamingException: [LDAP: error code 1 - 000004DC: LdapErr: DSID-0C0907C2, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v2580]; remaining name 'mail=erik.zs#mail.com, '
I hope someone knows how to add login without UID, thank you in advance.
Putting it into an answer, since it involves code blocks now, and these don't work well with the comments.
As discussed above in comments, your problem is that Spring uses LdapTemplate for LDAP access, which uses LDAP search for all authentication calls. Searching LDAP usually requires an admin account, called managerDn by the Spring LDAP classes. This managerDN is usually set when creating the LDAP context source. In your case, the methods to set it are provided by the contextSource() builder, to be set as follows:
auth.ldapAuthentication()
.userDnPatterns("mail={0},ou=group")
.groupSearchBase("ou=group")
.contextSource()
.managerDN("your admin account's Distinguished Name (DN)")
.managerPassword("password associated with your admin account")
.url("ldap://localhost:8389/dc=ad,dc=company,dc=com")
.and()
.passwordCompare()
.passwordEncoder(new LdapShaPasswordEncoder())
.passwordAttribute("userPassword");

Warn to user with message in session timeout in spring boot app 2.0

I want to display message to user as "Singed out because of inactive" in login page .
I tried the below code in spring security but its not effected .
sessionManagement().maximumSessions(1).expiredUrl("/login?expired") in httpsecurity.
After session timeout , simple its redirect to the /login only , did't get the expired value .
Using the below versions:
Spring boot 2.0
Spring security 5.0
This is just a snippet of my entire configuration, but this will check if the session has expired ONLY for authenticated users. When you use .maximumSessions(1) you are dealing with concurrent user management. That's not what you need.
In the following snippet, I check all incoming requests if they are authenticated .anyRequest().authenticated(). If the request is from an authenticated user (I don't check for roles) AND the session has timed out .sessionManagement().invalidSessionUrl(), redirect them back to the index page which has the login form.
#Configuration
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.sessionManagement().invalidSessionUrl("/?sessionexpired=true");
}
}

Resources