I currently have a service which is secured by TransportWithMessageCredential over https. This works great! I now need to add a bit of granularity to some operations on this service.
Lets say I have this method public IEnumerable<Project> GetProjects() now I need to add an additional method which will limit the projection to projects which the current user has access.
Is using code like this:
var uid = System
.ServiceModel
.OperationContext
.Current
.IncomingMessageProperties
.Security
.ServiceSecurityContext
.PrimaryIdentity;
var returnProjects = context.Projects.Where(p => p.ProjectManager.Equals(uid.Name));
going to leave me vulnerable to any type of attack?
I think this should be fine, since WCF will hit my custom UserNamePasswordValidator first and "authenticate" the user, then the code I have above will "authorize" them to get only their projects. Is there a flaw in my thinking here?
No, that is perfectly valid thinking. This is exactly the way that we implement user-specific security (with the minor exception that we use FormsAuthentication for identifying the user).
Before each request is processed, we always check the user and if there is anything suspicious about the request, we throw an exception.
Related
Baisicly the thing I wanna do is find out if the request to my wcf service was made securely. And I use the following code.
context = OperationContext.Current;
bool isSecure = context.IncomingMessageHeaders.To.Scheme == Uri.UriSchemeHttps;
is this a proper way to do that ? If you don't understand what I mean and what I want to achieve I can provide more details.
You can check Request.IsSecureConnection
See MSDN documentation
I guess you want to check because you are going to execute different logic depending on whether the connection was secure or not.
In this case, I would take a different approach. Rather than check in the service code and switch the control flow, you could consider implementing the different logical flows in different endpoint behaviors - configure one one for the HTTP endpoint and the other for HTTPS endpoint.
This feels like better encapsulation that the approach of checking the operation context and would likely be more testable.
I'm designing restful service and one of the entities to maintain - user accounts. I'm doing it in .NET and using membership provider.
Here is what I have:
/users/ GET - returns list of users
/users/ POST - can create or update
multiple users (post array of User
objects)
This POST won't matter if you updating or creating user
Problem I have: How do I create service to change password? Changing password is separate from updating users procedure. I'm thinking something like:
/users/{userName}/password POST - to
change user password.
But then I have to pass different object here? (I use JSON)
Do you have any suggestion on how to layout URL? And should I really create another object? MembershipProvider requires old and new password to change
Well the question has to be whether we see the password as a resource in its own right, or not.
In my user dbs, I store all my passwords (salted and stretched) in their own table, so I can easily present the password as a separate resource. But just because you don't have that fine grained control doesn't mean you can't do the same - but I wouldn't consider implementing a GET for the password, ultimately you need an authentication service for that, which should follow some kind of protocol.
A rest service is free to represent its data however it wishes, with no real regard for the underlying structure so, given that, I think you're free to do it as a separate resource if it makes sense in your case.
You could include in your user data a uri to be used for changing the password. The client would have to know the type of data to send (so yes you will need a dedicated resource type to handle the change request), and that the uri should be triggered with a POST request.
If I understand your question, you'd like suggestions on how related to the Uri layout itself. The suggestions below is related specifically to designing a Uri that someone can use to change a password.
Never include any sensitive information in the clear in URIs, even if it comes over HTTPS, as that information may be written to log files on the server, or worse, recorded by analytics or monitoring software. Make sure sensitive information is sent as part of the body or part of the header.
Here are a couple of considerations why changing a password with a RESTfull service may require its own Uri:
Prevent accidental changes to a password when updating a user details.
Whenever this method changes, you may need additional security reviews as any defects therein that allows a anonymous user to change the password of an existing user will allow that anonymous user to hijack the account.
You may also want to include other additional security features like notifying a user that their password has changed and invalidate any OAuth tokens issues to applications. The membership provider is great, but doesn't provide this additional measures.
Since it is a different Uri you can monitor its usage and correlate it to IP Addresses allowing you to detect whether someone is trying to compromise a user account.
You can just PUT a data contract to https://example.com/users/{id}/password:
[DataContract]
public class ChangePassword
{
[DataMember]
public string OldPassword { get; set; }
[DataMember]
public string NewPassword { get; set; }
}
The latter assumes you'll authorize whether the client can actually perform this action. You may want to look at PUT vs POST in REST whether to use PUT or POST. In addition, the book RESTful Web Services and REST API Design Rulebook has been invaluable to me when designing RESTfull services, including Uri layout.
I have a bit of a unique situation here. I'm making a web application that is going to have
the ability to login with different web applications credentials. For example you can login/register with my site or you can login/register with your YouTube account. I'm not using OpenID because I need to have access to YouTube's data in this case.
I'm using ASP.NET MVC 3 EF4 with custom Membership, role, profile providers.
The problem is user names can't be unique because someone with a YouTube user name could have the same user name as someone that registered with my site. So I got around with by specifying a user type in my user table. This is pretty much a composite key (user id and user type).
I have a custom authorize attribute that is checking for the role that the user is in but now I need to implement a custom IPrincipal because I need to pass a user type. Only problem is where do I store that? the session?
Originally I thought this is what the Application table was for, and I had momentary success with that but read there is threading issues, and I was getting session faults all over the place it wasn't that great :(
I'm wondering what the best way to do with is because I can't use the overridden methods in the providers because I have to add a UserType parameter to some of the methods, but then this breaks the functionality of the provider.
EDIT:
I basically need to have the ability to change the ApplicationName at runtime pro-grammatically. I tried doing this, the only problem was when I stopped my development server but left my browser open then ran my dev server again it wouldnt keep the application name.
EDIT:
I've changed my application to use OAuth, I never found a good solution.
I basically need to have the ability
to change the ApplicationName at
runtime pro-grammatically. I tried
doing this, the only problem was when
I stopped my development server but
left my browser open then ran my dev
server again it wouldnt keep the
application name.
If you need to change the ApplicationName, this means you need to select a provider at runtime.
The only way to do this is to NOT use the singleton "Membership" as it uses the provider defined in web.config.
Instead each time you need your provider use :
MembershipProvider userProvider = Membership.Providers[UserProviderName];
Just set UserProviderName the way you want. I would go with a custom global authorization or preAction filter which detect the provider from some cookie or other session variable and put the provider in the HttpContextBase.Items collection which lives for one and only one request.
The best answer to this problem is answered on stackoverflow here: Membership provider with different ApplicationName in area
Here's the code they used:
Membership.Providers["MyOtherProvider"].ValidateUser(username, pwd);
Ryan,
Hmmm... can you work-around the problem by prepending the issuing-authority (local or YouTube) to the username field itself... Example usernames: "LOCAL/corlettk", "YOUTUBE/corlettk"???
Ok, you'll need a custom Authenticator in order to split the complex-string, and flick-pass the login-request to appropriate underlying Authenticator... but once that's done, (I guess) you're all set to deal EASILY with the much bigger problem (from your perspective) of Authorisation.
I percieve that you're a smart guy... have you considered-and-dismissed this approach allready?
Cheers. Keith.
PS: Yes, I'm a hacker... but I have bad habit of hacking stuff up that WORKS... so they've given-up trying to educate me.
The current situation is as follows:
We have an production .net 3.5 WCF service, used by several applications throughout the organization, over wsHttpBinding or netTcpBinding. User authentication is being done on the Transport level, using Windows integrated security. This service has a method Foo(string parameter), which can only be called by members of given AD groups. The string parameter is obligatory.
A new client application has come into play (.net 3.5, C# console app), which eliminates the necessity of the string parameter. However, only calls from this particular application should be allowed to omit the string parameter. The identity of the caller of the client application should still be known by the server because the AD group limitation still applies (ruling out impersonation on the client side).
I found a way to pass on the "evidence" of the calling (strong-named) assembly in the message headers, but this method is clearly not secure because the "evidence" can easily be spoofed.
Also, CAS (code access security) seems like a possible solution, but I can't seem to figure out how to make use of CAS in this particular scenario.
Does anyone have a suggestion on how to solve this issue?
Edit: I found another thread on this subject; apparently the conclusion there is that it is simply impossible to implement in a secure fashion.
sounds to me like you need to pull the security out into a seperate service ... go down a more federated route this way you can implement a handshake form of encryption using public and private keys to generate a secure session token in both situations.
this way you cna still get both windows a=uthentication and a custom solution in play whilst retaining your attributes on methods for security (I am assuming that you are implementing it this way.)
sounds like a fair bit of work though - I had to do this from scratch and ran into some cross domain / delegation issues. But I am sure the idea is good.
howver you will end up with a nice solid claims based secuirty model
You could get the callers Address:
RemoteEndpointMessageProperty clientAddress =
OperationContext.Current.IncomingMessageProperties[RemoteEndpointMessageProperty.Name]
as RemoteEndpointMessageProperty;
string address = clientAddress.Address;
My applciation works as follows
[user]----username/password/domain----->[WCF service]
then i access the domain server to see to which actual DB the user is associated,
after getting that, i validate the user in his actual DB(DB is per domain)
the problem is that i need a place to store the domain name for the following requests against the db.
for example,if the users calls a WCF service operation:
Test()
first the validation procedure is called, (WCF UserNamePasswordValidator) which validates the user password(which is sent as part of the header for REST or as part of the SOAP), and the next function to be called is the Test, but by then i cant tell the domain of the user(to actually serve the request agains that domain..)
I dont want to change the signature of each domain to
Test(string domain)
I cant simply access the headers since i expose the same methods both as REST and as SOAP and the authentication is different for each of them..(one is with headers as with Amazon S3 and the later is using the SOAP standard)
so basically i'm looking for a global, per call storage.(i want to avoid the Per-Call initiation method)
thanks.
EDIT:
Maybe i should use the ThreadStaticAttribute? will that work?
This will not work. You can't store anything in UserNamePasswordValidator. It even doesn't have access to OperationContext because it runs on different thread.
The way to do this is create custom message inspector and extract the information from custom message header to custom operation context extension as Frank mentioned.
WCF knows a Current OperationContext. You can write your own extensions for it. Unrelated to this issue, I used the same mechanics in this NHibernate Session management here, which may work in its concept for you as well. It accesses the InstanceContext, but the concepts are similar.