ASP.NET MVC custom membership for beginners - asp.net-mvc

I am creating my own website and blog and I want for first time just me in database (my name and password) and maybe later some registration for others but first log in just for me and administration with authorization. I don´t want to use Membership from MS. I want try to create my own from start so I am looking for guide for beginners but I found big guides with roles, rights. I want just small example with check username, password in database with log on data.
Thanks for help
Libor

Even if you don't want to use the membership and role provider data store you can still utilize the authentication. Trust me, it's a lot easier than building your own. Here's how it works:
We'll say you already have your user storage setup for retrieving the username and their password. For the sake of simplicity I'm going to pretend you have a static class called DataLayer that contains your data retrieval methods for pulling info from the database (or whatever storage you use).
First you need a way to let the user log in. So set up a page with username and password fields. Then in the action method that the page posts to set up a quick if statement:
if (DataLayer.UserExists(userModel.Username))
{
User userFromDB = DataLayer.GetUser(userModel.Username);
if (userFromDB.Password == userModel.Password)
{
FormsAuthentication.SetAuthCookie(userFromDB.Username, checkBoxRememberMe.Checked);
//Use userFromDB as the username to authenticate because it will
//preserve capitalization of their username the way they entered it
//into the database; that way, if they registered as "Bob" but they
//type in "bob" in the login field, they will still be authenticated
//as "Bob" so their comments on your blogs will show their name
//the way they intended it to.
return "Successfully logged in!";
}
}
return "Invalid username or password.";
Now that they are authenticated you can just use Page.User.Identity.IsAuthenticated in your code to find out if they are logged in. LIke this:
if (User.Identity.IsAuthenticated)
{
DataLayer.PostBlogComment(User.Identity.Name, commentBody);
//Then in your controller that renders blog comments you would obviously
//have some logic to get the user from storage by the username, then pull
//their avatar and any other useful information to display along side the
//blog comment. This is just an example.
}
In addition, you can lock out entire action methods or even whole controllers to users that are authenticated through the forms authentication provider. All you have to do is add tags like these to your action methods/controllers:
[Authorize]
public ActionResult SomeActionMethod()
{
return View();
}
The [Authorize] attribute will prevent users that are not logged in from accessing that action method and it will redirect them to your login page. You can use this same attribute to filter out roles if you are using the built in roles provider.
[Authorize(Roles="Admin, SalesReps")]
public ActionResult SomeActionMethod()
{
return View();
}
These attributes can also be added above the controller class to apply it's logic to the entire controller.
EDIT: To log a user out all you need to do is call FormsAuthentication.SignOut();

Hey #Bibo, good for not choosing the Membership providers. I think a UserService or similar which provides methods for creating, authenticating users and some few more methods should be enough. As a suggestion, use password hashing and a password salt for the user´s password. Here is a good link to look at. Also have a look at this answer I gave some time ago.
Good luck!
EDIT: The rememberMe parameter should be named keepMeSignedIn instead.

This article on forms authentication gives you loads of info for creating your own simple security system, especially the bit about FormsAuthenticationTicket.
http://support.microsoft.com/kb/301240

Related

2 factor authentication in Grails

I want a way to implement 2 factor authentication. When the user enters their username and password it moves them to another page where they are granted a temporary Role and then they are asked to enter a security token which will be sent to them via email. authtoken image
login image
I have been there and I discovered that its pretty easy to implement this mostly in custom code if you are in conventional old school web app. I think there is something in spring that allows you to do this, but depending on your application it might be just so much easier to do this by yourself and not even that difficult.
One way is to create grails filter that covers all routes that are affected by this. For example all except login page and the second page after that. This filter will check the temp role and if found, it will redirect to the second auth page. Otherwise it lets the request pass. Could be something like this:
twoFactorCheck(controller: '*', controllerExclude: 'privacyPolicy|login|logout|2factor', action: '*') {
before = {
if (process2factorAuthNeed()) {
return true;
}
redirect(controller: "2factor", action: "index");
return false;
}
}
Then another thing you need is an implementation of custom UserDetailsService where you can capture the first normal authentication and set the temp role for the user. This is covered here: https://grails-plugins.github.io/grails-spring-security-core/2.0.x/guide/userDetailsService.html if you are on grails 2.* but your spring security plugins version user guide will have this entry as well.

