Grails Request Map custom errors - spring

I've got a websoftware done with Grails that uses request maps from Spring Security.
I am using them for security reasons, so that the user can't access admin areas but also it's used for our business model. We've got two different user roles. One is premium and one is premium plus, while PREMIUM_PLUS > PREMIUM.
The premium plus user can access some more pages than the premium user can. If a premium user wants to access a page that can only get called by a premium plus user, there will be a error like 'no access', but I want a custom message like 'Upgrade now to premium plus'.
I could easily edit the template for all request maps errors but there are also some restricted pages nobody should see where a message like 'no access' is perfect for.
Is there any possibility to do this with two different error pages?
Thank you.

The LoginController have the action denied that shows the denied.gsp. You can customize your controller action to check if you need to display the upgrade page or the denied page.
class LoginController {
def denied() {
if (springSecurityService.isLoggedIn() &&
authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) {
// have cookie but the page is guarded with IS_AUTHENTICATED_FULLY
redirect action: 'full', params: params
} else {
//implement a method checking whatever you need to define that will display the upgrade
if(mustShowUpgrade()) {
render view: 'upgrade'
}
}
}
}

Related

Laravel - Booting web middleware from an exception's render method

Found few answers on SO but most of them where kind of hacky so I decided to post anyway.
So I'm using Laravel 8 + InertiaJS and my app has a Billing/Plan logic.
Whenever an app user wants to create a resource, the resource's policy perform checks to ensure the user is under its plan allowance.
If the user reached the limit, a custom exception is returned.
The exception returns an Inertia view, which inherit the app's layout (containing a navbar with user details).
class PlanLimitReached extends Exception
{
public function render($request)
{
if ($request->expectsJson()) {
return response()->json([
'error' => 'PlanLimitReached',
'message' => 'You reached the limitation for your current billing plan, please upgrade your account.',
'documentation' => 'https://docs.company.tld'
], 403);
}
return Inertia::render('User/Billing/LimitReached');
}
}
The issue is that component does not render because user variables are not set. It's expected behaviour as you would typically have a template that do not include auth-related logic specifically for 4XX & 5XX errors pages.
But I would rather have a page directly integrated in my app, so I need a way to force this specific exception to force loading the web middleware (exactly what is discussed in https://github.com/laravel/ideas/issues/676).
Unfortunately solutions I found are:
Requiring the web middleware in the global middleware, which is not really feasible as it would mess up my API routes
Creating a route for the error page and then having the exception redirect to this page, it would work but I find this solution quite ugly
Creating a "guest" layout without auth logic for exception pages, pretty ugly IMO
TLDR: Looking for a way to load web middleware from an exception's render method to be able to use auth()->user() in my templates, without redirects or requiring the web middleware globally.

Laravel 5.1 use session to restrict direct access using urls users based on user role

I have 2 laravel projects, 1 for the front end where i m using html css angularjs. The second for api controllers. I call using http post and get the api controllers functions using angularjs to get content data.
In the front end i have a menu this menu appears differently based on user role, if admin or no.
This is done. My problem is the access for views using the url in the browser.
So I have a query where I get for each user what modules in the menu can he see. Now I'm putting the result in Laravel session.
$menu = DB::select menu by user id ... //Getting menu query based on user if admin or no
session(["menu" => $menu);
return session('menu');
I'm getting the results and the menu is showing good in the website based on the logged user if he s admin or no.
Now, to solve the direct url access issue, I want to use this session and compare the url to this session, if the url exists in the session i will let him access, if no i will redirect him to somewhere.
any idea?
I would strongly suggest looking at the Laravel documentation on Authorization before going too far down a custom implementation:
https://laravel.com/docs/5.1/authorization
Without knowing more about how your front-end and back-end applications interact with each other, it is a little difficult to get into speciifics but i shall do my best.
Each page returned by Laravel has access to a Request object which contains information about the request which returned the page. You can access this Request and its assocaited Route using Laravels helper functions (if you are not passing it to the view already). The getPrefix() method will return the root relative url which you can then use as you see fit. For example:
// Return and store the URL as a string
$url = request()->route()->getPrefix();
// Check your session for the URL/s you want to allow and compare to the stored URL
if (session()->get('URL') == $url) {
// User is allowed access to the page
// Do something ...
} else {
// User is not allowed access to this page
// Redirect back or to a route of your choice
return redirect()->back();
}
I hope this gives you some ideas, good luck!

Laravel Middleware change response content

For my application I am having multiple user roles and a custom maintenance mode. If the site is in maintenance mode, then depending on the user's role will limit their access to certain pages.
So when "normal" users access the forums, they should instead see a different view saying that the site is in maintenance mode; whereas when "admin" users access the forums they should be able to see the forums.
public function handle($request, Closure $next) {
if(Auth::user()->role->maintenance_mode != 1) {
// They do not have access during maintenance mode,
// so change the response to show a different view.
}
// They do have access during maintenance mode,
// so continue the request.
return $next($request);
}
Is it possible to have the same route (e.g. /forums) but to show a different view, changed by the middleware.
It is possible, yes, however each middleware calls $next($request) which may point to another middleware before the route, therefore returning a view may not be the best idea. If you do want to do it, then you need to do something like: return new Response(view('maintanance')); and don't forget to include use Illuminate\Http\Response; in the header of your Middleware class.
In your case, what I would do is have a route that returns a view such as /maintainance (preferably with a name) and then in the middleware, return a redirect to the route return redirect()->route('maintanance'); within the if.
You could also throw a HttpException with the status code of 503 to have the application invoke Laravel's built in maintenance mode within that first if.

Centralized Authorization of Controllers and Actions (ASP.NET MVC 3)

Are there any possible security issues or pitfalls to, within a custom AuthorizeAttibute (registered globally), apply authorization based on the controller type and action being called?
e.g. (not real code)
string controllerFullName=_filterContext.ActionDescriptor.ControllerDescriptor.ControllerType.FullName;
string minRequiredRole = GetControllerMinRequiredRole(controllerFullName);
if(User.MeetsRoleRequirement(minRequiredRole))
{
//give access
}
else
{
//no you're not allowed
}
The main issue is with Authorization caching - so there are a few things to know. Check out the links I've posted here:
Creating a AuthorizeAttribute - what do I need to know?
Look at the code to the existing attribute and how it handles caching to ensure you arent causing the same issue the base attribute prevents.

Magento - Redirect back (similar to using setBeforeAuthUrl) when user creates a new account

I have the following controller action, which redirects to the login page if no user is logged in:
public function requireloginAction() {
if(!Mage::getSingleton('customer/session')->isLoggedIn()) {
// Not logged in
// Save requested URL for later redirection
Mage::getSingleton('customer/session')->setBeforeAuthUrl($this->getRequest()->getRequestUri());
header("Status: 301");
header('Location: '.Mage::helper('customer')->getLoginUrl()); // send to the login page
}
else {
// Logged in
.. do something ..
}
}
By using setBeforeAuthUrl, once the user logs in he/she is redirected back to this action.
Problem:
If instead of logging in, the user, creates an account he/she is then redirected to the main page, rather then to the url set in setBeforeAuthUrl.
Question:
Is there something similar to setBeforeAuthUrl that works with Account Creation too? Or how can I achieve the desired effect?
(Magento Version 1.6)
You can try using the following extension. http://www.magentocommerce.com/magento-connect/MagePsycho/extension/3763/custom_login_redirect
Or you can also open app/code/core/Mage/Customer/controllers/AccountController.php and look for the createPostAction() function around line 328 edit:
$url = $this->_welcomeCustomer($customer);
$this->_redirectSuccess($url);
to
$url = 'http://www.mycustomrediurecturl.com';
$this->_redirectSuccess($url);
If you want to do it the nice way override the controller add configuration options and make it a module :)
Cheers
Found solution.
First of all, setBeforeAuthUrl($url) does work for both "Log In" and "New Account Creation"!
The main difference (and the reason I had the problem) is that for a "New Account Creation" Magento checks if $url is within the domain name of the current store and if it is not, it redirects to the "My Account" page. While the redirection for "Log In" redirects to any $url.
I do not know if this is a bug or a feature (I'm using V1.6.0.0).
So just make sure to redirect to a url within the domain name of the current store - especially in a Multi Store configuration.

Resources