How to implement one controller mapping method for different scenarios - spring

I have a spring controller method which could be called in different scenarios. here is the example...
#RequestMapping("/resetpassword")
public ModelAndView resetpassword( #Valid #ModelAttribute("resetpasswordForm") ResetPawdFormForm resetPawdFormForm, ModelAndView modelAndView){
... this method could be executed in 3 different scenarios....
using the hyper link coming from the user reset password link sent to user email..
eg: localhost/myApp/login/resetpassword//
Here I can authenticate userID and activationSecretCode in DB and let user reset password
user can click on resetpassword link from user settings page.
eg: Since the user is already coming from user settings page, I can validate userSession and allow him to reset password
User can login for first time successfully, but are forced to reset password due to admin requirements for reset initial default password.
eg: in this user neither have session, nor passing any activationcode to validate.
login method validates userid/default password and redirects to resetpassword mapping(method=GET).
How can the system authenticate the user request and allow him to reset password?
One alternative for this is, to use flash attributes and set a authenticationKey as flash attributes...which could be verified in resetpassword method.
is there other way to implement this....
Note: I posted an issue in implementing this approach in
Post: Spring: How to pass Java objects during redirect while using ModelAttribute
Any help?

I think the best way to implement this is using three different action methods:
resetPassword (e-mails)
resetLoggedUserPassword (via settings)
changeDefaultPassword
They may even share the same view, but the behaviors are not equal, so I would avoid overloading the action responsibility.
EDIT: elaborating on your comment:
1) To secure the e-mail link, one way is to add a authentication token. The token can be as weak as a hashed user id plus some salt string, or as strong as a GUID with expiration time in a database table, generated whenever a user requests a password reset.
2) The settings way is not a problem, considering that the user is already logged in.
3) The temporary password action can be secured the same way as 1, or the same way as 2, if you put the user on the session. Logging in the user even with the default password status shouldn't be a concern if the code that verify the status of the account are inside a request filter.

Related

How to login a user at backend without CSRF in Laravel?

I'm trying to make a user logged in at back-end who is already a user of another website of mine. For now I'm able to fetch the user's data from previous website's database using an API and make user registration during the login process. Same time I want this user to be logged in when data is just inserted because now user is existing. I tried to reuse same method $this->processLogin(); but this method takes request function processLogin(Request $request) I can't feel passing email & pass to utilize this same method. I have tried guzzle self request with 3 parms 'email, password, _token' using POST request which didn't work. I don't want to exclude this route as well because it is being used for normal login. How can i make this user logged in right after inserting the required data? Please advise. Thanks in advance.
// if $id is your user that you want to login, then:
auth()->loginUsingId($id);

How to implement ForgotPasswordController in SPA application with Laravel/Sanctum?

