How to redirect login plus previous URL in laravel - laravel-5.1

Laravel 5.1
I'm trying to build this functionality for every method in my controller. And this is very unpractical to do and very difficult to maintain. How can I set this that is when I registered an auth middleware in a specific route then it will redirect into a login page together with the URL that trying to view/visit.
Example:
URL: public/users
If this URL will try to visit by an unauthenticated user, then the user will be redirected to a url like public/login?url=http://localhost/myproject/public/users
Then After the user loggedin successfully, the user then will be redirected into http://localhost/myproject/public/users
What I have now: (But I think not a good one to use)
public function getLoginURL(){
if(!Input::get('location-login')){
// URL is not set, redirect user to home.
return redirect('/');
}
if(auth()->check()){
// User is logged in. Go the specified URL (depends on the middleware of the url (route))
return redirect()->to(Input::get('location-login'));
}
if(!auth()->check()){
// Redirect user to a login with the URL provided
return view('pages::auth.login.url');
}
}

You can use the next method in middleware... no need to send the url
public function handle($request, Closure $next)
{
if (Auth::user()) {
return $next($request);
}
return redirect('/login');
}

Use this in your AuthController
namespace App\Http\Controllers;
use Auth;
use Illuminate\Routing\Controller;
class AuthController extends Controller
{
/**
* Handle an authentication attempt.
*
* #return Response
*/
public function authenticate()
{
if (Auth::attempt(['email' => $email, 'password' => $password])) {
// Authentication passed...
return redirect()->intended('dashboard');
}
}
}
intended() function will redirect you to your intended location.
Check the full detail here Intended redirect

Related

How to create a login function without using spring security with grails 3 using interceptors

