How to implement HMAC Authentication in a RESTful WCF API - c#

We are building a RESTful API using WCF (currently .Net 3.5, but will be moving to .Net 4 soon). We have a functional framework in place, but it is currently unsecured. It will need to be accessible from .Net applications as well as iOS, Android, and web applications.
We would like to use an HMAC Authentication scheme as described here and here, but both examples seem to fall apart when describing how to validate the hash. The first example fails to describe the UserKeys object (hashtable?) and the second example is missing the GetUserKey methods on the client- and server-side.
Can anyone provide an explanation of how the "User Key"/token is generated/stored/retrieved/used in those examples or provide a better example (with source code, if possible) of how to use HMAC Authorization in a RESTful WCF service?
Edit:
After more research, we determined that we needed more of an "Authorization" technique rather than an "Authentication" technique (semantics?). We implemented Basic Authorization and secured the API behind SSL. The Basic Authorization uses the same "Authorization" header from the web Request as the HMAC Authentication scheme, but passes a username:password string encoded in Base64 instead of a token. This allowed us to custom-validate a user against our database to determine if the user is licensed for and has appropriate security rights to access the desired API method.
We're certainly open to hearing other options on how to accomplish custom username/password validation and other methods for securing the API.

Retrieving the user key is just an implementation detail you can do any way you like but on the server it is often stored in a database along with the user name.
The basic approach is real simple.
Somehow the server and the client exchange a shared key for the user to use. This can be done any way you like, including sending an old fashioned dead tree style letter. Quite often this is just the password the user entered.
When the client wants to send a request he builds the complete request and then using the secret key computes a hash over the complete message body (and optionally some of the message headers if required)
Next the client add the computed hash and his username to the message in one of the headers and sends it to the service.
The service retrieves the username from the message header and searches the private keu for that user in its own database.
Next he computes the hash over the message body (and selected headers) using the key to generate its hash.
If the hash the client sends matches the hash the server computes the server knows the message was send by the real client and was not altered in any way.
Really the only tricky part is sharing a secret key with the user and keeping that secure. That is why some services allow for generation of shared keys with a limited life time so you can give the key to a third party to temporarily work on your behalf.

Implementation for HMAC we can find at
https://github.com/cuongle/WebAPI.Hmac

Related

Angular Auth Token and Visible data client side

I have come across a concern on an API project currently. I am newer to angular, so bare with me please. The data is storing in a static file our cient_id and secret key. You can view this in developer tools. Now I know there is no safe way to store data client side and hence encrypting takes a key to pass etc. Also should use tsl and so on.
My question (and is based around lack of knowledge of oauth and tokens) is would it be possible or reasonable to handle a situation like this in the manner below:
User Login request sent
Server validates and returns auth token to api controller
Prior to returning to UI JS side we encrypt in code behind.
Only the encrypted value is stored in client side.
Any request needing the AUTH token hits a anonymous api, then decrypts in code behind to get your client key, secret and other data.
At this point if valid then continues to targeted api call, does its work, returns data to UI again.
Does this concept make sense or no due to again my lack of knowledge in this arena?
Thanks in advance!

REST API best practise for authorization

I am developing an API using ASP.Net Web API to service a mobile app. I am using OWIN middleware with a custom OAuthAuthorizationServerProvider to handle the various grant requests for access tokens and restrict calls to authorised endpoints and this is all working fine.
I would like to restrict use of the API to the mobile app alone, using a secret key or keys. I understand this is not a 100% secure solution (possible reverse engineering / sniffing etc.), however I would like some guidance on the best practises to implement this.
The oAuth protocol already defines the use of a client id and secret, which I was thinking of using for the above purpose, however it seems the client id / secret are only checked when the access token is requested (ValidateClientAuthentication), whereas I would like to authenticate all API calls including generic, non-user related ones.
Another option would be of passing the secret key (client id / secret) in the HTTP header and checking this in a global AuthorizationFilterAttribute. This works but I am not sure whether it is best practise. Is there a generally accepted way to handle this scenario?

How to make REST API to be used by registered applications

I have REST API and to make it more secure I would like restrict the access to the registered applications or websites only.
Now these client applications could be web app or mobile app under Android/Windows/BlackBerry/Apple etc.
Also I can't ask the client apps to modify there code to store any value being provided by my rest API to get registered. (as these apps may or may not be using database or other persistent media).
WCF REST API should not that the caller is registered with it or not.
Any suggestions how to do it.
Using HTTP Basic Authentication (as long as your REST service is running under HTTPS) is a pretty standard way to do this. You then generate a login/password for each registered app that you want to access your API.
[EDIT: more details here: http://en.wikipedia.org/wiki/Basic_access_authentication
Basically when a client connects they need to Base64 encode their username/password and attach it into the standard HTTP Authorization header. Your server application reads the header, decodes and extracts the username/password and checks it with your list of authorized applications.
NOTE - the header is only base64 encoded, so the username/password are effectively plain text. You really should be running HTTPS if you want to use this authentication method, otherwise the header is open to interception]

How to safely include password in query string