Prevent access to page based on Authentication

I have an ASP.Net MVC 4 Website. When I started this site I had little to no web programming experience, and I don't believe I set up all of it appropriately.
I have pages, such as Home, Login, Register, which I consider public,
pages like, VerifyPIN and AccountCreated, which I consider internal
and pages like Dashboard and Profile, which are private.
I feel public pages should be accessed by anonymous users, but Login and Register should not be accessible once a user logs in.
Internal pages I want to only be available upon server redirect and never through the browser, aka I don't want a user to be able to type in www.MySite.com/AccountCreated.
And private pages are for a logged in user only.
I feel I have private pages working fine, but I don't know how to limit access to the other pages as described above. Perhaps my notion to not allow a logged in user to access the log in page is miss-found.
My site is relatively small due to the ajax nature of the site. I use [AllowAnonymous] on all public pages but then a logged in user can still access those and I am not sure how to prevent that.
My questions are,
How can I prevent a user from accessing a page via the address bar (www.MySite.com/AccountCreated)
How can I prevent access to a [AllowAnonymous] page once a user has logged in.
EDIT
Is it normal to prevent logged on users from accessing certain anonymous pages, such as login?
You may always check if user is already logged in. If he did, he will be redirected to another page:
public ActionResult AccountCreated(some params)
{
if (Request.IsAuthenticated)
{
return RedirectToAction("Index")
}
else
{
// login logic here
}
}
You may also check it directly in View:
#if (Request.IsAuthenticated)
{
<span> You are already logged in</span>
}
else
{
//Login form here
}
well for your first question you can use the [Authorize] action filter.
For your other question, I guess you will have to write your own implementation. You will need to create a new IAuthorizationFilter and use it instead of [AllowAnonymous]
Just some ideas(didn't try them actually).
For question 1 - if AccountCreated is an action that means that the registration form actually POSTs to that URL - i.e. It is accessible from outside. I suggest you apply an HttpPost attribute to it so it will process only POST requests - there is not much you can do here
For point two you can do something like this in your action method
if (HttpContext.User.Identity.IsAuthenticated)
{
return RedirectToAction("Index", "Home");
}
else return View();
Just a thought, Signout user when a user goes to Login or Register page .
Hope you have not provided any link on private pages for a user to go to login or Register
page or check if user is authenticated redirect it to Home page, frankly you can not stop a user to write a URL and pressing the enter button, or just give a notification that You'll be logged out if you proceed to whatever page.

ASP.NET MVC4 WebMatrix WebSecurity Forms authentication: Changing a username

I'm using WebMatrix WebSecurity for my application's Forms Authentication.
The user needs to be able to change his username, without being logged out.
I supposed calling WebSecurity.Logout(), followed by WebSecurity.Login() would do the trick, but Login() requires a password. Of course, I cannot provide this password as it is hashed in the DB.
How can I make this requirement work?
EDIT:
Below are a few suggestions on how to fix the issue of changing the username.
However, my actual problem was that the cookie still holds the old username. I found the following instructions on how to handle that:
http://omaralzabir.com/how_to_change_user_name_in_asp_net_2_0_membership_provider/
So this is how I able to change the user name. This all happens inside a post action method for updating all kinds of user data.
First I check to see if the user name already exists. "info" is a model object coming from the view.
if (WebSecurity.CurrentUserName != info.UserName &&
this.userRepository.Find(info.UserName) != null)
{
ModelState.AddModelError("", "This email is already taken.");
return View();
}
Then I update the database.
UserProfile user = this.userRepository.Find(info.UserId);
user.UserName = info.UserName;
this.userRepository.SaveUser(user);
Then here is the magic part. You have to reset the authorization cookie.
FormsAuthentication.SetAuthCookie(user.UserName, false);
I hope that helps someone out there.
Since WebMatrix WebSecurity is done via UserId, not Username, just change the data in the table you are storing your userdata in, and then redirect them to a new page. You don't need to log them out and back in, I believe the new username will be picked up immediately.
You can do the following steps
Get the UserDetails by UserId or UserName
Change the UserName
Now update the user data by calling the SimpleMembershipProvider.UpdateUser.
More details here

display view regarding to authentication?

When it comes to display a view regarding to authentication (view displayed depending to the visitor if he's a user or not). I face many choices. So I need your help to show me how i deal with such situation :
Using 2 views (one for the users and other for visitors), or just one view.
using 2 actions (one with authorize filter and the other without), or just one action.
And why the choices you suggest is better ?
You don't have to not use Authorize attribute. It's main function is to setup the User in the context, and then by default, it also checks that they are logged in. However, this last part can be overridden by using the AllowAnonymous attribute as well:
[Authorize]
[AllowAnonymous]
public ActionResult SomeView()
{
...
}
So, now your view will have a User to play with, and you can dynamically present different pieces of the view using that based on auth status:
#if (User.IsAuthenticated)
{
<p>Logged in</p>
}
else
{
<p>Anonymous</p>
}
EDIT (for clarification)
The Authorize attribute actually does two distinct things for you. First, it setups all the machinery for recognizing a user: reads the cookie or whatever, checks the authentication status, pulls in the user's info, if they are authenticated, etc. Second, it validates that the user is in fact logged in. Using AllowAnonymous skips this second part and allows anyone, logged in or not, to access the view, BUT and this is key, you still need the first part to know stuff like whether you have an authenticated user or not.
So, simply, using both the Authorize and AllowAnonymous attributes together means essentially, "see if the user is logged in, but don't require it to access this view". That allows anonymous users to still reach the page, but enables you to still deliver unique or different content to an actual logged in user.

Redirect to Login Page on some condition of session check

In C# with MVC, i want to write a common utility or class in which if a particular conditoin fails need to redirect to login page.
For ex.: When the user logged in to the website, userid will be added to session. To Access the "ManageUsers" page, the user should be logged in as admin, else i need to redirect to Login page. i need to check this condition in some of the other similar pages also. i dont want to check either the user is admin or normal user while login. i need to check this in common class.
Any suggesstions?
Actually I think this is not particularly good behavior for an application. I think you ought to disable (or hide) any actions that a user is not able to perform. In the case where the user hand-enters a URL, or uses a bookmark from when they had the privilege, show an error message rather than redirecting to the login page.
Imagine you're a user who is logged into your application. You click on a user interface element and it looks like you've been logged out. You have no way of knowing that you weren't supposed to use it. Disabling/hiding the element prevents this scenario from occurring for most users. Redirecting to an error gives valuable feedback to the user as to why the action they took did not result in what they expected.
I use a custom attribute derived from AuthorizeAttribute to achieve this effect. If a user isn't logged in, it redirects to the login page. If they are logged in, but not sufficiently privileged, it displays a suitable error view.
This already exist in ASP.NET MVC with the Authorize Attribute:
[Authorize(Roles="Administrators")]
public AcitonResult ManageUsers() {
return View();
}
Or
[Authorize(Users="Admin,SomeUser")]
public AcitonResult ManageUsers() {
return View();
}
More infos:
http://www.asp.net/learn/mvc/tutorial-17-vb.aspx
[Authorize(Roles = "Admin")]
public ActionResult ManageUsersController()
{
...
}
In your web.config check:
...
<forms loginUrl="~/your_login_page" defaultUrl="~/">
...
Also you should setup both MembershipProvider and RoleProvider in your web.config

Resources