Spring boot LDAP auth in rest API without spring security - java

I have an API that is consumed by a mobile application that goes something like this:
#PostMapping("/myAPI")
public String getAgentProductsList(#RequestParam String username, #RequestParam String password, #RequestParam String productType) {
/*
here I need to verify the username and password in LDAP and retrieve the user's related data
*/
/*
some more code
*/
return "some products related to the user authenticated previously";
}
I need to do the authentication without using spring security or any redirection (that's what I've found in almost all the basic tutorial out there). So authenticating the username/password must happen inside the my endpoint.
That's my first time with LDAP so any helpful links or explinations is highly appreciated.

Related

How do I get the #AuthenticatedPrincipal from a web socket simpUser?

I'm trying to get logged in users' details who are connected via websocket on Spring Boot 2. To do this, I'm currently using SimpUserRegistry to find a list of connected SimpUsers.
Since Spring Boot 2.4, I noticed the SimpUser class has a getPrincipal() method that returns a generic Principal object. As each user is supposed to login via Spring Security's mechanisms, I thought I was able to cast it to Spring Security's UserDetails to get the logged in user , but I realize it wasn't the case.
Does anyone know how I can make use of getPrincipal or other ways to get logged in userDetails?
First of all, let's make it clear that, to use getPrincipal() with websocket, you have to implement websocket authentication and authorization through Interceptor (as far as I know SpringSecurity doesn't do this automatically).
After doing the above correctly, you can now use the getPrincipal () method. It will return The identity of the principal being authenticated (maybe Username, email,...)
You can use code that looks like this:
#MessageMapping("/test")
public void doSomething(#Payload AppMessage appMessage, Principal principal) {
String username = principal.getName();
// find userDetail with username here
}

Storing a JWT token

I am using JWT for authentication. Now i want to store this token which is being generated in one class, so that any other class can use it until the session expires. What is the best way to do it. My application is in spring boot.
Adding more. I am making a client which hits a rest webservice with the credentials to get the token. Now i need to store this token somewhere so that further rest requests can use it.
Is it fine to store the token in httpSession and retrieve it further.
Usually is not a good idea to store a JWT token, since it should contain all the information to identify and authorize a service user without hit the DB/persistence layer.
But maybe there are situations that require to persist it among user data. In this case you can store it in a table/collection and retrieve it while authenticating the user.
If you are using Spring + Spring Security, you can then populate a token field in a custom User implementation.
You can retrieve user data this way:
CustomUser userDetails = (CustomUser)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
It is not preferred to store a JWT token in order to protect it from CSRF.
But if you want to persist or use it anyways, one way in spring boot is you can just include the #RequestHeader parameter in any rest request with the value as "Authorization" and then you can just fetch out the jwt token from it and can use it as per your functionality :
#GetMapping("/abc")
public ResponseEntity<String> getToken(
#RequestHeader(value="Authorization") String authorizationHeader){
String jwt = authorizationHeader.substring(7);
//your functionality
return ResponseEntity.ok("JWT Token successfully retrieved");
}

ldap & JWT authentication without spring security

