How to do LDAP authentication on Post Request - spring-boot

For my application, I use Spring boot and LDAP to authentication user. And I have Spring Security to control the API.
Basically what I do is to attach the Authentication: basic on the header and call the get user api(/user, get mapping) to get the user details. From there I return the pricinpal and use the user session to access the application.
#GetMapping("/user")
public Principal user(Principal user) {
return user;
}
My question is how to do authencation on post? Same header with authentication, but the only difference is /user endpoint will be post mapping. From postman I got 401 error. Somehow LDAP isn't picking up the authentication header to do authentication.
#PostMapping("/user")
public Principal user(Principal user) {
return user;
}
Please Help. And Thanks in advance.

Related

How can I implement access tokens for a public Spring Boot API?

I have a public facing API created with Spring Boot. I want users of the API to include a token with requests so that I can ensure they are allowed to access it and also track how many requests are made within a certain period of time.
I'm a little confused on how to approach this because everything I am reading online is where a user sends their user/password and the application returns a token. This is not what I'm looking for.
I want something similar to when you use Google APIs or similar APIs where your token never changes unless you want it to change and you do not send Google API your user/pass on the first request.
Maybe I'm not using the correct terminology. Can someone point me in the right direction?
If you want to authenticate using a static token for each user you will have to create a custom AuthenticationManager that gets your request header and tries to match it aginst known keys.
Example using single key, you'd have to add a lookup to user table if needed
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception
{
http.authorizeRequests(auth -> auth
.anyRequest().authenticated());
http.addFilter(tokenFilter());
http.csrf().disable();
return http.build();
}
public Filter tokenFilter()
{
AuthenticationTokenFilter filter = new AuthenticationTokenFilter(authenticationTokenHeader);
filter.setAuthenticationManager(authenticationManager());
return filter;
}
protected AuthenticationManager authenticationManager()
{
final AuthenticationManager authenticationManager = new AuthenticationManager()
{
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
{
String principal = (String) authentication.getPrincipal();
if (!authenticationTokenValue.equals(principal))
{
throw new BadCredentialsException("The API key was not found or not the expected value.");
}
authentication.setAuthenticated(true);
return authentication;
}
};
return authenticationManager;
}
Do keep in mind that this approach is not the most secure, and if you'r application is public facing I would not recommend using this. And would recommend either using Authorization header with username/password or JWT
As a side note, I think you'r mistaken on how the google API authenticates. To the best of my knowledge all google APIs use Oauth2 for authentication, the static key/file you have does not provide access to the API it is only good for retrieving a short lived access token, in essence this would be not much different from standard JWT where you use some form of credentials to get a token with which you access the API.
for more info on JWT authentication:
https://www.baeldung.com/spring-security-oauth-jwt
https://blog.softtek.com/en/token-based-api-authentication-with-spring-and-jwt

Is it good idea to take user id from SecurityContextholder in spring boot RestController..?

I am developing spring boot rest application for an ecommerce app, suppose i have endpoint /shipping-address which will fetch all the saved addresses for the user, is it good idea to take user id from SecurityContextHolder like
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Long userId;
if (principal instanceof UserPrincipal) {
userId = ((UserPrincipal) principal).getId();
}
or should i pass from the client side in the request body..? which is correct..? If i take from SecurityContextHolder is it problem when it comes to Horizontal scaling..??
Please help, i am new to backend development. Thanks.
Taking the userId from the SecurityContext is a good idea because it will prevent from hacking your application.
If you pass the userId from the client somebody could intercept the request and change the userId.
In regards to scaling it depends how you authenticate the user. If it's basic or token based and does not rely on session information. Everything will be fine.
SecurityContext
There is no problem in using a SecurityContext with Spring MVC.
You could use something like :
#RestController
#RequestMapping(path = "/auth")
#Slf4j
public class AuthResource {
#GetMapping(path = "whoami", produces = MediaType.APPLICATION_JSON_VALUE)
#PreAuthorize("isAuthenticated()")
public ResponseEntity<String> whoami(#AuthenticationPrincipal() UserDetails userDetails) {
String login = userDetails.getUsername();
return ResponseEntity.ok(login);
}
}
The annotation #AuthenticationPrincipal from Spring Security will simplify your code.
Session storage
By default, the session will be backed by the HttpSession (cookie JSESSIONID).
So you'll need something like sticky sessions if using a load balancer.
However, sessions can be stored elsewhere, like in relational databases (JDBC) or in Redis : this is what Spring Session can do.
See also Control the Session with Spring Security.
You can also choose to not use sessions with Spring Security :
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