I'm using Laravel 7.x and sanctum. Logins are working and I would like to create a Forgot Password option from my SPA application.
I'm struggling with the basics as most of the examples in the documentation rely on the auth scaffolding. So far I've managed to get the following:
I have a controller class called ForgotPasswordController with a method called reset that receives the email to be reset via POST.
I've created a object: $user = User::where('email', $email)->get()->first();
At this point I'm too unfamiliar with the architecture to know where to go next, whether it's the Password facade, I see some additional classes in the Illuminat\Auth\Password namespace. My goal is to create an expiring token, email it to the user via the default email config (I know how to send the email / design the template) and then be able to make the webservice call that will allow the password to be resolved.
Here's what I think I know...
I've set CanResetPassword trait on my user models, which I believe are necessary to support the native methods for password reset
I believe the goal is to create a reset token keyed against the user email that expires after a period of time, then send that token appended to a url in an email (I don't know the architectural implications surrounding the generation of the token beyond the table row)
There's a Password facade with a sendResetLink method - but this
method can't work for spa applications because the base url of the
client app will be different, so I'm assuming something native will have to be re-written. In fact, calling this method will return an error of Route [password.reset] not defined.
I'm assuming I will need the password Facade, if so, what is the method to generate the token? Should I just email the link with the token appended or are there other architectural considerations to support the token expiration?
Apologies if my questions are flawed, I'm unclear on the architecture so I'm making assumptions.
Have you tried Laravel authentication? All authentication requirements have been moved to a package called laravel/ui.
By installing that package you can use Laravel authentication. It will take care of your registration, login, and forgot password processes.
This package will create some controllers for all those processes and those you need for forgot password are
ForgotPasswordController: will generate and send reset password links.
ResetPasswordController: will reset the password by getting user's email, new password, and reset password token.
But if you don't want to use the official Laravel package you should take these steps:
Show a "Request reset password form" to the user.
Validate the provided email by the user.
Generate a random reset password token and store it at DB (Need a table with at least two fields: email and token).
Send that token to the user(It's better if you send it as a URL parameter in the reset password link).
When the user navigated to the reset password page, ask for email again and validate the token by checking your DB table and matching the email and token.
Reset the password to whatever the user wants at this point.
Update: I use this piece of code for generating random tokens:
$email = 'user#email.com';
$token = \Illuminate\Support\Str::random(10);
while(\DB::table('reset_password_tokens')->where('token', $token)->exists()) {
$token = \Illuminate\Support\Str::random(10);
}
\DB::table('reset_password_tokens')->insert(compact('email', 'token'));

Spring security - Is username and password must for creating authentication

I am using spring security to authenticate a user. The user is authenticated by a third party and will already be authenticated when he reaches my application.
To implemented this, I have simulated a Authentication object.
I don't have any username and password and instead just have identifier. I check if this identifier is valid or not using my custom code.
My query is as follows:
Do I require a username and password to create a authentication object.
I have done without providing username and password and my application works fine.
I just want to ensure that I am using spring-security correctly.
Is there any impact of not putting username and password in Authentication object. I read below in AbstractUserDetailsAuthenticationProvider:
// Ensure we return the original credentials the user supplied,
// so subsequent attempts are successful even with encoded passwords.
I have also implemented a custom provider.
What does above comments means?
Is my approach correct?
The Authentication interface in Spring Security represents a token for carrying out validations against the configured security rules and the current call context. This interface has six methods of interest - getPrincipal, getCredentials, getDetails, getAuthorities, isAuthenticated and setAuthenticated.
Since you are authenticating users on your own, you should be mostly concerned with calling setAuthenticated(true) at an appropriate stage in the flow so that isAuthenticated starts returning true to indicate an authenticated user. Additionally, you may add GrantedAuthoritys to the Authentication for any role-based checks to work correctly.
However, it will be useful to make sure that getPrincipal (username in the case of form login) returns a unique value per user or per session. This will prevent the possibility of user sessions getting interchanged due to non-unique principal, which is used by the framework to identify users uniquely.
You may leave getCredentials and getDetails unimplemented. In fact, getCredentials (password in the case of form login) should be left unimplemented in your case because your application does not have the credentials used to actually authenticate the user; plus, it is a security risk to keep the credentials around after the user has been authenticated successfully.

Spring Two factor authentication where to save credentials

I'm trying to implement two factor authentication in my Spring application.
Desired situation
I want the user to first log in with his username and password, if those are correct I want the system to generate a random key and email that to the user. After that the system has to redirect the user to a page where he only has to enter the token and login to the system.
What I got so far (in pseudo code)
User enters the login.jsp page. Upon logging in with username/password the system sends out a CustomMade AuthenticationException. In the AuthenticationFailureHandler I do a getAuthentication on the exception (I'm aware of deprecacy) But I use the username to send the user his token. After that I put the exception in the session (using request.getSession().setAttribute ) and finally the system reloads the login.jsp.
Login.jsp sees the exception in the session and shows the token input field. User fills the token input field and logs in. System authenticates the user with the credentials in the session and the given token.
Question
I think it's bad practice to save the username/password in session. Two possible solutions I thought of:
After checking Username/Password. Save the username in a static variable or in DB. When user is entering the token check whether username is in the variable/db and check the token. If the token is correct do a login with the user.
After checking username / password log the user in with a low role. With the low role the user can only go to the token page, after entering a valid token the system gives the user new authorities.
What would be the best solution to implement?

spring security 2 phase authentication

I'm a newb to spring security and I'm not sure where to start. I have requirements to have a multi-page authentication. The first page authenticates the username, if the username exists the web app progresses to the password page. (site image) The second page authenticates the password, if successful then the user is authenticated. I'm not sure how to fit this into spring auth. Do I add multiple login-filters and authenticationproviders ? If I add multiple authenticationproviders, will I be authenticated after the first login ?
Page 1: User enters username. Submit this to your own controller where you check if the user exists. If the user exists, display page 2, pass the username in the model. You better not include Spring Security authentication in this step.
Page 2: User enters password. Use a readonly or hidden field to keep track of the username. Submit the form to Spring Security form login filter. You don't need multiple authentication providers.
Note: This approach has an information "leak"; any visitor can check whether a username exists in the system or not.
It depends on the kind of your authentication:
JDBCAuthentication
You can do with #holmis83 suggests.
LDAPAuthentication:
I am afraid tht you can't do that.

Resources