I have an MVC4 ASP.net financial application with a WCF service. The current scenario isn't secure enough and I need you help with that.
The current scenario:
The user login using a login form, and I send his login details using a JSON object containing the UserID and the Password to the WCF service:
http://example.com:22559/Login
This returns a JSON object with a true or false.
If it's true, I use the ASP function
FormsAuthentication.SetAuthCookie(loginModel.UserID, loginModel.RememberMe);
to set authorization cookies to use it later.
When the user adds a new Transaction I send a JSON object containing the transaction details without the password to:
http://example.com:22559/AddTransaction
I depend here that the MVC controller will not allow the user to access the transaction page if he isn't logged in.
The problem is anyone can now sneak-out and add a transaction without entering the password!, using the URL:
http://example.com:22559/AddTransaction
What I need to do now, is to make the WCF service itself secured, but I don't know how to do that without making the user enter his username and password each time he adds a new transaction!, so, what is the proper way to do that?
Thanks in advance.
MVC 4's controllers typically use MemberShipProvider for authentication and RoleProvider for authorization. So your WCF services may share the providers.
For authentication, you don't need to do anything in WCF codes. For authorization, it is handy to decorate respective operation implementation function (not interface) with PrincipalPermissionAttribute with the Role name defined. The rest will be done in config and by runtime.
For more details, just search "membershipprovider wcf", you will find a lot articles/tutorials in MSDN, CodeProject and StackOverflow.
Please be mindful that in MVC 5 if you will be moving to MVC5, Identity 2.0 is used by default, and MembershipProvider and RoleProvider will not be their by default. Nevertheless, your WCF codes should remain unchanged, and only some elements under ServiceModel will need to adapt the new custom authentication and authorization, and the client codes should remain the same as well, no config change needed.
Related
In "old" ASP.NET I could build a custom authorize attribute and override HandleUnauthorizedRequest. I cannot seem to do this with ASP.NET Core using a custom authorization handler. The latter either "succeed" or "fails" and I would like to redirect to alternative controller actions based on the nature of the failure.
Here's the scenario. Users of my web app have a claim which indicates that they are "active" users, i.e. they have fully registered and we have validated their details etc. New users have been authenticated using the OpenIdConnect middleware but, until we have fully validated and set up their account, do not have the "active" user claim. Thus, both new users and active users have been authenticated. I want to prevent new users accessing most of the application. Every time they try to get to https://app.example.com/dashboard I want to redirect them to a https://app.example.com/newuser page, from which they can go through the set up process.
I can use an authorization policy on my controllers to check for the presence of the "active" user claim and allow access. When a new user doesn't have this claim, and fails the authorization, I want the authorization handler to have some logic which then redirects them to an area of the app which they do have access to. But I cannot see how to do this using the authorization framework in ASPNET core.
There is a somewhat clunky solution which uses the CookieMiddleware and implements a handler for the OnRedirectToAccessDenied event - see https://github.com/aspnet/Mvc/issues/4890. I also thought about implementing an action filter which runs on every request.
Am I just being stupid here? Surely, it makes sense to want to carry out some action on authorization failures which doesn't just send the user off to re-authenticate.
After some digging about and referring to the wonderful book, Pro ASP.NET Core MVC (6th Edition, Adam Freeman), the simple answer to my question is to create an Authorization Filter. This implements IAuthorizationFilter with a single method OnAuthorization(AuthorizationFilterContext context). In this method do whatever you need to do to check the request. If it fails authorization simply set the context.Result property to some IActionResult, in my case RedirectToActionResult. If the request passes authorization do nothing.
You can also use dependency injection in the filter - fantastic.
There is no mention on how to implement or code samples for IAuthorizationFilter on the Microsoft ASP.NET docs site. Thanks are to Adam Freeman.
I have been going around in circles trying to properly understand this.
I have an ASP .Net MVC project I am working on and need to implement user logins that authorize and authenticate against en external system (via webservice).
I can't seem to get my head around MembershipProvider and AuthorizeAttribute in the context that I require.
Which do I need to use (I believe its both) and where do I need to customize to provide the authentication against an external system.
There is one additional thing I also require on top of the default ASP .Net user principals in that the external webservice will return a session ID upon successful login that would be used for subsequent requests to external services.
Would someone be able to point me in the direction of some useful example of this sort of set up?
MembershipProvider is used to provide the users that may login the system. The RoleProvider is used to tell which roles a user has. They are used during the authentication process. i.e. identifying the user. You can read about membership vs roles
The [Authorize] attribute on the other hand is used during authorization. i.e. to check if the user is allowed to do something.
We are starting with a new application build with Asp.net. It should connect to a webservice which is already available to retrieve data to present to the user. We've created a repository which communicates with the webservice.
The webservice needs authorization with the same user credentials which the user uses to logon to the web application. The user is authorized with Forms Authentication with cookie support.
The problem is that we cannot retrieve the password from the user on new requests when the user is once authorized and automatically logged on. This password is needed to logon to the webservice from the repository classes.
Any ideas on how to implement this the best and safest way ?
You can try using Client Application Services to get and set the cookie. Or you can manually get and set the cookie using the sample code on this post. The example shows both methods and is geared specifically to passing a forms authentication cookie from an MVC application to an OData WCF feed:
http://blogs.msdn.com/b/astoriateam/archive/2010/07/21/odata-and-authentication-part-7-forms-authentication.aspx
Also, here is a similar example that is trimmed down in scope:
http://www.codeproject.com/Articles/190806/Send-Cookies-When-Making-WCF-Service-Calls
I've implemented a custom ASP.net membership provider to deal with forms authentication. The custom provider uses a custom User object for authentication and authorization. I was wondering If I can pass this object to each WCF call without adding it to the parameters list?
Since you are already using a MembershipProvider you can utalize that on wcf as well so both are secured by the same mechanism.
See this post on msdn.
Windows Communication Foundation (WCF)
developers can take advantage of these
features for security purposes. When
integrated into an WCF application,
users must supply a user name/password
combination to the WCF client
application. To transfer the data to
the WCF service, use a binding that
supports user name/password
credentials, such as the WSHttpBinding
(in configuration, the wsHttpBinding
Element) and set the client credential
type to UserName. On the service, WCF
security authenticates the user based
on the user name and password, and
also assigns the role specified by the
ASP.NET role.
Another option would be to create a custom IAuthorizationPolicy that pulls off your user via
OperationContext.Current.IncomingMessageHeaders.GetHeader<T>
And than setup your principal like the following:
evaluationContext.Properties[Constants.EvaluationContextPrincipal] = principal;
Here is some more information on creating a custom IAuthroizationPolicy. With this method you could achieve what you want without passing your user to the method.
Just be warned if you go this route a crafty person could end up impersonating the user by simply suppling a bogus user in your header.
Using the asp.net membership provider for wcf would most likely get you what you are really after plus adding some security.
You definitely should not add this to the parameters each method.
I do not know about your custom user object but as far as WS* and most security standards concerned, your user object will have username and password.
The answer depends on the binding you use. BasicHttpBinding or BasicHttpContextBinding can use HTTP authentication schemes while WsHttpBinding can use custom Message security which you can provide user name and password.
BasicHttpContextBinding is especially good since it can work with ASP NET session.
I'm writing an admin panel in ASP.NET for an existing set of web service calls. My goal is to use some of the existing login stuff (locking out pages if your not logged in) etc but using my login mechanism. This works by hitting an http post request with a username and password, if you're good you get a session id back, if not you get a 401. Here is the WCF for that:
[WebInvoke(UriTemplate = "/Login/", Method = "POST")]
public String Login(User user)
{
// If we are good return sessiond id
// Otherwise throw 401 etc
So to get this working in ASP.Net what is needed?
I think this:
Implement a user that overrides MembershipUser and has a session id in it.
Implement a membership provider that overrides MembershipProvider and does all the WCF calls etc.
In the Web.Config set up a custom membership provider.
Is this correct or am I missing something major?
Rather than do this yourself, you might want to take a look at the WCF Authentication Services.
Before you go down this route, be aware that the authentication services supports login and logout, but that is about it. The usual Membership methods such as CreateUser aren't available. If you need them, you'll need to create three projects:
A WCF Service Application with a single service called WCFMembershipService that wraps the core Membership Provider requirements, i.e. calling Membership.Provider.Method(). Configure the standard SQLMembershipProvider in the web.config, and
A custom membership provider to be used in the ASP.NET application that calls your WCF service from step 1, and
An ASP.NET Application with the custom membership provider configured
You will find that the Membership and Role providers are extremely easy, but the Profile provider is more challenging, because you cannot serialize the default properties that the provider requires, such as SettingsPropertyValueCollection.
In this case, you would need to convert the SettingsPropertyValueCollection into a serializable type first, and then reconstruct it at the other end. Probably a Dictionary<string, string>() would suffice.