How to have Spring Security enabled for an application using third party login?

I have a Spring Boot enabled application whose login is controlled by third party Siteminder application. After successful authentication, Sitemeinder redirects to our application url. We fetch the HttpRequest from Siteminder and process the requests.
Now, how can Spring security be enabled in this case for authorizing users based on roles.
#Controller
public class LoginController
#RequestMapping( value= "/")
public void requestProcessor(HttpServletRequest request)
{
.
.
.}
The above controller's request mapper reads the request coming from SiteMinder and processes the request which has the Role of the user logged in. Where can we have Spring Security enabled to authorize pages and service methods to the user.
This is an scenario for the PreAuthenticated security classes:
Take a look here:
http://docs.spring.io/spring-security/site/docs/current/reference/html/preauth.html
Spring Security processes request before it gets to your controller in a filter configured in spring security configuration.
There is a documentation on how to configure spring security with SiteMinder.
The rules in your configuration will define the access to resources
Depends what you get in session. If somehow u can to take user and password from session you can authenticate user directly from code as :
#Autowired
AuthenticationManager authenticationManager;
...
public boolean autoLogin(String username, String password) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
Authentication auth = authenticationManager.authenticate(token);
if (auth.isAuthenticated()) {
logger.debug("Succeed to auth user: " + username);
SecurityContextHolder.getContext().setAuthentication(auth);
return true;
}
return false;
}

How to validate a token from a OAuth server?

I created a Spring Boot application where I have the authorization and resource server, this is my main class:
#SpringBootApplication
#EnableResourceServer
#EnableAuthorizationServer
public class OauthServerApplication {
public static void main(String[] args) {
SpringApplication.run(OauthServerApplication.class, args);
}
}
And this is my application.yml:
security:
user:
name: guest
password: guest123
oauth2:
client:
client-id: trustedclient
client-secret: trustedclient123
authorized-grant-types: authorization_code,refresh_token,password
scope: openid
To generate the access token I only execute this url (POST):
http://trustedclient:trustedclient123#localhost:8080/oauth/token?username=guest&password=guest123&grant_type=password
It returns:
{
"access_token": "f2e722b7-3807-4a27-9281-5b28b7bd3d0d",
"token_type": "bearer",
"refresh_token": "f96d472c-8259-42e2-b939-4963dfeeb086",
"scope": "openid"
}
Now I need to know how to validate if the token is correct, any help?
You have multiple possibilities, you can:
1) Store the token in a TokenStore and open a secured validate token enpoint on the authorization server for the resource server.
2) If the authorization server and the resource server can share a DataSource, (in your case it's easy because both are in the same application). They can both use a JdbcTokenStore pointing to the same database and the resource server can directly check the validity of a token in this token store. See this tutorial : Spring REST API + OAuth2 + AngularJS
3) You can use signed JWT tokens with JwtTokenStore and JwtAccessTokenConverter. See this tutorial : Using JWT with Spring Security OAuth
Both of these tutorials are based on the following github repository : https://github.com/Baeldung/spring-security-oauth
To validate the token I typically make a request for the /user using access token in the Authorization header.
In the Spring Oauth server I add the following endpoint.
#GetMapping("/user")
public Principal user(Principal user) {
return user;
}
And this would be the request sent to it.
GET http://localhost:8443/v1/auth/user
Authorization: Bearer some-access-token
This has the added benefit of returning the user object, which is typically needed. So kill two birds with one stone.

Getting Basic Authentication Headers Springboot

I am using Spring boot for my application with Basic Authentication for the rest api.
I would like to get the username and password of the request being authenticated to do some more fine grained authorization tasks. How can I process the HttpHeaders to get the details?
You can use the #AuthenticationPrincipal annotation, to get the logged in user as a parameter for your controller function.
#RequestMapping(method = RequestMethod.GET, consumes="application/json")
public ResponseEntity<> searchMeta(#AuthenticationPrincipal UserModel activeUser) {
//Do your processing with the UserModel
}

Resources