Externally provided username as identity? - asp.net

I have a couple of systems which uses external authentication, google authentication.
I'm just keeping the login information in a session variable and keep track of the user that way (no membership provider).
I would like to have the user identity in the HttpContext.Current.User object.
Should I assign the user manually on an event in Global.asax.cs, or could I have the user automatically identified during the session?

You could write a custom Authorize attribute which will take care of assigning the HttpContext.Current.User property from the session:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var user = httpContext.Session["username"] as string;
if (string.IsNullOrEmpty(user))
{
// we don't have any username inside the session => unauthorized access
return false;
}
// we have a username inside the session => assign the User property
// so that it could be accessed from anywhere
var identity = new GenericIdentity(user);
httpContext.User = new GenericPrincipal(identity, null);
return true;
}
}
Then simply decorate your controllers/actions that require authentication with this custom attribute.

Use a membership provider, it will give you exactly what you want. Even creating your own provider isn't too difficult, just implement the abstract class MembershipProvider and plug into config, or use some of the out-of-the-box providers.
Don't roll your own solution for something critical like security, it will have gaping security holes. Storing authentication info in the session is a really bad idea. It leaves it open to session hijacking, session replay attacks etc.
If you really want to go down the route of custom authentication. Then have a look at the code I posted here. It will show you how you can take control of the authentication cookie, and use this to create your own HttpContext.Current.User instance.

Related

ASP.NET MVC Windows Authenticate with extending properties

I need help of experts!
I write ASP.NET MVC 4 Intranet application. I using Windows Authentication, the domain name get through User.Identity.Name. I have a database with the configured data context, where more complete information about the user: Last name, First name, E-mail, etc. As well as a list of user access groups.
Needed to make sure that a user open a program, has received the required access from the database, his name brought up in the upper right corner of the page.
Now I have realized that with the use of OWIN Asp.Net Identity. I created a base controller that inherits the other controllers, it ordered CurrentUser method for the user and his SignIn:
protected ApplicationUser CurrentUser
{
get
{
var curUser = AppUserManager.FindByName(User.Identity.Name);
if (curUser != null)
SignInManager.SignIn(curUser, true, true);
else
curUser = new ApplicationUser();
return curUser;
}
}
protected ApplicationSignInManager SignInManager
{
get
{
return HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
}
I understand that these operations are unnecessary, when you refresh the page every time it is necessary to drag into the database, users receive and make SignIn, which is unnecessary.
I'm sure you can realize all without using Asp.Net Identity. For example by expanding IPrincipal User, adding him to the field name, which are needed when displaying pages and adding once Roles from the database and save all in Cookies.
Please, help me! And sorry for my bad english...

How do IIdentity, IPrincipal, OWIN, IdentityUser and IUser<string> fit together?

I am struggling to work out which .Net authentication concepts are still relevant in the world of OWIN, and which are now obsolete. From the pre-OWIN ASP.Net days, I am used to dealing with the .Net constructs: FormsAuthentication, FormsAuthCookie, IPrincipal, IIdentity and also custom implementations of IPrincipal (inheriting from GenericPrincipal). With the latest version of MVC (5) much of the authentication seems to have been changed be to OWIN based. Two things I am trying to understand in particular:
1)Where does IPrincipal and IIdentity and GenericPrincipal fit in?
With FormsAuthentication, custom data could be stored in the FormsAuth cookie. This could then used in the ASP.Net PostAuthenticate event to create a CustomPrincipal object, and override the default IPrincipal on the HTTPContext (per code example below). How (or does) OWIN change this?:
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
//Decrypt forms authentication cookie and retrieve some userdata
...
//Create CustomPrincipal (which inherits from GenericPrincipal)
var principal = new CustomPrincipal(userId, roles, someAdditionalUserDataFromCookie);
//Replace standard IPrincipal object on HTTPContext with custom principal
HttpContext.Current.User = newUser
}
2) Where can custom auth data be stored? In the pre-OWIN days I used the UserData value of the AuthCookie to store custom identification information (in addition to the username) - such as OrgID. Can this now be stored as a Claim in the ClaimsIdentity object? Is this a good idea? Can it still be stored in the AuthenticationTicket? Am I looking at this all wrong?!
Thanks for any help.
You will use CookieAuthenticationMiddleware instead of FormsAuthenticationModule. CookieAuthenticationMiddleware still creates a cookie with an authentication ticket but the format is different. With CookieAuthenticationMiddleware, things are designed for claims from the ground up. So, by default, you get ClaimsPrincipal with ClaimsIdentity although these classes implement IPrincipal and IIdentity.
Regarding custom authentication data, store them as claims part of the identity. One good thing about the new world is that you no longer need to use PostAuthenticate to restore your principal based on the custom data in the ticket. If you create your identity with all the required claims before calling SignIn, CookieAuthenticationMiddleware takes care of serializing claims part of identity into the ticket in the cookie and back into the identity in its entirety. Also, you will not use HttpContext.Current.User to read the principal. You will read from the OWIN context using the extension method available on the request object like so.
Request.GetOwinContext().Authentication.User returns ClaimsPrincipal
Request.GetOwinContext().Request.User returns same as above but as IPrincipal
From the controller, you can use User which is IPrincipal, which again returns the one from the context.

