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);
}
}
Related
I am working on an ERP asp.net mvc 5 web application deployed under iis7. And now I want to implement a new scanning service, which mainly uses powercli and power shell scripts, and scan our network for servers & vms and get their specifications and their statues.
So I am thinking of the following approach:-
1.Since the scanning should be access by only specific users and requires the hosting server to have powercli and other tools installed, so I want to create a new asp.net mvc 5 web application , and deploy it under iis7 instread of modifying my current ERP syste,. Where the new application will have the following action method which will do the scan as follow:-
public ActionResult ScanServer(string token)
{
// do the scan
//send n email with scanning result
}
2.Now inside my current ERP system I can manually initiating the scan by calling the above action method as follow:-
[HttpPost]
[CheckUserPermissions(Action = "", Model = "Admin")]
public ActionResult Scan()
{
try
{
string currentURL = System.Web.Configuration.WebConfigurationManager.AppSettings["scanningURL"];
using (WebClient wc = new WebClient())
{
string url = currentURL + "home/scanserver?token=*******" ;
var json = wc.DownloadString(url);
TempData["messagePartial"] = string.Format("Scan has been completed. Scan reported generated");
}
}
catch (WebException ex)
{
TempData["messageDangerPartial"] = string.Format("scanningservice can not be accessed");
}
catch (Exception e)
{
TempData["messageDangerPartial"] = string.Format("scan can not be completed");
}
Now I did a quick test where I manually started the scan from the ERP and the scanning service deployed under iis worked well.
But I have these questions:-
The scanning service might take 20-30 minutes to complete. So from an architecture point of view is my current approach considered valid ? I mean to initiate a scan by calling an action method from another application ?
Now can i inside the scanning service web application, to force it to call its action method on a timly basis (for example every 4 hours)?
Thanks
Your best option would be to write a windows service to install on the webserver alongside the web app. This windows service can use threads or a timer to execute a long running task (such as scanning your network) at a specified interval and send an email when finished.
You can talk to your service from the app using the database, a config file, or maybe even a registry entry.
If this will not work for you, you can look into some task scheduling apps such as Quartz.NET. If you do use a windows service, I recommend the excellent TopShelf which makes it easy to create and deploy. Here is a nice blog post I found by Scott Hanselman that may help.
I'm looking for some guidance on how to implement authorization security for SignalR on a back end service running in a self-hosted (non-IIS) environment, that is called from a Web application. The backend app is basically a monitor that fires SignalR events back to the HTML based client. This all works fine (amazingly well actually).
However, we need to restrict access to the server for authenticated users from the Web site. So basically if a user is authenticated on the Web site, we need to somehow pick up the crendentials (user name is enough) and validation state in the backend app to decide whether to allow the connection as to avoid unauthorized access.
Can anybody point at some strategies or patterns on how to accomplish this sort of auth forwarding?
I am having similar issues here, as in my web app I use a simple cookie authentication system which uses an AoP style approach to check for any controllers with an attribute, then will get the current context (be it from the static HttpContext.Current or from the target invocation object depending on the type of interceptor) and then verify the cookie exists, it contains right data, then finally verify the token with the db or cache etc.
Anyway this approach can also be used for Signalr, although its a bit more long winded and you are using dependency injection. You would basically wrap the hub calls with the desired attribute, then set up your DI/IoC configuration to intercept these calls, then either get the hub instance within your interceptor and get the cookie (or your custom authentication mechanism) from the request, verify it is all valid or not, and if not then throw a new HttpException("403", "Not authenticated"); which should kick the user out and return back before it even hits your hub method, this way you can put the logic in one place (your interceptor, or a class the interceptor consumes) then just wrap any method that needs to use this authentication using your attribute.
I use Ninject and the interception extension, but most major DI frameworks these days have some form of IoC plugin/extensions, such as Autofac, Windsor, Spring etc.
If you were not happy going down the route of introducing DI and/or AOP to your current project, then maybe you could just create a custom hub instance which contains your authentication logic and then just use that in your hubs, so ok you will still be manually calling some authentication logic from within each hub method you want to protect, but its less code, so something like:
public class AuthorisableHub : Hub
{
private ISomeAuthenticationToken GetSomeAuthenticationTokenFromRequest(Request request) // probably a SignalR specific request object
{
// Get your token from the querystring or cookie etc
}
private bool IsAuthenticationTokenValid(ISomeAuthenticationToken token)
{
// Perform some validation, be it simple or db based and return result
}
protected void PerformUserAuthentication()
{
var token = GetSomeAuthenticationTokenFromRequest(Context.Request);
var isRequestValid = IsAuthenticationTokenValid(token);
if(!isRequestValid)
{ throw new HttpException(403, "<Some forbidden message here>"); }
}
}
public class MyFancyPantsHub : AuthorisableHub
{
public void TellAllClientsSomethingSecret(ISecret secret)
{
PerformUserAuthentication();
// Do stuff with the secret as it should have bombed the user out
// before it reaches here if working correctly
}
}
It is not perfect but would work (I think), also I am sure I once read somewhere that Hubs are newly instantiated for each request, and if this is indeed true, you could possibly just put this logic in your constructor if you want to apply the authentication to every action within the hub.
Hope that helps, or gives you ideas... would be interested in knowing how you did solve it in the end.
SignalR does not provide any additional features for authentication. Instead, it is designed to work with the authentication mechanism of your application.
Hubs
You should do authentication as you normally would and then use the Authorize attribute provided by SignalR to enforce the results of the authentication on the Hubs.
The Authorize attribute can be applied to an entire Hub or particular methods in the Hub. Some examples:
[Authorize] – only authenticated users
[Authorize(Roles = "Admin,Manager")] – only authenticated users in the specified .NET roles
[Authorize(Users = "user1,user2")] – only authenticated users with the specified user names
You can also require all Hubs to require authentication by adding the following method in the Application_Start method:
GlobalHost.HubPipeline.RequireAuthentication();
Persistent Connections
You can use the user object in the request to see if the user is authenticated:
request.User.IsAuthenticated
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.
I am currently working on an iPhone application. This application calls back to WCF services exposed through my ASP.NET web application. Currently, my WCF operation looks like the following:
[OperationContract]
[WebInvoke(Method = "POST")]
public string SubmitMessage(string message, int priority)
{
try
{
// Process message
// Return success code | message
}
catch (Exception)
{
// Return error code | message
}
}
My web application is using ASP.NET Forms Authentication. My challenge is, I only want authenticated users to be able to call this operation from their iPhone. I know that the iPhone SDK has baked in support for XML. However, I’m not sure how to lock down my WCF operation such that only authenticated users can access it.
How do I make my WCF operation only accessible to authenticated users from third party applications?
Thank you
This has to be done in both sides of the transfer, namely server (WCF site) and client (iPhones).
If you're using SOAP endpoints then you should look for Objective-C SOAP client libraries. This way all you will have to do is to setup best security options to your needs and your server-side code will be almost identical as it is at the moment.
Instead if you're exposing as RESTful endpoints I suggest you to look for an OpenID(&OAuth) approach. Here also, there are .NET and Objective-C libraries available. I belive this solution would require much more coding in both of the sides.
I am using a web service which sets the Thread.CurrentPrincipal object while logging in and soon later when another webmethod of the same web service accesses Thread.CurrentPrincipal, its different/resets
Can someone tell me if this is expected or can different webmethod calls from the same client can access the same Thread.CurrentPrincipal object
Thanks
As soon as you stop using a thread it goes back into the thread pool.
The next call will take a thread from the thread pool, but you have no control which one you get.
You need to send information about which user is making the call, with each request.
This is expected, every new web request is actually new thread. And every web request reset stuff like CurrentThread, CurrentCulture and so on.
What are you trying to do is authentication session. There are many possible solutions. But to suggest something I have to specify technology you use.
For example, ASP.NET ASMX Services can use Forms Authentication. Also they are aware about ASP.NET Session.
With WCF, you can enable ASP.NET support, so you will have same stuff like for ASP.NET ASMX Services. But you also can leverage on Windows Communication Foundation Authentication Service.
Anyways need more info from you.
If you are using the built-in ASP .NET authentication for your website and then just calling the web service from a web page, you may be able to enable session variables and user context information in the methods of the web service with a decoration. Like this:
[WebMethod(EnableSession=true)]
public void MyWebMethod()
{
string mySessionVar = HttpContext.Current.Session["sessionVar"].ToString();
IPrincipal currentUser = HttpContext.Current.User;
...
}
If that doesn't solve your problem, tell us what are you using the Thread.CurrentPrincipal object for (what you are pulling out of the Thread.CurrentPrincipal object). Perhaps there is another solution.