I'm trying to create a security module that will check against LDAP for user credentials (on login) and on successful login generate a JWT for further requests to the server.
currently my module works like this:
i have 3 rest API endpoints to provide authentication (login, validate JWT, logout) that are not protected as anyone must be able to access those endpoints,
and also 1 userUpdate endpoint protected with spring security via a JWTAuthenticationProvider
all the stuff pertaining the JWT is ready, now I just need to create a method to check in LDAP if the user and password are correct. but i am having some trouble understanding how am i supposed to do so
i already have the master user and pass to conect to ldap, but most of the examples i find about ldap authentication are with spring security and i dont think thats the way to do it in this case as i need to verify the matching us/pass only on login (and not protect my endpoints with security).
can anyone tell me how im supposed to do that verification? any stuff i am not being clear on? please ask and comment and answer.
thanks
oh one edit:
#Override
public AuthenticationResponse login(AuthenticationRequest authenticationRequest) {
checkNotNull(authenticationRequest, "The authenticationRequest is a required argument!");
AuthenticationResponse authenticationResponse = AuthenticationResponse.builder().build();
//currently a pseudo authentication, here is where i should authenticate against LDAP
Optional<Usuario> optionalUsuario = service.findByNombreUsuario(authenticationRequest);
if (optionalUsuario.isPresent()) {
Usuario usuario = optionalUsuario.get();
String token = JwtTokenUtil.generateToken(authenticationRequest);
authenticationResponse.setAuthenticationToken(token);
repository.saveToken(UserToken.builder()
.nombreUsuario(usuario.getNombreUsuario())
.roles(usuario.getRoles())
.build(), token);
as you can see i intent to make the authentication against ldap only at login, and only to check if the user and pass are correct, i will manage the roles and authorities using other DB
another edit: i have some basic ldap structure for ldap auth using spring security, but i always get bad credentials
edit again: i managed to make it work with spring security, but (as expected) was told by my team that we need to implement that authentication without spring security to integrate with our custom role loader and token creation
use http://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/ldap/authentication/LdapAuthenticationProvider.html to authenticate and get roles from LDAP, it should be done using spring security, I probably missed smth but could you explain why you don't want use it as far it is security standart

Rest Authentication - Token validation with a database look up Vs alternatives

I read through several q&a on stackoverflow for implementing rest authentication. And in one of those questions found a sample code as well.
https://github.com/philipsorst/angular-rest-springsecurity/blob/master/src/main/java/net/dontdrinkandroot/example/angularrestspringsecurity/rest/AuthenticationTokenProcessingFilter.java
Most of the answers talked about having an interceptor and filtering every request based on the auth header (a token and a user id or login id) and comparing it with the ones stored in the database.
I am implementing an Order management system.
And my url looks like http://myapi.com/customers/{customerId}/Orders/{OrderId}
Currently it is http and we're setting up the https soon.
In the URL, I get the customer ID and the order ID. I do a quick look up in the database with the order id and customer id and if it returns some rows, I return a JSON.
Questions I have:
To protect this endpoint, I can have a security interceptor. But every time I'll have to validate the request against the database. What are my alternatives (cache?) to validate or authorize each requests?
This rest end point is consumed by an android app(angular js)client and a website (a php client). For mobile, I should not re generate token each time the user logs in. So I have configured the token expiry to 30 days. However for the website, it is a session token. How should one handle this scenario?
What you need can be solved with Oauth.
Your backend (REST-API) will require authenticated access to your API operations. In turn, your clients/front-end will need to issue authenticated requests when communicating with the backend. This is achieved by sending access tokens.
Although this could seem complex, it will be very useful for you to take a look at Stormpath. We have a quite a straightforward solution for this. Please take a look at Using Stormpath for API Authentication.
As a summary, your solution will look like this:
You will use the Stormpath Java SDK to easily delegate all your user-management needs.
In your front, when the user presses the login button, your front end will send the credentials securely to your backend-end thorough its REST API.
2.1. By the way, Stormpath greatly enhances all the possibilities here. Instead of having your own login page, you can completely delegate the login/register functionality to Stormpath via its IDSite, or you can also delegate it to our Servlet Plugin. Stormpath also supports Google, Facebook, LinkedIn and Github login.
Your backend will then try to authenticate the user against the Stormpath Backend and will return an access token as a result:
/** This code will throw an Exception if the authentication fails */
public void postOAuthToken(HttpServletRequest request, HttpServletResponse response) {
Application application = client.getResource(applicationRestUrl, Application.class);
//Getting the authentication result
AccessTokenResult result = (AccessTokenResult) application.authenticateApiRequest(request);
//Here you can get all the user data stored in Stormpath
Account account = accessTokenResult.getAccount();
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("application/json");
//Output the json of the Access Token
response.getWriter().print(token.toJson());
response.getWriter().flush();
}
Then, for every authenticated request, your backend will do:
/** This is your (now protected) exposed operation */
public void getOrder(HttpServletRequest request, HttpServletResponse response) {
Application application = client.getResource(applicationRestUrl, Application.class);
OauthAuthenticationResult result = (OauthAuthenticationResult) application.authenticateOauthRequest(request).execute();
System.out.println(result.getApiKey());
System.out.println(result.getAccount());
//Return what you need to return in the response
doGetOrder(request, response);
}
Please take a look here for more information
Hope that helps!
Disclaimer, I am an active Stormpath contributor.

How to retrieve user name from CAS in Apache Wicket

I am working on a research project for a university, and I must build a portal-like web application where they see analysis information about their academic performances.
My web application is built using the Apache Wicket framework.
I need to use the university's CAS authentication server and use its login page to validate the user credentials. However, I also want to retrieve the name the user entered as username, as I need it for storage in session variables and use for the duration of the session.
I saw that CAS has a client for Apache Wicket, but I can't see how I can retrieve the username.
Any help would be appreciated,
Jeremie
Looking at the code for the client here https://wiki.jasig.org/display/CASC/Apache+Wicket+CAS+Client it looks like the getUser() method in CasAuthenticatedWebPage may be what you want.
/**
* #return the authenticated principal name
*/
public String getUser() {
Session session = getSession();
Serializable value = session.getAttribute(SSO_USER_NAME);
return value + BLANK_STRING;
}

Categories

Resources