Manually associate session with current request asp.net MVC

I have a MVC 5 asp.net website where I need to expose a number of REST APIs to a stand-alone mobile client. The rest of the site is using Forms based security where it sets the ASP.NET_SessionId as a cookie, and that is used to authenticate the user with the request after they log in. With my mobile application, I am not able to use the cookie method because of the cross-doman issue. What I would like to do is add a header "X-SessionId" with the value of the ASP.NET_SessionId, then on the server side, have a filter that looks for that field, and if it is present, associates the request with the given session. (Client will log in with an AJAX POST call which will return the ASP.NET_SessionId upon successful login).
Is this possible?
Something like this?
public sealed class CustomSecurityAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext == null)
throw new ArgumentNullException("filterContext");
if (string.IsNullOrEmpty(filterContext.HttpContext.Request.Headers["X-SessionId"]) && IsAuthenticated(ilterContext.HttpContext.Request.Headers["X-SessionId"]))
filterContext.Result = new HttpNotFoundResult();
}
private bool IsAuthenticated(string sessionId)
{
// get your user details from your database (or whatever)
var user = new UserRepository().Get(sessionId);
if (user == null)
return false;
// build up an identity, use your own or out of the box.
FormsIdentity itentity = new MyIdentity(user);
// Set the user
filterContext.HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(itentity , user.Roles);
return true;
}
}
You are going to have to store current sessions in your database, so for example when a user logs in grab the sessionid and stick it in the db, so you know they have 1..n current sessions.
Then you can look it up as part of your authentication.
Edit:
Let's take a step back, never mind cookies and sessions for the moment.
You have a website and a restful api, they both servce different purposes and clients and have different security requirements.
So what are the most common options for securing your Api?
Basic authentication.
Most restful APIs require a username/password to be sent through with each request, as part of the headers or in the request itself.
An authentication token
You can provide a token associated with a user account (a guid could suffice) when requests are made you check for the token.
Using an existing protocal like OAuth
I would recommend using these common scenarios to be sure you don't miss something and open your self up to security vulnerabilities.
Is there a reason you can't use any of these?

how to retrieve Login Form password in Custom UserDetailsService

I have a Custom User class that extends the User(Spring Security's) class and Custome UserDetailsService class. This service queries the database using Hibernate service method to fetch user details. If there is no records found in the database for that userId, instead of throwing a UsernamNotFoundException, I want to create a dummy Custom user object and pass the authentication with read-only attributes. But I can't get it working because, I am not sure how to retrieve the password value entered by user on the login page. I need to pass it to the custom user constructor to get it authenticated properly..
So, to sum it up, is there anyway to retrieve password entered by the user on login page inside the loadUserByUserName() method? Thanks in advance
I am doing something in a similar vein a current project. I have just started getting into Spring Security over the past 2 weeks, but I've really dug into it during that time (attached source, went through it in the debugger).
I have a Custom User class that extends org.springframework.security.core.userdetails.User and a custom class that implements org.springframework.security.core.userdetails.UserDetailsService interface.
As you know, the signature of the loadUserByUsername method in UserDetailsService interface specifies that a class implementing UserDetails interface is going to be returned.
Spring Security is going to take the class that implements UserDetails and check the username and password provided by login form / basic authentication / digest authentication / (whatever authentication scheme you selected) against the Username and Password in UserDetails.
I have not found a way that you can get at the credentials provided by the end user via authentication scheme. If you want, I could try looking into it when I'm back at work tomorrow (I'm at home and writing this from memory.
I am running Spring 3.0.6 RELEASE and Spring Security 3.0.6 RELEASE.
I ran the code in my debugger. You will not be able to get at the Authentication object from the custom UserDetailsService.
However, I believe you may be able to create your own AuthenticationProvider that gets at it: http://static.springsource.org/spring-security/site/docs/3.0.x/reference/core-services.html
Please reference this code snippet from Spring Security's org.springframework.security.authentication.ProviderManager, which loops over the AuthenticationProvider(s):
for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {
continue;
}
logger.debug("Authentication attempt using " + provider.getClass().getName());
try {
result = provider.authenticate(authentication);
if (result != null) {
copyDetails(authentication, result);
break;
}
} catch (AccountStatusException e) {
// SEC-546: Avoid polling additional providers if auth failure is due to invalid account status
eventPublisher.publishAuthenticationFailure(e, authentication);
throw e;
} catch (AuthenticationException e) {
lastException = e;
}
}
As you can see, it loops over each AuthenticationProvider and passes in the Credentials. Hope that helps!
Philip
We are able to do something similar to what you're asking by extending AbstractUserDetailsAuthenticationProvider. There's an method retrieveUser(String _userName, UsernamePasswordAuthenticationToken _authToken) that you can override and put in your own custom logic. The return object is a UserDetails. So at this point you can create your own custom UserDetails and return it back to the framework (note: you can set your read-only attributes in this method as well).
At this point Spring Security will not have tried to authenticate using the password. They leave that to the additionalAuthenticationChecks(UserDetails _userDetails, UsernamePasswordAuthenticationToken _authToken) method that you can also override. Since this is where you would do your password validation it's ok to just skip the validation and let the method return. At this point your anonymous user will be validated.
Finally add this into your security.xml
<authentication-manager alias="authenticationManager">
<authentication-provider ref="appUserSecurityService" />
</authentication-manager>
I hope this helps!