System has two grails apps:
the private backoffice which uses springsecurity and an Operator domain object holding the operators username, password, number of failed logins etc.
the public web front end where users signup, login, and use the system. The User domain object holds the users username, password etc.
Because we are using springsecuirty for the backoffice, I assume we cant use it again for the web (the config and db will conflict). Also, the web just needs a very basic auth (all pages require a valid session except register and the login form itself).
Setting up the login form and the interceptor are easy.
The question is, what should the login form actually do in the controller? I can check the username and password match whats in the DB, then I presumably need to create a session, with session timeouts etc. Where do I look for documentation on how to do this? http://docs.grails.org/3.1.1/ref/Servlet%20API/session.html Tells you how to logout, but not login. I presumably need to store sessions in the DB (so that the user can hit any server) etc.
By looking at some of my old java code, I have got some of the way there.
The interceptor looks like this:
class AuthInterceptor {
public AuthInterceptor() {
// allow the login form and register form to work.
matchAll().excludes(controller: 'auth')
}
boolean before() {
if(session.getAttribute("user")== null ) {
// jump to the login form if there is no user attribute.
redirect controller: 'auth', action: 'login'
return false
}
true
}
boolean after() { true }
void afterView() {
// no-op
}
The controller looks like this:
class AuthController {
def index() { }
def login() {
def email = params.email
def password = params.password
if (email != null) {
// It would be better to invalidate the old session
// but if we do, we cant get a new one...
// session.invalidate()
User user = User.findByEmail(email);
if (user != null) {
log.error("user.pass:" + user.password + " pass:" + password)
// #TODO handle password encryption
if (user.password == password) {
session.setAttribute("user", user)
redirect(controller:"dashboard")
}
}
flash.message = "email or password incorrect"
}
render (view:"login")
} // login()
However, I have not found where we can set the session timeout yet.

What is the best way to check if the user is logged in or not in grails Spring Security?

I would like to check if the user is logged in or not.I have integrated interceptor in most of the projects to check if user is logged in . But this does-not work well with AJAX request and matching all the controllers in the interceptor causes filter to be applied for all controllers including /static/** ,where in this case i will have to exclude (.excludes(uri: "/static/**")) .Is this the correct and standard way of doing?
LoginInterceptor() {
matchAll()
.excludes(controller: "login")
.excludes(controller: "signUp")
.excludes(uri: "/static/**")
.excludes(uri: "/assets/**")
}
boolean before() {
if (!springSecurityService.isLoggedIn()) {
flash.message="You need to login to access furthur pages"
redirect( controller: 'login',action: 'auth');
return false
}
true
}
boolean after() { true }
void afterView() {
// no-op
}
The above code doesnot work with the AJAX request . How do i make a generic interceptor which works well with both AJAX and WEB request? And is this a standard way of monitoring request for logged in?
If you use spring security plugin. You can do it by configuring security config. You can find more here
For ajax request you can check return code and if it is == 403, you can redirect user to the login page.
When working on my project, I found the following way to check the log-in status.
def springSecurityService
boolean canEdit() {
boolean isLoggedIn = springSecurityService.isLoggedIn()
if (!isLoggedIn) { return false }
boolean hasAdminOrCuratorRole = userService.isLoggedInUserACurator() || userService.isLoggedInUserAAdmin()
hasAdminOrCuratorRole
}
Hope this helps!

No Access To UserDetailsService in LogoutController When Logged into Grails Application via SAML

Using Spring SAML Security, I've enabled our application as a Service Provider. This works great, I use a custom WickedUserDetails (extended from GrailsUser), and everything populates as it should.
Now I'm trying to implement the global logout for SAML, but even before I can do anything "fancy," I've noticed that when I hit our regular LogoutController, I do not have access to WickedUserDetails. I just have an anonymous grails user.
This behavior happens when I try to access /logout/index and /logout/special. It works as expected when I use SlogoutController.
class LogoutController {
def springSecurityService
/**
* Index action. Redirects to the Spring security logout uri.
*/
def index = {
// Populates with ANONYMOUS GRAILS USER when logged in via SAML
// but with WickedUserDetails when logged in via the "normal" Spring Security mechanism
def check = springSecurityService.principal
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl // '/j_spring_security_logout'
}
def special = {
// Populates with ANONYMOUS GRAILS USER when logged in via SAML
// but with WickedUserDetails when logged in via the "normal" Spring Security mechanism
def check = springSecurityService.principal
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl // '/j_spring_security_logout'
}
}
class SlogoutController {
def springSecurityService
def special = {
// Populates with WickedUserDetails
def check = springSecurityService.principal
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl // '/j_spring_security_logout'
}
// Populates with WickedUserDetails
def index = {
def check = springSecurityService.principal
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl // '/j_spring_security_logout'
}
}
In my Config.groovy, I don't have any special interceptor URLs set up, the only reference I have to the logout URL is:
grails.plugin.springsecurity.secureChannel.definition = [
'/login/**' : 'REQUIRES_SECURE_CHANNEL',
'/logout/**' : 'REQUIRES_INSECURE_CHANNEL'
]
This is the only reference I have set up in UrlMappings:
"/logout/$action?"(controller: "logout")
Can someone please explain to me why this behavior happens? I can come up with a workaround in my app, but I am insanely curious as to what's going on.
OK, the issue was my taking shortcuts. In the authentication provider originally, I was not updating the bespoke token with the SAML credentials
Authentication authenticate(Authentication authentication) {
if (authentication instanceof SAMLAuthenticationToken) {
def samlToken = super.authenticate(authentication)
if (samlToken) {
String username = samlToken.principal
LightweightContact contact = new LightweightContact(username: username)
contact = contact.findByUsername()
boolean isContactValid = contactValid(contact, samlToken)
if (isContactValid) {
WickedAuthenticationToken wickedToken = MyNormalSpringCustomWickedAuthenticationProvider.getWickedAuthenticationToken(contact)
// -------- I needed to explicitly set the credentials here -----------------------
wickedToken.setCredentials(samlToken.credentials)
return wickedToken
}
}
}
// the authentication token was not of the correct class
// or no user was found for it
return null
}

Laravel 5 User activation

I have a strange problem that I can't solve.
When a user is registered, I redirect them to a feed url, open a modal and tell my user to activate his account by clicking the email link that I sent them. But after I click the link, I keep being redirected to the exact same page (feed) and my account isn't being activated. What could be the problem here?
routes.php
Route::group(['namespace' => 'Auth'], function ()
{
Route::group(['middleware' => 'auth'], function ()
{
Route::get('activate/{token}', 'PasswordController#activate');
});
});
PasswordController
public function activate($token) {
//get token value.
// find the user that belongs to that token.
$activation = User::where("confirmation_code", $token)->get()->first();
$activation->confirmed = 1;
$activation->save();
}
RedirectIfAuthenticated.php If I remove feed url, it works. But I don't want to do that.
public function handle($request, Closure $next)
{
if ($this->auth->check()) {
return redirect('/feed');
}
return $next($request);
}
Assuming your using laravel default authentication system. Do the following.
In your AuthController add the method. This will create the user but not log them in since they haven't activated their account. Please note laravel will automatically login the user hence the function below overrides default behaviour.
public function postRegister(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
$this->create($request->all());
return redirect('/feed');
}
In RedirectIfAuthenticated.php remove '/feed' and instead have a url which users are to be redirected if logged in. Since having feed there will redirect user to the page asking them to activate there account every time they log in.
In the activate function of your password controller there is no logic as to what should be done once user is activated. Add the following lines after $activation->save()
Auth::login($activation);
return redirect('/');

Grails 3 interceptors and controller by example

I am experimenting with Grails 3 and its new concept of interceptors. Given the following interceptor/controller:
class AuthInterceptor {
// ...other stuff in here
boolean before() {
if(FizzBuzz.isFoo()) {
redirect(controller: auth, action: signin)
true
} else {
true
}
}
}
class AuthController {
AuthService authService
def signin() {
String username = params[username]
String password = params[password]
user = authService.authenticate(username, password)
if(user) {
SimpleSecurityUtils.setCurrentUser(user)
redirect(url: ??? INTENDED_DESTINATION ???)
} else {
// Auth failed.
redirect(action: failed)
}
}
}
AuthService is a Grails Service. I would like there to be one instance of AuthService per instance of AuthController. And I would like AuthController to have prototype scope such that I am never storing state, and a controller is created for each request. What do I have to change in both (AuthService/AuthController) to meet these scope requirements?
Assuming AuthController#signin is executed due to a redirect(controller:auth, action: signin) inside an interceptor, how do I redirect (yet again) the user to their intended destination (that is, the URL they wanted to go to prior to the interceptor intercepting the request) from inside the controller action above?
First, if you redirect to another URL, you must return false to cancel the rendering process, e.g.
redirect(controller: auth, action: signin)
false
Second, if you want back to previews intended URL, you must save it, may be, to session, and then you redirect to the saved URL when you finish signin process.

Resources