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.
Related
I have this scenario where an external web site is going to send some data over the network to my web app, then I have to process that info and complete a process within my app. After process completion, I need to return to the original external web with some info.
My questions is about security, how do I know that the external site making the request is actually the web site is supposed to make the request? If you can point me in the right direction would be great!
I'm using ASP.NET MVC4.
For this scenario, certificate authentication best suits. I have got many external clients consuming my service and cert authentication is working as expected.
#Mick Wasson has written this post:
http://www.asp.net/web-api/overview/security/working-with-ssl-in-web-api
You can purchase certificates from 3rd party like :
Rapid SSL :https://www.rapidssl.com/index.html
Global Sign: https://www.globalsign.eu/ssl/
The following are available options. Basic or Tokens might be good choice if your web app is a public web service.
Basic
The caller adds an HTTP authorization header containing a user name and password. Those values are essentially plaintext, using only base64 encoding for simple obfuscation. This generally requires Secure Sockets Layer (SSL) transport security (i.e., an endpoint
that exposes an HTTPS address) to protect the plaintext user name and password.
Digest
Provides a fancier method of putting the user name and password in the HTTP header that provides encryption for those values. This is intended to avoid the need for HTTPS.
Kerberos
Uses an authentication server, such as Windows Active Directory, to provide integrated and seamless credential validation. This is similar to intranet sites on Windows networks that integrate with the domain for user authentication. A lot of internal SharePoint sites use this approach so that a company's users don't have to re-enter their user name and password when they visit the intranet.
Public-Key, Certificates
Relies on caller-provided certificates to identify a user. This is not very useful in a public web site or service, but it is very appropriate for applications where the users or devices are known. An example of this approach is an internal, portable, device-based
warehousing application for tracking inventory, or maybe a set of iPads used by the sales team. The group of users is relatively small and well-defined within a company's organizational structure. Each user or device is issued a certificate that identifies him (or it) on every call to your site or service.
Tokens
Largely used when third-party token issuers are involved (e.g., OpenID, OAuth). This relieves your service of the burden of both storing and verifying a user's credentials. Here's how it works (generally speaking):
The caller first verifies the user name and password using a token issuer that your service trusts. Upon successful verification, the token issuer provides the caller with a token. Once the caller has that token, it uses it to call your service. Since your service trusts the issuer that the caller used for credential verification, your service can trust that the token securely identifies the user, and it therefore doesn't have to bother with verifying the user's credentials itself.
Source: ASP.NET Web API 2: Building a REST Service from Start to Finish.
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 am working on the web service. A user is going to be able to create a user account using a form on different asp.net project. So when the user enters the password information I need to store that encrpted in a database. But now when the user sends the user credentials through for a web services then I need to the user to send that password encrpted for security purposes.
Now how can we both have the same ecrption procedure so that I will be able to validate the request.
What you want is to use HTTPS connection to transfer the password from the user to the server safely. Here is the explanation on how to set up the development environment with IIS for HTTPS - scottgu link.
HTTPS protocol will handle the encryption and decryption and you just deal with the plain-text password on the server-side.
After that, on the server side, you compute the hash of the password and compare it to the hash stored in the database. Standard ASP.NET SQL membership provider can be used for this.
There is a good explanation from Jeff Atwood on the problems behind storing and hashing passwords - coding horror link.
If the user's browser in any way knows how to encrypt your password then you kind of lose the point and a smart hacker could extract that encryption.
Using SSL to pass information directly to your application is essentially doing what you're asking and is the accepted secure way to receive the password. You will just have to check against your encrypted version in the database.
Your app receives the password raw (browser and server have taken care of encrypt/decrypt), then your app encrypts it and looks in the database for a match.
The other way this is done with web services is using a single login step that returns an expiring token which is used for further communication. OAuth is the most popular so do some googling on that.
You can encrypt the info you need using System.Security.Cryptography;
have a look at the below:
http://jakkaj.wordpress.com/2007/10/27/encrypting-and-securing-web-service-traffic-without-ssl/
Bear in mind that anything you do to provide "encryption" that isn't using SSL/TLS is likely to be vulnerable
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.
I have N- Tier application Which consist of three parts:
1. Client (WPF)
2. WebService (Java web service) (Business logic)
3. Database (Oracle)
I store my password in md5 in oracle database but send password from from client to web service in not encrypted state just like a simple string. Which technic I have to use to secure password in network?
I would really recommend using SSL unless you want to go through caring about a lot of security concerns. Kerberos solve those pretty nicely as well but it is not that straightforward to use.
I've get some insights about secure authentication problems by reading Designing an Authentication System:
a Dialogue in Four Scenes (it is about designing Kerberos, but a lot applies to all authentication systems in general).
I think SSL is your friend as suggested by others. But whatever you do, I would not send the MD5 hash over the network. Part of the point of hashing (with MD5 or else) is to avoid storing a value that can be used 'as such' to authenticate a user. If any attacker gets access to the DB, he only sees the hashed password, but would still need to use the original password - which he can't decrypt from the hash - to access the web service. If your web service, instead of asking for the original pwd and hashing it itself before comparing it with the value stored in the DB, decides to let the client do the hashing, the aforementioned attacker needs only to send the compromised hash to be authenticated.
If you're worried about the requests being intercepted then you could use SSL to communicate between the client and the WS. Even if you encode the real password inside the client before sending it to the webservice, if the encoded form is somehow disclosed it could be used 'as is' to formulate a request to the webservice from any HTTP client. Alternatively you could encrypt the message content itself using an algorithm stored solely in the client so you can ensure that all WS requests come only from your client.
You could send password MD5 from client to web service. Even better, salted MD5 (and in DB you should keep also salted MD5). Then just compare what is received from client with what is in DB.