ASP.NET MVC project architecture problems — authorization and session - asp.net

I am finishing a project that started another programmer. Alter the entire architecture is not possible, but some things I want to overwrite. Namely - the authorization, and a way to store the current user session.
The project represents a client that communicates with the server through the soap-services. On the server, there is Security-Services, and several others, for example, A-service, B-Service.
Security service provides authentication and session key with which initialized other services.
The project is written in ASP.NET MVC3, the head of a user model, which is implemented as singletone-Class, which describes the methods of interacting with services.
How authorization works - there is CustomMembershipProvider with overridden ValidateUser method, which operates on Security-service. If successful authorization occurs the user registration in asp.net - FormsService.SignIn (model.UserName, false) and then initizalied user class:
class SiteUser
{
public static SiteUser Current
{
get
{
if (HttpContext.Current.Session.IsNewSession & &! HttpContext.Current.User.Identity.IsAuthenticated)
{
throw new UserAutorizationExeption () {Reason = AuthExceptionReason.NewSession};
}
if (HttpContext.Current.Session [sessionKey] == null)
{
FormsAuthentication.SignOut ();
throw new UserAutorizationExeption () {Reason = AuthExceptionReason.ServerSessionExpired};
}
return HttpContext.Current.Session [sessionKey] as W1User;
}
set
{
if (HttpContext.Current.Session! = null)
{
HttpContext.Current.Session [sessionKey] = value;
}
}
}
public SiteUser ()
{
}
public static SiteUser Create ()
{
SiteUser.Current = new SiteUser ();
return SiteUser.Current;
}
/ / Web-services methods go here
}
The main problem is that now the session is stored in memory:
web.config:
<sessionState mode="InProc" timeout="20" />
Set SqlServer-mode is problematic because it would be difficult SiteUser serialized. How can I get around this?
And there are problems with authorization - how to correctly do Asp.Net synchronization sessions with a session on services?
Sorry for my English, if needed clarification - ask questions. Thank you.

I personally prefer things simpler hence if I could, I would have a dedicated user to use the services so you do not have to impersonate the user down to the services layer hence having to maintain a session key.
Having said that it is not always possible, especially in a SOA environment where service layer does provide services to 3rd parties and auditing, etc. In fact my project looks like this.
You cannot get away from having a session if you need to impersonate the user to the service layer. InProc session provides better performance and SqlServer mode provides better scalability - decision on trade off is yours.
There is an alternative to store user's session key in the user table itself and retrieve every time and invalidate when user logs out. But this is only a custom implementation of user session.

Related

ASP.NET Core Session loading per request, Authentication or seperate Middleware?

