I am developing an Android project where I need to connect to the backend C# service to get data.
I am thinking of using JSON to avoid the SOAP message overhead. What is the best way to implement the security for the JSON request to make it not accessible to public and only accessible from the dedicated users.
I am think of getting a token (or SessionID) from server after login using SSL and for all the service calls after login will be using this token to authenticate.
But how should I use the token after login -
1).through HTTP (can it be easily intercepted?)
2).through HTTPs (will there be performance issue if every call is made through HTTPs?)
Could you give some guidance on how to implement it to be secure without effecting performance?
UPDATE!
The Android application is in Hybrid mode which is consisting of webviews and native activities.
How should I maintain the session if the token is base on session? The user can just login and inactive for long period. Should I just increase the session timeout?
I would suggest using SSL even after you acquire the token. Our company deals with projects with banks and health related secure data and we are mandated to use SSL even after the token implementation. We found that the performance is still within reasonable limit even after using https.
Using Https would not be a huge performance hit especially considering the implication of someone could be sniffing your packet and get the token (given we don't know the access point that the user might be connecting to).
The overhead associated with SSL will happen during the initial handshake since it needs to basically exchange key and encryption algorithm via RSA. However once you pass that initial handshake, the cost is related only to encryption/decryption of the packet and that will not be a huge impact to your app.
As a side note you could also implement security using client certificate on your app to make sure that only the app can make the call to the webservice. This would further secure the call since the hacker would need access to the certificate in order to gain access to the server. Even if they know the login, they cannot access the endpoint without the certificate.
SSL will affect performance some but not too much (from what I've experienced). I would use a semi-secure hash based on something like this:
MD5SUM or SHA1 the following: today's date + some punctuation + something unique about the user (perhaps email, etc…). This would give you a long string looking like ajadfh28dfj2yadsfh28… As long as your Android side sent it in the same way that the server side is expecting it and it's unique between users, to me it would be pretty secure.
To do it the WCF / Microsoft recommended way, you implement WCF authorization using a Role provider.
That includes an IPrincipal, and injecting your custom principal, which will have the roles loaded from a database, LDAP, etc.
Then, any WCF methods can simply be decorated like so, for authorization:
[PrincipalPermission(SecurityAction.Demand, Role = "ADMIN")]
[PrincipalPermission(SecurityAction.Demand, Role = "OPERATOR")]
public void SomeServiceCall(string foo)
{
// In your case this would be an AJAX endpoint, not a void method
}
That will protect the service calls; they won't even appear to exist to the caller.
Starting points: http://msdn.microsoft.com/en-us/library/ff647040.aspx
Microsoft provides sourcecode to a sample role provider.
Keep in mind, too, it is not required to implement a full Membership provider, though many people think so. You only need a custom validator and Role provider for this. Much of the membership provider can be left unimplemented.
Related
We have an application which features different levels of users. This is not a "security feature", this is more to prevent that users change anything that is not related to their role.
Also, the server is not public and only available on local connection(network not accessible from internet).
We would like to use credentials, but we would like that no encryption and ssl is required(because the service has sometimes a lot of data to transfer and we don't want to "loose" time to encrypt/decrypt each time).
Is this possible? What should be used as Security Mode?(we do configure our services in the code, not through XAML).
Thanks
I would want to know more about the use case you are looking for.
But assuming that you are just trying to prevent anonymous access of an application, you may go for a windows authentication if you are using AD based workstations. If not then you may need to rely on custom authentication which just pops up a challenge before allowing you through.
EDIT: Based on your comment, I understand that you are using CustomUserNameValidator in WCF for auth. Understand that it is not a mandate to use certificate when you are using this. However, certificate improves the security. If you are absolutely sure that your network is protected and snoop-free, you can use self signed certificate using makecert. However, i will always advise to purchase a certificate.
A sample is found here https://blogs.msdn.microsoft.com/pedram/2007/10/05/wcf-authentication-custom-username-and-password-validator/
You can also choose to use HTTP custom binding with plain username / password without any certificate involved
I have a simple service contract, defined as:
[ServiceContact]
public interface IEcho
{
[OperationContract]
void Hello(string value);
}
which is implemented in a local WCF service (accessed through a net.pipe:// address).
I need to know who is calling the service.
Basically, I need to reject the calls to IHello.Echo made from any assembly not signed by me, for security reasons. The Hello method should not be available to untrusted callers.
I vaguely remember that in the old .NET 1 remoting days, we could walk the stack and check the identity of the callers. But how can I do this with WCF?
You can't authenticate the caller assembly. Caller of the service resides in a different process that you have no access.
Instead you need to use any solution that provides client authentication in WCF. Since you are using named pipes, you should look into message level authentication (as opposed to transport level).
In WCF you can interrogate CLientCredentials object if you have authentication turned on.
You could also secure the service usign a certificate ... that way you know whoever is calling it has been issued the certificate ... that isn't the same as a signed assembly ... but it is the same as a certified caller from a known source.
You do that with the ServiceCredentials part of the web.config ... it is quite flexible in how you choos ethe certificate. If you wan tto lock down who can call the service i recommend this.
If you want to be in control of a list of people who can register and unregister than go for some kind of user storage and authentication . authorisation mechanism that calls off to a database.
response to comment:
Yeah fair enough. However in the situation with trusted assemblies the malicious user can simply copy the assembly. So i think you are strawmanning slightly tbh. One involves reverse enginnering the other requires xcopy.
Given your new requirement:
You need to write some kind of authenticator service that generates a pseudo random sequence has some kind of handshake using a revocable one time use certificate to sync up. There are several examples around ... you are getting into the territory of STS servers and authentication providers. In reality you probably want a window to resync over time and a pseudo random generator that can spit out the nth number in its sequence quickly. the algorithms exist but you are getting into the kind of realm where you need to be highly qualified to start giving advice without 3 pages of saying 'don't quote me this is hard shit'. I'd rather describe how to implement an encryption algorithm tbh - and i wouldn't do that either.
There is a saying with computers if you want a secure computer lock it in a safe, dump it in the ocean. It is logically impossible to be secure - you just have to determine the lengths you want an attacker to go through.
The fact is if you are in a trust situation you should know a lot of information from mac address to ip to certificate. you can revoke those credentials at any time and reestablish them. But if someone presents the correct credentials then to say they are not who they say they are is the same as saying a chair is not a chair - its being paranoid. the trick is to gather the evidence to make the decision.
If you want bullet proof authentication go out and buy it - it will cost you a lot of money
I've come across other questions along the same lines:
How do I securely authenticate the calling assembly of a WCF service method?
How to authenticate client application for trust of messages sent from it
and apparently, there is no secure way of making sure the sender of the message is indeed a specific strongly signed assembly. There is always some way a malicious assembly could spoof its identity.
In short, the answer is: it is impossible.
I'm building an application that syncs data between users' Exchange Server accounts (version 2007-2013 supported) and the application.
The application can't use impersonation (at least not in the typical case) as users could be on any number of domains and exchange servers.
I know I'm going to have to ask for their username/email-address and password initially. However, I really don't want to be responsible for storing these credentials if I don't have to (even if they are encrypted, I'd rather not).
I'm not sure what questions to ask, so I'm going with these:
How does Exchange Server authenticate? Do the user's credentials get sent directly to the server as they are, or are the hashed together before being sent across the wire? If they are hashed, how can I get/generate this hash for re-use on successive authentications?
Does Exchange Server send some sort of authentication token that can be re-used later (and forever, until password change or invalidation)?
If you know of a solution to the problem, that the answers to these questions won't address, please do provide it instead.
Active directory federation services is exactly for such tasks. You can read about it there.
As mentioned by Kirill, ADFS 2.0 is one of the best solution for your task. You can also look into other SSO implementations as well. Though the main goal of SSO implementation is to maintain single Login state for multiple application (thereby reducing multiple Login prompt for each application), some of your application goals seems relevant. Please do a thorough research on all the tradeoffs before heading to the sso implementation since there is a small degree of complexity involved during implementation. SSO suits best if you are considering integration of multiple application in the future with the exchange server.
To answer some of your questions (in the same order - considering an SSO scenario with ADFS 2.0):
The authentication to exchange server will be done via ADFS 2.0 (Which provides security tokens (STS service) - to your application after authenticating with AD/ main Directory service). All the communication is encrypted and token signing certificates are used for Integrity and confidentiality.
The lifetime of Security tokens sent by ADFS 2.0 can be configured and reused as required. Please see this blog post for more details.
Also you can configure the ADFS 2.0 (Federation Service) to send only the relevant claim values (like username and email address) to the application, thereby improving the data security.
The System.Net.CredentialCache should work to suite your needs. The WebCredentials is a wrapper for the System.Net.NetworkCredential. Depending on the connection type/domain ect you should be able to utilize System.Net.CredentialCache.DefaultNetworkCredentials or System.Net.CredentialCache.DefaultCredentials
perhaps you should take a look at this Links Connecting to EWS by using the EWS Managed API , Connect to Exchange - Getting Started Tutorial? hopfully it will give you a new idea how to solve your problem :)
because if i understand the information correctly you maybe over think problem but i haven't any experiences so i could also absolute wrong
Bottom Line
If you can't configure anything on the server, there's no automatically generated token to use. It's unfortunate, but you're facing the same general problem that web browsers have--saving the password.
It's worth noting that any authentication needs to be over SSL (an https connection) to prevent a third party listening in on the authentication.
Password storage thoughts:
My suggestion is then to be somewhat creative when storing the password. You can use a keyed encryption algorithm, and then use a hash to generate the key, letting you arbitrarily choose what goes into the key. You would want at least 3 pieces of information going into this: something unique to the device, something unique to the app, and something unique to the exchange server.
For example:
a unique id given by the device (it doesn't matter whether or not this value is app-specific or not, merely that it is consistent)
a (long) string of information compiled into the app, possibly keyed to installation specific values, say the time when the app was first used
something unique to the destination, like the DNS name and perhaps some more specific server info
If you're willing to provide the option to the user, you could have an authorization PIN of some kind that would also be added to the data.
All this data gets put together in one byte array and hashed. The hash (or part of it, or it twice, depending on the hash size vs. the key length) is then used as the key for the encryption of the password.
You could also include some check information along with the password to be able to check client side whether or not the password was decrypted correctly. (If the wrong data is hashed, the wrong key is generated, and the wrong result comes from the decryption).
It's worth noting that all the information to be used for putting into the hash needs to be stored on the device, which is why I would suggest a Pin to authorize the usage of the account.
I have made a WCF REST service which consumes data from an OLAP database and it is not Microsoft technology, ultimately, I would like to connect many other OLAP database to a single platform.
And after a lot of reading, the security for WCF REST is very discouraging, in summary, I have 2 choices, one is to use the Basic Authentication which expose username and password over the wire, or maybe a bit better, using Basic Authentication with SSL, now I need to get different certificates from the webserver. Or using Digest Authentication, which use an encrypted password and authenticate against the database, that's the best option, but in my case, it is not possible as I am not using Microsoft technology, the security is on different platform and I cannot encrypt my password using MD5 because the database cannot read the encrypted password.
That concludes me only be able to use Basic Authentication with SSL, but is this the correct way of doing? I see many products out there doing something similar to what I do, when they login, I do not see https, but only http, are they not secure and easy to hack?
I am not trying to make a bullet proof website, but a simple website, using Basic Authentication is too simple, or in fact it's almost like giving away the password, but using https, is that overkill?
So, after REST being that discouraging, let's not use REST, use the normal WCF, from what I have read, they shares the same problem.
Please give me some guidance. I think I have lost.
Many Thanks
PlayKid
Often, basic authentication is used for regular websites and yes, the username and password often go over the line readable if used with http. Https is already better, because the information is send encrypted over the line. But in practice, you only see this in place for commercial or banking applications. You cannot use MD5, which is a pitty, because that would be sort of middle-of-the-road approach.
So, depending on the application you will expose, use http for simplicity or https with a bit more complexity and safety.
By the way, big safety problems often have to do with SQL injection or a hacker being able to get some admin level privileges on your site. That way they get acess to a lot of info, while sniffing your line and getting a single user password combination is relatively harmless, if you take the needed precautions and counter measures.
Basically, Basic authentication with SSL is really very secure and shoul be used if its going to be exposed to outside world.
One easiest hack approach I have seen before and if you just want to authenticate (not authorize a endpoint) clients which are known set of clients use:
OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name
This will provide username accessing the service, Authenticate this usern with your DB or AD using LDAP if a valid user is accessing the service and with every request add a encrypted key that user needs to send as part of request. This way you know the username and encrypted key from the request.
You can also use this along with Basic authentication to be sure its not insecure.
I am developing web services using the servicestack.net library.
In my scenario, the web services will be called from a WPF application. I need the ability to authenticate that only an approved client app is calling my service.
Is this as simple as hardcoding a "username" and "password" in the client application? This certainly does not seem like the proper approach. Is there a better way?
EDIT
In addition, on the client end, Users themselves will be able to login with a username/password and initiate requests to the service(not sure if this effects anything, so I thought I would mention it),
For more background information about Authentication in ServiceStack see this question.
Normally you would authenticate users not clients which you seem to be doing in addition. But if you're trying to lock down services so their only accessible via a specific set of clients you should look into employing some PKI into your client and server.
Basically something along the lines of: the client sends an additional token at login with an encrypted version of the user:password together with a private key embedded in the app. The server has the client public key and so would do un extra validation step on Login to unencrypt the user:pass token and compare it with the validated user credentials.
If a PKI solution is too heavy, an alternate strategy without using encryption could be for clients to ship with a secret Guid which when they login which will send an MD5 hash version of the Guid and the current time, as well as the unhashed version of the time. If the time is within a specified threshold and the MD5 hash is valid then their using an authenticated client.