I'm working on a project that will generate an OAuth querystring in JavaScript, using HTTPS and in internal application, so security is not a major concern at this point (figured I'd mention that up front )
The JavaScript querystring is used to call a C# script on a different server and domain, essentially to pass data from the internal application to the C# application, and allow to verification that a) the query comes from the right source, and b) the query is valid and hasn't expired, etc.
OAuthSimple gives me a signed URL like this:
http://www.myremotesite.com/mycodepath/mycodefile.aspx?firstname=Kevin&lastname=Blount&oauth_consumer_key=ThisIsTheConsumerKey&oauth_nonce=nuOoM&oauth_signature=DAoaSxD5SvVFTTDNSxiTbANzGlc%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1313162452
My question is, one the C# side of things.. what do I do next? I've two thoughts, but I can't work out which I need to explore:
using C# generate a new signed URL and compare the two (or just compare the oauth_signature values)
take the querystring and somehow decrypt/decode it and verify it.
I'm told that DotNetOpenAuth is the standard to use, but I can't figure out my next step using it.
Can I get some advice on what I need to look into, or articles that explain how I should proceed?
Read the instructions on DotNetOpenAuth and make sure you understand it. I haven't used it previously, but have heard good things about it.
The oAuth server will do several steps:
Validate version - Is the client using the correct version of oAuth for you to handle
Validate TimeStamp - All timestamps must be in UTC to avoid Time Zone problems
Validate Nonce - Has it been used previously allowed time range
Validate Signature - Get the private key from the consumer key, compute the signature using the values passed in the parameters and compare to the actual signature.
Once the message has passed all the checks, then the server will return the resource requested by the message
Related
I'm attempting to implement the Client Credentials flow of OAuth 2.0 to secure a RESTful service, using Apache CXF (version 2.7.12).
My only client (for now) will be trusted to keep the key and secret confidential - I'm aware of the considerations around that.
My question is how I should store the client secret on the authorisation server. In my mind, the 'client secret' is effectively a password, and thus should be salted and hashed. However, CXF's AccessTokenService, which does the comparison between the stored secret and the value passed in on the request, only does a String.equals() comparison, and doesn't seem to give me any hook where I can provide a different mechanism.
This means that I would need to store the client secret in plain text in order to compare it against the plain text value from the request, without a slightly hacky alternative.
Am I missing some obvious functionality that would let me hash the incoming value before the comparison, or am I being overly-cautious with the client secret? Maybe I'm wrong to treat it like a password?
A sort-of answer, for people encountering this question in the future.
My approach was to create a very simple filter (as described here: http://cxf.apache.org/docs/jax-rs-filters.html), which manually creates a SecurityContext (https://cxf.apache.org/javadoc/latest/org/apache/cxf/security/SecurityContext.html), and adds it to the Message as it passes through the Filter.
This means that as the flow continues on to CXF's AccessTokenService, it's identified as already being authenticated.
I also asked a question on the CXF mailing list, and got a very prompt reply from a developer agreeing that he'd recently noticed this as a potential issue, and was looking into it. Within a few hours he'd committed a change which addressed it, and looked like it would have been an ideal solution. Unfortunately, I've still not found time to test it, as my solution works and gives me a bit of extra flexibility that's helpful for other requirements on my project.
I've been reading quite a few questions here on SO about securing web api's using api keys, tokens, hmac ect and haven't found the answer I am looking for.
I'm working on a MVC4 web application project with internet and intranet sites, web api and Android/iOS applications.
The Web API is to be used by my applications and nobody else as it will be accessing sensitive data.
What would be the best way of securing this api so only my apps can use it? Something that seems like such a simple request is extremely difficult to get started on.
I've looked at the post here on SO using HMAC and a few others but none of them sounded like they would fit here, more than likely I am just missing something.
Is HMAC the way to go or would client certificates be more appropriate for this situation?
Should I use SSL and some sort of API key?
I know the question is a bit vague, I've been staring at it for over an hour trying to figure out how to word what I am thinking so I figured I would just post it and update if needed... :(
I would be more than happy to provide more details upon request.
Generate a key for each of your apps and have them pass the key in each request as a token. Your server can then verify the key and authenticate the request.
Take a look at the Basic Authentication module from the ASP.NET site. The sample uses 'basic' as the authorization scheme but you can change it use 'token' instead.
private static void OnApplicationAuthenticateRequest(object sender, EventArgs e)
{
var request = HttpContext.Current.Request;
var authHeader = request.Headers["Authorization"];
if (authHeader != null)
{
var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);
// RFC 2617 sec 1.2, "scheme" name is case-insensitive
if (authHeaderVal.Scheme.Equals("token",
StringComparison.OrdinalIgnoreCase) &&
authHeaderVal.Parameter != null)
{
AuthenticateUser(authHeaderVal.Parameter);
}
}
}
Once you have the Basic Auth module in place you can simply decorate any actions or controllers with the Authorize attribute and it will forward the request to the Basic Auth handlers.
namespace webapi.Controllers
{
[Authorize]
public class SensitiveDataController : ApiController
{
...
}
}
As far as over the wire you MUST use SSL when using basic authentication as your key will be transmitted in plain text.
You can use FormsAuthentication. Encrypt the ticket and ensure machineKey is the same in both the config files. See this and this. This will allow the same user credentials to be shared between web app and api. ASP.NET FAM module will establish the identity in this case.
For api key, look at hawk scheme. It uses shared symmetric key. However, Hawk is feature-complete and until it reaches version 1.0 it is likely to change. Nonetheless, it will give you a good idea of implementing HMAC-based security. I have a .NET implementation here for Hawk. And there is one from Pablo as well. In this case, you will need to write a message handler to establish the identity for the consuming application.
In a general case for a high traffic app, all the above answer have a flaw that many attackers can easily exploit:
With a jail broken iPhone, you can break SSL - not to your server, but when they have your app on their phone, they can at least analyse the packages you send.
The best way to avoid that (in my opinion) is using 'on time passwords' - real on time passwords.
How can you generate these one time passwords?
A1. Get a device_identifier for each device (this could also just be any random number, but you should avoid collisions with other devices' identifiers)
A2. Have an api_key, that you will use for hashing
Now if you want to send a package to your api, you do the following:
B1. Construct your normal package, here is the example of some json payload:
var payload = {"hello":"world"}
B2. Hash your var hashed_payload = hash(payload) using your favourite hashing function
B3. Generate the one time password for this package:
var otp = hash(salt & hashed_payload & device_token & api_key)
Now you have everything you need, to send to the server:
In the headers, you need to send the otp,salt and device_token as well!
On the server, you will do the same steps marked as B1-3 and compare your hashing result with the one provided by the client. After that you have to make sure that you 'ban' this salt for this device_token in order to avoid replay attacks.
This method still has one flaw but requires much more work from attackers:
They can find your api_key in you compiled code.
I'm working on a similar project where I assign unique API keys to each user or client application accessing my API. I'm not a security expert, but I'd recommend that you use SSL and generate unique API keys for both your Android and iOS applications. With SSL, data being transmitted to your API will be encrypted and protected.
I have to implement a web site (MVC4/Single Page Application + knockout + Web.API) and I've been reading tons of articles and forums but I still can't figure out about some points in security/authentication and the way to go forward when securing the login page and the Web.API.
The site will run totally under SSL. Once the user logs on the first time, he/she will get an email with a link to confirm the register process. Password and a “salt” value will be stored encrypted in database, with no possibility to get password decrypted back. The API will be used just for this application.
I have some questions that I need to answer before to go any further:
Which method will be the best for my application in terms of security: Basic/ SimpleMembership? Any other possibilities?
The object Principal/IPrincipal is to be used just with Basic Authentication?
As far as I know, if I use SimpleMembership, because of the use of cookies, is this not breaking the RESTful paradigm? So if I build a REST Web.API, shouldn't I avoid to use SimpleMembership?
I was checking ThinkTecture.IdentityModel, with tokens. Is this a type of authentication like Basic, or Forms, or Auth, or it's something that can be added to the other authentication types?
Thank you.
Most likely this question will be closed as too localized. Even then, I will put in a few pointers. This is not an answer, but the comments section would be too small for this.
What method and how you authenticate is totally up to your subsystem. There is no one way that will work the best for everyone. A SPA is no different that any other application. You still will be giving access to certain resources based on authentication. That could be APIs, with a custom Authorization attribute, could be a header value, token based, who knows! Whatever you think is best.
I suggest you read more on this to understand how this works.
Use of cookies in no way states that it breaks REST. You will find ton of articles on this specific item itself. Cookies will be passed with your request, just the way you pass any specific information that the server needs in order for it to give you data. If sending cookies breaks REST, then sending parameters to your API should break REST too!
Now, a very common approach (and by no means the ONE AND ALL approach), is the use of a token based system for SPA. The reason though many, the easiest to explain would be that, your services (Web API or whatever) could be hosted separately and your client is working as CORS client. In which case, you authenticate in whatever form you choose, create a secure token and send it back to the client and every resource that needs an authenticated user, is checked against the token. The token will be sent as part of your header with every request. No token would result in a simple 401 (Unauthorized) or a invalid token could result in a 403 (Forbidden).
No one says an SPA needs to be all static HTML, with data binding, it could as well be your MVC site returning partials being loaded (something I have done in the past). As far as working with just HTML and JS (Durandal specifically), there are ways to secure even the client app. Ultimately, lock down the data from the server and route the client to the login screen the moment you receive a 401/403.
If your concern is more in the terms of XSS or request forging, there are ways to prevent that even with just HTML and JS (though not as easy as dropping anti-forgery token with MVC).
My two cents.
If you do "direct" authentication - meaning you can validate the passwords directly - you can use Basic Authentication.
I wrote about it here:
http://leastprivilege.com/2013/04/22/web-api-security-basic-authentication-with-thinktecture-identitymodel-authenticationhandler/
In addition you can consider using session tokens to get rid of the password on the client:
http://leastprivilege.com/2012/06/19/session-token-support-for-asp-net-web-api/
A common use case for WebAPI would be to have shell views rendered by MVC controllers, which contain javascript that then hit your API to access data.
But let's say you have some expensive API operations and you don't want people remotely accessing those endpoints -- you only want your MVC views, delivered by your application, to access them. How could you go about protecting them?
In this case Request.IsLocal doesn't work, because javascript is invoking it from the client's browser on their machine. Even if it did work, you need to dig to get the real HttpContext in order to find this property -- and that solution wouldn't work in self-hosted WebAPI.
For API endpoints that require a valid IPrincipal, you could protect them with the [Authorize] attribute. But what about API endpoints that you want your app to be able to access for anonymous users?
I have tried a solution and will post it separately as an answer, because I'm not sure if it's the best (or even a good) approach.
If your MVC site uses authentication, you could enable forms authentication for your Web API methods. You could write a custom [Authorize] attribute that will check for the presence of a forms authentication cookie which will be sent from the AJAX call and if present construct the principal.
Another possible solution is to protect your API with tokens which is a more RESTful style. The idea here is that when a user authenticates on your MVC website you could generate and pass a token to the view which will be used when sending the AJAX request to the Web API which in turn will verify the validity of the token and its signature.
If on the other hand your site doesn't use authentication, then things will get very complicated because you have no way of knowing whether the request comes from a trusted client since you are using javascript to call your API methods.
Before you go harping about "what have you tried", here is what I have tried. It works. Just not sure if there is a better way.
Create an MVC action filter and add it as a global filter during Application_Start.
Create an Http (WebAPI) action filter and use it on actions that should reject remote requests.
The global MVC filter does this:
Looks for a specific cookie in the request. If the cookie is there, its value is decrypted. The decrypted value should be a string representation of a DateTime, so use DateTime.TryParse to get it out. If the value is correctly parsed to a DateTime, and that DateTime is less than a day old, STOP HERE and do nothing else.
If the cookie is not there, or cannot be decrypted / parsed, or is older than a day, write a new cookie to the browser. Use the current DateTime.UtcNow.ToString() as the value, encrypt it, and write it with HttpOnly = false.
The WebAPI filter does this:
Looks for a specific cookie in the request. If the cookie is there, decrypt its value and try to parse it out as a DateTime.
If the value is a valid DateTime and is less than 2 days old, STOP HERE and do nothing else.
Otherwise, throw a 403 Forbidden exception.
A couple of notes about my current implementation of this. First of all, I use AES encryption with a shared secret and a salt. The shared secret is stored as an appSetting in web.config. For the salt, I enabled anonymous identification and used Request.AnonymousID as the salt. I'm not entirely fond of the salt because it's tricker to get at in a WebAPI controller, but not impossible as long as it is not self-hosted.
I am writing a web application using server-side authentication, and I've been trying to figure out a way to leverage Facebook's Javascript SDK in my application.
The documentation for FB.init defines the optional authResponse parameter as something used to "Manually set the object retrievable from getAuthResponse". It also states that once obtained, an application may store the entire authResponse object for future access. This may work if an application uses FB.login, the Javascript SDK's authentication, but what about an app using server-side authentication?
Server-side authentication enables my app to obtain a user's access token, the most crucial piece of information needed for graph API calls. I would hope that this access_token alone would be enough to construct a valid authResponse object to use to authenticate to use with the Javascript SDK.
Merely calling FB.init (with valid appID, channelUrl, and other parameters) with an authResponse containing a valid "accessToken" field is not sufficient. Including the userId is also insufficient. Ideally, these parameters alone would work. The only others defined for the authResponse are 'expiresIn' and 'signedRequest'. Which, if either, of these parameters would be sufficient to generate a valid authResponse object? To what values must they be assigned?
I managed to dig up this description of a 'signedRequest':
https://developers.facebook.com/docs/authentication/signed_request/
This document raises a number of questions. I assume that the signature is produced by a symmetric algorithm. If not, then generating it would not be possible. Assuming it is possible, the description of the payload is in no way specific. There is a list of 9 parameters, none of which are labeled as required.
Like CBroe says, you shouldn't be passing anything manually. You start with a call to FB.getLoginStatus and pass your javascript handler as an argument to this method. You will have the authResponse returned back from the getLoginStatus call.
You can, of course, in theory pass the access_token param around to any FB.api call e.g. /me?access_token=blah_blah, where blah_blah is the string you have but again, this is not required and you are better off delegating this to the response handlers.
Be very careful when using the javascript sdk and server side authentication for access token generation/extension/verification. You end up maintaining two separate code paths and end up making the same call to Facebook over and over again. Even if you are storing the access token on your side, would be always better to pick one approach that works best for you, rather than having a server side call to get access token and a client side call to FB.api to use the access token.
There is a solution for that. I didn't think that it's so easy.
FB.api('/me?access_token={{ access_token }}', function (me) {
console.log(me); //do anything with me
});
So you didn't need to set an Objekt Variable in FB before -
simply add the access_token as parameter with your request.