Is it possible to safely include a password in a query string for a c# asp.net site.
Few assumptions and things I know -
The site does not and will not have links/images/javascript/analytics to/from other sites. So no referrer links to worry about.
ALL communication with the web browser will be over https.
I know that the query string will remain in the history of the
computer.
More than just the password/username is needed to login. So simply
pasting the url back into the browser will not result in a login.
I know the site may be susceptible to cross site scripting and replay attacks. How do I mitigate these?
Given the above scenario, how should I include a password in a query string?
Please don't ask me 'why', I know this is not a good idea, but it is what the client wants.
SSL
You can safely send the password to a web server using a SSL connection. This encrypts all the communication between the client/server.
Hide In The Header
Basic authentication protocols place the user/password information in the HTTP request header. C# and many other web server languages can access this information, and use it to authenticate the request. When mixed with SSL this is very safe.
Register An Application Key
If none of the above is possible, then it's recommended that you create a unique key for each user. Rather then send their password this key is used. The advantage is that the key is stored in the database and can be removed. The user's password remains unchanged, but they must register again to get a new key. This is good if there is a chance someone could abuse their key.
Perform Hand Shaking
Hand shaking is where the client makes a request to the server, and the server sends back a randomly generated key. The client then generates a hash from that key using a secret, and sends it back to the server. The server can then check if the client knew the correct secret. The same thing can be done where the password is the secret instead and the client includes username details in the request. This can authenticate without ever sending the password.
Encrypt Password
If none of the above are possible options, then you could attempt to use JavaScript to encrypt the password before it's sent via an open URL. I found an open source version the AES block cipher. The project is called JSAES and supports 128 to 256 bit encryption. There might be other JS libraries that do the same thing.
It is generally not advisable to put secrets in a query string, which can then be book marked and copied, exposing the password at-rest in history files, cookies, etc.
To just safeguard the password in this use-case, an option would be to hash the password (one-way, not reversible). In this way, the actual password is not known in transit nor at-rest but... it implies that an attacker can still use the hashed value to login to the server that would presumably compare the hash value to its store for authentication.
Update: Switching to stateless (JWT) sessions
In the olden days when buggies were a thing (okay - they are still a thing with some fringe groups but) - we used "sessions".
A "session-ID" (see JSESSION_ID) for example in Java/J2EE/Servlet based systems was stored as a cookie. That value, being a random number, was hard to guess - but it had problems from hijacking to memory and lookup overhead on the server.
In 2020 times (as of this writing) ... JSON Web Tokens (JWT) can be used to securely encapsulate the user-session information and be pushed back down in an immutable cookie without ever exposing the password and with very little server overhead.
In this model, after login, the server issues a token (using OAUTH2 or related), which has an expiration time-stamp.
This data and possibly other session information can then be encrypted, hashed, signed and wrapped up in a JWT (token) - as a cookie back to the web-browser.
Ref: https://oauth.net/2/jwt/
At this point, the client cannot do anything to compromise (or even view) the cookie because any sensitive data should have been encrypted (using AES256 et al or better) and the contents hashed and the hash signed. What this means is that when the server gets the token back, it looks at the timestamp and may throw it out - forcing re-authentication and then...
Can otherwise verify it signed the content, hash the contents and verify the hash and decrypt data if needed (which would not include the password but rather just the ID of the user - which is verified and not necessarily a secret per se).
This can include already-looked-up scopes (authorization) for what the user can do etc - avoiding round trips to the authentication server until the token times out.
Thus the above (using JWTs, hashing, signing, encrypting - into a cookie) is the recommended way to both go stateless and avoid passing around a secret between the client and server.
Ref: https://auth0.com/blog/stateless-auth-for-stateful-minds/
Additionally, consider that multi-factor authentication schemes (see Google authenticator) and related systems are a much stronger security posture (stealing password is not enough and the keys auto-rotate on external systems) but do require semi-frequent access to the rotating key system, which inhibits a smooth user experience to some extent.
Update: Multi-Factor auth by Google and others has gotten much better.
Older companies still use SMS one-time-passwords (OTP) ... which can be compromised by going to a wireless company store and claiming SIM card loss (given a known phone-number).
Google and other more advanced companies comparatively use rotating tokens that can be embedded in a smartphone app that then are used for many services.
Google even has push-notification where user just confirms by button press: "Yes - it is me".

How to prevent just anyone sending a request to my web service

I have an app in C# which serializes an object into xml into a http stream to my server. The server has some php which runs a stored procedure in mysql with the xml data as its only parameter.
The problem is that someone could very easily just send up an xml of the same format with a whole lot of entires that would ruin the database with crap data. What are my options to prevent this from happening?
I'm pretty new to web requests so I don't even know where to start.
We require a username and password to be supplied to all input parameter lists which is validated against our back-end user login system before a request is processed. Low tech, but works for us.
You should use some form of authentication and authorization. In SOAP based services there's the WS-Security extension. Here's another article on MSDN that explains how this works. However I have no idea what is the support for those standards on the PHP side. If you are using some custom protocol you could simply require a username/password to be sent along with the request and verified on the server side.
Are you planning on having this client out-there in public hands on the internet? If so it may be impossible to prevent people using different software as they could always reverse engineer the application to find out what security mechanism you are using. As a result your only defence will be to validate the data thoroughly on the server.
You might get around this by modifying the client to require a user name and password that gets sent with data to your server using HTTPS, that way at least you know who did the damage. If however you have a more closed audience you could use some kind of client certificate system or IP filtering.
Our solution (and we're hopelessly naive in this respect) is that we generate a unique key per session on the server in a non-uniform manner (ie. it is difficult to predict what the "next" value would be), and give that to the client code as part of its login process. It is then required to pass that value back to use for each request as the first parameter.
This ensures that:
Logging out invalidates the authentication key
Username and password is not sent in cleartext for the web service requests
This does not ensure that:
Only our application code can talk to the server (the user might intercept the request, copy the key, and generate his own requests, as long as the key is still considered valid.)
What you're going to find is that as long as code on the users machine is talking to your server, you have no control over the code on that machine, only the code on that server. So if the users machine is sending you requests originating from a different program, that looks just like they would and should if your code generated them, you're going to have a hard time figuring out that this is what is happening.

Categories

Resources