Nancy Fx Razor views how to show or hide elements based on user roles - forms

I am playing with Nancy and Forms Authentication. I have a layout view that shows a login or a logout link depending on whether or not the user is authenticated:
#if (#Html.RenderContext.Context.CurrentUser.IsAuthenticated())
{
<p><small><span style="padding-right:15px"><em>#Html.RenderContext.Context.CurrentUser.UserName</em></span>
Logout</small></p>
}
else
{
<p><small>Login</small></p>
}
Throughout my app I will have elements that need to be visible only to those with the correct role.
My question is this. What is the best way to handle this? Should I check for the role in the view and then show/hide the element or in the module show different views depending on the user role?

I ended up using partial views in my layout to provide different navigation sections based on permissions.
#if (#Html.RenderContext.Context.CurrentUser.IsAuthenticated())
{
if (#Html.RenderContext.Context.CurrentUser.Claims.Contains("Admin"))
{
#Html.Partial("Views/Partials/_AdminMenu")
}
else if (#Html.RenderContext.Context.CurrentUser.Claims.Contains("Editor"))
{
#Html.Partial("Views/Partials/_EditorMenu")
}
else if (#Html.RenderContext.Context.CurrentUser.Claims.Contains("Viewer"))
{
#Html.Partial("Views/Partials/_ViewerMenu")
}
else
{
#Html.Partial("Views/Partials/_PublicMenu")
}
}
else
{
#Html.Partial("Views/Partials/_PublicMenu")
}
I will render different views from the module if there are significant differences and send the user to a "permission denied" type view if the get to somewhere they are not supposed to.
I found this to redirect the user to a denied view. Add an after hook to the top of the module.
public class EditUserRoleModule : NancyModule
{
public EditUserRoleModule()
{
// add an after hook to send the user to access denied if they are NOT admin
After += context =>
{
if (context.Response.StatusCode == HttpStatusCode.Forbidden)
context.Response = this.Response.AsRedirect("/denied");
};
this.RequiresAnyClaim(new[] { "admin" });

Related

Keycloak-js perform action after user authentication

I'm using Keycloak for my auth server in a reactJs site. I have all the normal workflows working using keycloak-js, KeycloakProvider and useKeycloak. I need to have some custom redirection rules however when a user logs in based on their role. i.e.
If they log in from the home screen, then
a) If it is a normal user they are redirected to /dashboard
b) If it is an admin user they are redirected to /admin
If they tried to reach some protected screen, they should be redirected back to the screen they requested
Right now it keycloak always directs them to the last screen they were on and I don't see a way to capture the "on intial login" event.
Any suggestions?
Maybe it's sufficient to check for the roles after the init/login or alternatively the keycloak.idTokenParsed.preferred_username and then redirect after a successfuly auth to your desired path (eg React Router or history.push("/dashboard") (with the useHistory hook))?
What I ended up doing is creating a /login route that my login points to. The only thing it does is force authentication the redirect to the proper page.
const RoleRedirector = (params) => {
const { keycloak,initialized } = useKeycloak();
const history = useHistory();
useEffect(()=>{
if(keycloak && initialized){
if(keycloak.authenticated){
const { tokenParsed } = keycloak;
const { realm_access } = tokenParsed;
const { roles } = realm_access || [];
if(roles.includes("admin")) {
//This is a separate React site living under the common domain
document.location = "/admin/index.html";
}else if(roles.includes("manager")) {
document.location = "/manager";
}else {
history.push("/dashboard");
}
}else{
keycloak.login();
}
}
},[keycloak,initialized])
return <div/>
}

How do you navigate to a user profile with Google uid without showing it in the url

I was just wondering how to navigate to a users profile with their google uid in ui-router. I'm assuming that this is sensitive information that shouldn't be displayed but I'm not really too sure so I figured I would ask to make sure I'm doing things the right way.
The link I am using is:
<a ui-sref="timeline.profile({ userKey: post.userKey })" ui-sref-active="selected">{{post.userKey}}</a>
Where userKey is equal to the google uid. And then this is my state for the public profile.
.state('timeline.profile', {
url: '/{userKey}',
views: {
'timeline-tab#tab': {
templateUrl: 'timeline/templates/public-profile.html',
controller: 'PublicProfileCtrl as publicProfileCtrl'
}
},
resolve: {
auth: function($state, Auth){
return Auth.$requireAuth().catch(function(){
});
},
publicProfile: function(Users, Auth, $stateParams) {
return Auth.$requireAuth().then(function(authData) {
return Users.getPublicProfile($stateParams.userKey).$loaded();
});
}
}
})
It works for grabbing the users profile and navigating to the template but the url contains the google uid. I was just wondering how to achieve the same result without showing the google uid if that is sensitive information that shouldn't be shown.
And I was also wondering if this was good practice to create two different profiles. A private profile where the user can access all of their information and then a public profile that just displays the information.

Fuelphp - route index with parameters

Using Fuelphp, I'd like to be able to use a URL system similar to here on StackOverflow to get to specific pages.
Desired behavior:
-stackoverflow.com/questions -> page with many questions
-stackoverflow.com/questions/1982 ->page with specific question
Here's my controller:
class Controllers_Images extends Controller_Template
{
public function action_index($id=null)
{
if($id)
{
//Use Model_Image to find specific image
//Create appropriate view
}
else
{
//Use Model_Image to find many images
//Create appropriate view
}
}
}
I can access the "generic" page with mysite.com/images/ - this is routed to the action_index function. I can access a "specific" page with mysite.com/images/index/1. What I'd like to do is be able to skip index in this case too, so that mysite.com/images/1 works. Right now I'm getting 404. How do I set up routing for this?
After poking around a bit more, I came up with a solution that works fine:
class Controllers_Images extends Controller_Template
{
public function action_index()
{
//Use Model_Image to find many images
//Create appropriate view
}
public function get_id($id)
{
//Use Model_Image to find specific image
//Create appropriate view
}
}
In routes.php:
return array(
'images/(:num)'=>'images/id/$1',
//other routing stuff...
);
With this setup, the url "mysite.com/images/1" now appropriately displays the selected image as if "mysite.com/images/id/1" was used instead. Not a huge deal, but it is a nicer interface, which is important!

Redirect action to mobile view

public ActionResult Home()
{
return View();
}
This is what I have for my current site within the HomeController. How can I detect if the action is called from a mobile device, and if it is, re-direct to MobileHome.aspx instead of Home.aspx.
I don't need to know the details of the device, because I am implementing the view in JQuery Mobile, which should adjust itself correctly depending on the view it's rendered in.
You may find the following blog post useful.
The following is an override on the Controller class. I have not tested this, so consider it pseudo code:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (this.Request.Browser.IsMobileDevice && filterContext.Result is ViewResultBase)
{
var viewResult = filterContext.Result as ViewResultBase;
viewResult.ViewName = "Mobile" + viewResult.ViewName;
}
base.OnActionExecuted(filterContext);
}
You can use the Request.Browser.IsMobileDevice to determine if the device is mobile (obviously), and then check to see if the result it a view. However, changing the view name is not sufficient if you pass an actual view to the result of your action.

How to create a simple landing page in MVC2

I'm trying to create a http://domain.com/NotAuthorized page.
went to Views\Shared and added a View called NotAuthorized witch originates the file name NotAuthorized.aspx
in my Routes I wrote
routes.MapRoute(
"NotAuthorized", // Route name
"NotAuthorized.aspx" // Route Url
);
but every time I access http://domain.com/NotAuthorized I get an error
The resource cannot be found.
What am I missing?
How can access this without using View("NotAuthorized") in the Controller, in other words, not passing through any controller.
You can't access views directly without passing through a controller. All pages in the Views folder cannot be served directly. So one way to accomplish what you are looking for is to write a custom[Authorize] attribute and set the error page:
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(filterContext);
}
else
{
filterContext.Result = new ViewResult { ViewName = "NotAuthorized" };
}
}
I still have no idea on how to accomplish it, but what I did was use the Home Controller and create an Action called NotAuthorized
public ActionResult NotAuthorized()
{
return View();
}
And add a route like
routes.MapRoute(
"NotAuthorized", // Route name
"NotAuthorized", // URL with parameters
new { controller = "Home", action = "NotAuthorized" } // Parameter defaults
);
And works fine now, I can easily redirect in any part of my Business Logic to /Notauthorized and that will route fine.