Is there any good reason why the authentication cookie and the session state cookie are two separate cookies?

Is there any good reason why ASP.NET's session state cookie and the Forms Authentication cookie are two separate cookies? What if I want to "tie" them to each other? Is it possible in an elegant way?
Right now, I am stuck with the following solution, which works, but is still ugly:
[Authorize]
public ActionResult SomeAction(SomeModel model)
{
// The following four lines must be included in *every* controller action
// that requires the user to be authenticated, defeating the purpose of
// having the Authorize attribute.
if (SomeStaticClass.WasSessionStateLost/*?*/) {
FormsAuthentication.SignOut();
return RedirectToAction("Login", "Account");
}
// ...
}
#RPM1984: This is what happens:
[HttpPost]
public ActionResult Login(LoginModel loginModel)
{
if (/* user ok */)
{
// ...
Session["UserID"] = loginModel.UserID;
Session["Password"] = loginModel.Password;
// ...
}
else
{
return View();
}
}
And it doesn't take much guessing to know what WasSessionStateLost does.
Session != Authentication
The session state cookie tracks the user's activity during a browser session.
The forms authentication cookie tracks the user's authenticated activity during a given time period, specified by the expiration date of the ticket and whether or not you have created a persistent cookie (e.g "Remember Me" checkbox).
You shouldn't be touching the session cookie itself, and all it contains is an identifier to tie the client session (browser) to the server.
If you need to access the session, use HttpContext.Current.Session.
What exactly are you trying to "tie" together?
What does SomeStaticClass.WasSessionStateLost do?
I'll start with a solution, then an explanation followed by a recommendation.
Create a custom authorization attribute:
Since your application defines Authorized as follows:
Logged in
Must have values in Session["UserID"] and Session["Password"]
you need to define your own AuthorizationAttribute
public class AuthorizedWithSessionAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if(httpContext.Request.IsAuthenticated &&
Session["UserID"] != null && Session["Password"] != null)
return true;
// sign them out so they can log back in with the Password
if(httpContext.Request.IsAuthenticated)
FormsAuthentication.SignOut();
return false;
}
}
Replace all your [Authorize] attributes with [AuthorizedWithSession] and you shouldn't need to put session check code in your controllers.
I don't know enough about your application, but saving passwords in session (even worse in plain text) is not a secure thing to do.
In addition, as RPM1984 said, the session cookie and authentication cookie are separate.
Explanation:
Think of the session as a bucket of info (on the server side) with your name on it. ASP.NET can take and put stuff in that bucket. ASP.NET gives you a name, your session id, and puts it on the bucket so it can know which one is yours.
The authentication cookie tells ASP.NET that you're authenticated and stores your authentication name in it. The authentication name is usually set by the developer of the application and is usually a unique key (think primary key in a DB) to separate you from the other users.
Recommendation to be more secure:
Encrypt the passwords before your store them. This is not total security, but it beats storing passwords in plain text and of course, if someone were to get a hold of the encryption key, they can crack the passwords.
Rather than using session, which is short lived you could cache in the System.Web.Cache. With this you can add events that are called before an entry is removed and decide accordingly if the cache should be cleared. You can set a higher time-out value on that, with the added bonus that you're not storing the clear text password in a file or database anywhere. Another bonus is you won't be vulnerable to session hijacking.
Of course if the application pool recycles the cache is gone, and as it's in memory load balanced machines will be out of sync, but Velocity or another distributed, out of process cache system would solve that.
It's not perfect though, entries may be dumped due to pressure on the cache, and of course you know this is all a bad idea anyway, so I'll skip that lecture.

Resources