Our application has a extra piece of a Middleware which is called after UseAuthentication and UseAuthorization. It's reponsible to load user data from cache or database. The data is then stored in HttpContext.Items.
We however recently felt that this is a little out of place. We currently believe, it makes more sense to handle this in a custom authorization handler. Since the authorization handler is responsible for setting the HttpContext.User. Setting the session, is extremely close in functionality to setting the User. Our application actually doesn't use HttpContext.User, but our custom Session object to keep track of certain data.
Overall the documentation doesn't clearly specific when to use custom Middleware or custom Authentication handlers.
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/?view=aspnetcore-6.0
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-6.0
Nothing relevant is mentioned in the performance considerations either.(https://learn.microsoft.com/en-us/aspnet/core/performance/performance-best-practices?view=aspnetcore-6.0).
Are there limitations or considerations that should be considered when deciding to implement custom Middleware or Authentication handles in .net-core?
public async Task Invoke(HttpContext context, ISessionManager sessionManager, ILogger<VarioClientSessionMiddleware> logger)
{
var token = ParseToken(context.Request.Headers.Authorization);
try
{
var session = sessionManager.GetSession(token);
if (session != null)
{
context.SetSessionState(session);
}
}
catch (InvalidSessionIdException ex)
{
logger.LogDebug("...");
}
await _next.Invoke(context);
}

Implement a Simple Authorization Function in ASP.NET Without Using ASP.NET Identity

I'm building a simple CMS using ASP.NET MVC 5 and Entity Framework 6. I have 2 sites: Public and Admin. Public site to diplay all the content and Admin site to manage all the content.
I only need a single Admin account to handle all the content in the Admin site.
I'm thinking to use a session to keep the logged in user data and check for the session details when accessing an authorized page.
Keep the user data in a session.
var obj = db.UserProfiles.Where(a => a.UserName.Equals(objUser.UserName) && a.Password.Equals(objUser.Password)).FirstOrDefault();
if (obj != null)
{
Session["UserID"] = obj.UserId.ToString();
Session["UserName"] = obj.UserName.ToString();
return RedirectToAction("UserDashBoard");
}
Check before accessing an authorized page.
public ActionResult UserDashBoard()
{
if (Session["UserID"] != null)
{
return View();
} else
{
return RedirectToAction("Login");
}
}
So with this approach I wouldn't need to implement advance ASP Identity functions for the authorization.
Is this approach correct and would there be any downsides using this approach?
NEVER EVER EVER EVER EVER use session for authentication. It's insecure for starters, and it won't survive a loss of session (which IIS can kill at any time, for any reason). Session cookies are not encrypted, so they can be grabbed and used easily (assuming a non-encrypted link, even if you use HTTPS for authentication pages).
Another issue is that you are doing your authentication way too late in the pipeline. OnAuthenticate runs at the very beginning of the pipeline, while you action methods are towards the end. This means that the site is doing a lot of work it doesn't have to do if the user is not authorized.
I'm not sure why you are so against using Identity, the MVC basic templates already roll a full identity implementation for you. You don't have to do much.
The downside is that you have to write it all yourself anyway. You already need role-based authorisation and have to write cludges. Identity already have this implemented and tested for you. Also keeping information in session is not very secure.
And you don't need to implement much yourself anyway. Yes, there are lot of functionality that you'll probably won't need, but just don't use it.
Don't build your own authorisation system. Since you ask this question, you are probably not qualified enough to make it secure.

asp web service: check if user is logged-in

I'm creating a web service that'll be called from a web form in asp.net. How does the web service check if the user is logged-in and if it is the logged-in user that's actually requesting the service?
thanks
It cannot. Since you're going to call the web service from ASP.NET, you're building a 3-tier application.
Tier 1 is the browser and tier 2 is ASP.NET web application. They share cookies and session variables, so ASP.NET can always authenticate the user. And you already know that.
Tier 3 is the web service. Communication between 2 and 3 is done over a different HTTP connection, sharing different cookies (actually none) and session variables (again, actually none because calls are stateless).
You then have no way to allow the web service on tier 3 to authenticate the client on tier 1.
HOWEVER...............
There is still a possibility, but only if your web service is local to your ASP.NET webapp. That's unlikely to occur, really, because web services are made for remote calls, not local calls. I don't think it's your case.
If this is a local web service, as djechelon suggests, They will share session state you are all set. Use djechelon's answer, ignore mine :)
If not: ask the larger question: what is stoping someone from calling your web service outside the context of your web app: using a tool like soapUI?
1) lock down your service (using WCF Security).
http://msdn.microsoft.com/en-us/library/ms731925.aspx
2) create a local webservice that checks authentication/authorization, and calls the webservice: passing the authorization information.
This is one approach that values the operation the WS performs over redundant Webservice calls. It is your disgression if a WS that calls another fits your performance needs.
You can Enable Session in WebMethod like this:
[WebMethod(EnableSession = true)]
public string DoSomthing(string para)
{
user = new SystemUser();
if (!user.Authenticate())
{//401 Unauthenicated}
}
Authenticate Method:
public bool Authenticate()
{
try
{
if (HttpContext.Current.Session["UName"] == null || HttpContext.Current.Session["Role"] == null)
{
return false;
}
else
{
this.Id = HttpContext.Current.Session["UName"].ToString();
this.Role = (Core.Role)HttpContext.Current.Session["Role"];
return true;
}
}
catch (Exception ex)
{
throw new Exception("Authenticate",ex);
}
}

Loading the initial state on a silverlight application based on asp.net session

I'm writing a silverlight application that resembles a shopping cart system.
This app can only be launched from the asp.net website after the user is logged in to the site.
Upon first load, the app will send a request to the backend through WCF service to retreive all the existing items in the shopping cart.
Therefore the silverlight app needs to know who the current user is, to find which shopping cart to load.
I found there are a couple of ways so far, but not happy with any of them:
using wcf aspnet compat. silverlight can ask who the current user is by asking the wcf service.
pass parameters from the page to xaml by using xaml.InitParameters and pass in the minimum amount of information to identify a user in a serialized format.
pass parameters through query string to xaml (apparently this is also possible)
Can anyone share the best practice to achieve this?
Thanks
We use the first solution in our projects. You haven't to invent any type of serialization format or so in this case. A disadvantage of this approach - extra async logic at startup.
The example of service:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class UserInfoService : IUserInfoService
{
public UserInfo GetUserInfo()
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
return null;
var userInfo = new UserInfo
{
Login = HttpContext.Current.User.Identity.Name,
Fullname = ...,
};
return userInfo;
}
}
Sending userid via initParams or query string is not good idea I think. Such things should be more hidden.
The real important thing is to verify user on server on each service call because anyone can call your services in similar way as your app.
HTH

How to provide a Session/Host object for use in both a windows and web application?

I have a web application that makes heavy use of the Session state to store information about the current user, their personal settings, record their session history and so on.
I have found myself retrieving this session information in my business layer, like so:
((UserSession)HttpContext.Current.Session["UserSession"]).User.Info
This poses a problem - at some point in the future my application will have a Windows client which obviously cannot reference the web Session state. So I need a host or customized session class that I can reference in my business layer that is agnostic of whether the application is running on the web or desktop. Something like:
IHost.User.Info
Behind the scenes, the web implementation will obviously utilize the Session state to store information, but I need to hide this away from my business layer. Has anyone solved this problem or got any practival advice on how best to approach this?
Help appreciated.
Assuming that the business layer is a separate DLL, I would never add a reference to System.Web and in consequence I would never use the Session object directly. This would lead to a different design of the business layer and of the exposed interfaces to a client (either web or winforms).
That said, as a quick workaround I would suggest to write a wrapper class in your business layer that hides the Session object from your code. Your calls from code will be something like this:
((UserSession) DualContext.Current["UserSession"]).User.Info
and the wrapper implementation will be something like this (not completed and tested):
public class DualContext
{
private Dictionary<string, object> winFormsSession = new Dictionary<string, object>();
private static readonly DualContext instance = new DualContext();
public static DualContext Current
{
get { return instance; }
}
public object this[string key]
{
get
{
if (HttpContext.Current != null)
return HttpContext.Current.Session[key];
else
return winFormsSession[key];
}
set
{
if (HttpContext.Current != null)
HttpContext.Current.Session[key] = value;
else
winFormsSession[key] = value;
}
}
}
It would take some re-architecting, but if you switch from using Session State to User Profiles you could then use Client Application Services to share the information.
http://msdn.microsoft.com/en-us/library/bb384297.aspx
I guess you need to create a webservice or RESTfull service. The service will return an XML file representing your user information. You will be able to invoke the service wither from you windows or web application.

Resources