I've been working on the development of an Android app in my spare time for several months now. I've done all of my planning for the on-device side (except for server-side interaction), but I've been met with a very steep learning curve for the on-server side implementation. I've researched for about a month with no real leads. Consequently, I'm really at a dead end. The app that I'm working on included these minimal requirements:
Must offer account creation/authentication to the server from the
device
Must maintain some sort of session that allows the user authorization
to make changes that will impact only the on-server user data within the context of the account that they are logged in to.
The ability to log out/be logged out by the server under certain conditions.
A web interface will not be necessary, as this service is only to be consumed by Android devices.
I've decided that a Rails implementation is the most desirable option for me. My experience with Rails and servers in general is very limited. A friend recommended that I read though "Agile Web Development with Rails" in order to get up to speed. I made it through enough of the Depot Application demo in order to understand ORM libraries, the MVC pattern, and scaffolding, but then I got fed up with the way that the book presents the information. Everything is very sequential, and the authors seem to omit a lot of the "how", saying that they'll explain later, and to just not worry about it until that point. That's not the way I learn. I digress.
So far I've used scaffolding in Rails to generate a model, view, and a controller for an Accounts table. I've set up attributes for a username, password, session_key (a randomly generated key that the user should receive and use to connect from their device after login), etc using scaffolding. I am validating the username and session_key to ensure that they're unique, and my alphanumeric key generation is working properly (all of which is done in the model).
Now I'd like to focus on managing sessions in a restful manner. I know that I'll need to implement this by having Android devices pass their user's session key to the server when making HTTP requests and accessing resources etc., but other than that I'm at a loss.
I'm looking for someone to provide me with a good resource (or explanation) outlining how HTTP requests and responses work in general, how JSON information can be received and parsed using a request, and how to otherwise manage restful authorization (assuming that the user has already been assigned their session key). If my approach isn't quite right, please let me know what you would suggest.
Thanks!
For authentication, you might want to check out: http://railscasts.com/episodes/250-authentication-from-scratch You'll basically just be performing the authentication using the session_key. There are other more complicated things you might do, and you could check out authlogic, devise, sorcery, etc. to see how they implement keeping sessions alive. Since you need log outs, and presumably the need to log back in, I would suggest looking into using the session key you describe as the master authentication and then have a perishable key of some sort that gets reset after every request and sent back to the client as a keepalive. Depending on your ultimate needs, that might be enough security and functionality.
For JSON receiving, rails has built-in parsing. Look into respond_to. For sending back JSON, you can use any number of methods. The most basic is to just allow rails to automatically convert the JSON (which happens when respond_with is used, as in the link). You could also build out presenter classes or use something a little more formal like rabl.
Related
I have an app, client side, that uses auth0 for accessing the different API's on the server. But now I want to add another app, a single page app, I'm going to use VueJs, and this app would be open "ideally" w/o a user having to sign in, it's like a demo with reduced functionality, I just want to check that the user is not a robot basically, so I don't expose my API in those cases.
My ideas so far:
- Somehow use recaptcha and auth0 altogether.
- Then have a new server that would validate that the calls are made only to allowed endpoints (this is not of my interest in the question), so that even if somehow the auth is vulnerated it doesn't leave the real server open to all type of calls.
- Pass the call to the server along with the bearer token, just as if I was doing it with my other old client app.
Is this viable? Now I'm forcing the user to validate, this is more a thing about UX (User-experience), but I'd like a way to avoid that. I'm aware that just with auth0 I can't do this see this post from Auth0, so I was expecting a mix between what I mentioned.
EDIT:
I'm sticking to validating in both cases, but I'm still interested to get opinions over this as future references.
At the end, with the very concept of how auth0 works that idea is not possible, so my approach was the following:
Give a temporary authenticated (auth 0) visitor a token which has restricted access level, then pass the request to a new middle server, the idea is to encrypt the real ids so the frontend thinks it's requesting project A123456etc, when indeed it's going to get decrypted in the middle server to project 456y-etc and given a whitelist it will decide to pass the request along with the token to the final server, the final server has measures to reduce xss and Ddos threats.
Anyway, if there's a better resolve to it I will change the accepted answer.
You could do a mix of using recaptcha for the open public, then on the server side analyse the incoming user request (you can already try to get a human made digital fingerprint just to differentiate with a robot-generated one) and the server (more a middle server) makes the call to you API (and this server has limited surface access)
What we normally do in these situations (if I got your issue correctly) is to create two different endpoints, one working with the token and another one receiving the Recaptcha token and validating it with Google servers.
Both endpoints end up calling the same code but this way you can add extra functionality in a layer in the 'public' endpoint to ensure that you are asking only for public features (if that cannot be granted just modifying the interface).
If I have a single server with multiple domains, what is the preferred method for implementing a single-sign-on solution on the same domain. I am currently using devise, have a few million cookies in place on separate domains, and am stuck. On top of just implementing SSO, I also need to migrate the various cookies to a central domain. Regarding the various servers, they only have one single page that requires me to show different states depending on whether or not the user is logged in.
I have tried the following:
CORS: pick one domain as the central auth hub. From all other domains make cross domain checks to see if the user is logged in. For migrating cookies, detect if there's a "current_user" object, send it to the client, make a CORS request, sign the user in and kill the token. Works Great! BUT... After building it for 2-3 weeks, it TOTALLY FAILS in IE. Even IE11, I'm noticing the default setting is disabling this behavior.
tried tinkering with the session store at
Rails.application.config.session_store
with no luck.
I am currently experimenting with the following:
JSONP: I have someone right now trying to convert the above to JSONP instead while I try some other options:
Set up a custom OAUTH provider. Like before, it will be the "central domain" if the person is signed in, return to the requested domain with a token from which the users can make requests. https://github.com/songkick/oauth2-provider
Looking at this but it looks outdated? https://github.com/rubycas/rubycas-client. I also get the feeling this could have been a solution if I rolled this out from the get-go, but given how far we are into the project, it's unclear to me how I'd transfer the existing cookies. Also it's unclear if this requires two applications for me to get up and running ( one for client(s), one for auth server)
As I go through each of these possibilities, if anyone has had any experience doing what I'm doing, please do inform me and save me a whole lot of work :)
The best way unless this is a toy app is probably to set up an oauth provider.
We use Doorkeeper with Devise for this and it works great. It will be worth your time to set a little time aside to read through the documentation and watch a talk or two on youtube if you're not already familiar with the strategy but once you understand the core concepts its actually pretty simple to set up with the help of this gem.
There is a quick video run down on http://railscasts.com/episodes/353-oauth-with-doorkeeper
When building a single page application, in my example with Backbone w/ Marionette, how does one approach administrative/super user sections of code. For example if I build a site that has an admin section that can delete users, manage account details from a financial perspective, etc, technically an attacker can view the code. Additionally an attacker could see the precompiled templates from a visual standpoint. While I understand you can compress the code/obfuscate , that really isn't a solution. Is this just something that's considered a pitfall when developing SPA's? IE one just needs to make absolutely sure the API is secure, etc. If something isn't secure, essentially a roadmap is already provided to a potential attacker...
Well code for the interface really isn't important: it's javascript anyway, so a malicious user could build his own, or simply generate the required API calls.
In addition, the only thing you'd be giving a "roadmap" for is API endpoints, which tend to be easy to guess (e.g. managing users usually goes through the "users" endpoint). In addition, these endpoints are often known: a user could edit his own account by hitting the "users" endpoint, while an admin could edit all users. The API call would be the same (or very similar) and the credentials/authorization would be verified on the server (which, theoretically, the attacker wouldn't have access to).
Your question is close to "how do I achieve security by obscurity?". I know that's not what you're asking, but its not far off. There shouldn't be an issue with an attacker being able to see the admin code path or API calls, because there shouldn't be anything special about them.
But as you said in your question, you absolutely MUST validate/authorize everything on the server. If you don't treat all data coming from the user as hostile or tampered with, you'll have a bad time...
Hope this helps!
I am building an api for others to use. This is a simple enough Json request the user passes as some data and we pass some back.
What I would love is to secure our api and have some sort of user system where we can turn users on and off and we can log how many requests each user makes.
What would be the best way to do this in Rails? I don't want it to slow down the request. I can see ways of doing it using devise maybe but would be great to hear other people's opinions.
Thanks
Another way is to use 3scale (http://www.3scale.net) - it's free up to a traffic cap but handles all the key management, users, documentation etc. and there's a ruby library which you can drop into your code if you're using rails. (other libs are here: https://support.3scale.net/libraries).
I've done this before using the Token Authentication capabilities of devise (see https://github.com/plataformatec/devise ).
I found the following setup works:
Create a user account for each api user.
Configure devise for token authentication
Set the Token Authentication configuration to require the token to be submitted with each request.
This will allow you to enable and disable individual users as well as to track every request back to the api user that made the call.
If you're really interested in tracking usage you may want to consider also creating a database table where you track all api requests. This can be setup to belong_to the users table so that you easily find all requests from different users (e.g., #user.api_requests).
The count of all requests made by a user would be:
#user.api_requests.count
# or use a where clause to find how many of each type
#user.api_requests.where("api_request_type = ?", 'SomeAPICallType').count
One final note -- I recently used the Grape library for building out an API. I thought it was pretty well done and it worked great for our needs. I especially like the ability it provided to version APIs. Details are here: https://github.com/intridea/grape/wiki
I'm going to be writing the services for an iPhone app being built by a third party vendor.
I'll be using ASP.NET MVC to accept posts and also return JSON formatted data.
My question is, how do you secure it?
Just using an API key perhaps? Would that be enough to ensure that only data from the iPhone apps are allowed to hit the specified services?
I'm sort of struggling with the same concepts myself. I think the first thing is to do HTTPS only, so that it's starting out more secure than not.
Next, it depends on how you're going to do authentication. If all you need is an API key, (to track which entity is accessing the data) that should be fine. If you also want to track user information, you'll need some way to associate that specific API keys can access specific types of records, based on a join somewhere.
I'm looking at doing forms auth on my app, and using an auth cookie. Fortunately ASP.NET on IIS can do a lot of that heavy lifting for you.
Example time: (I'm sure I'll need to add more to this, but while I'm at work it gives something to gnaw on)
Forms auth:
Send a pair (or more) of fields in a form body. This is POST through and through. There's no amount of non-reversible hashing that can make this secure. To secure it you must either always be behind a firewall from all intruding eyes (yeah right) or you must be over HTTPS. Simple enough.
Basic auth:
Send a base64 encoded string of "username:password" over the wire as part of the header. Note that base64 is to secure as a screen door is to a submarine. You do not want it to be unsecured. HTTPS is required.
API key:
This says that an app is supposedly XYZ. This should be private. This has nothing to do with users. Preferably is that at the time that the API key is requested, a public key is shared with the API grantor, allowing the API key to be encoded on transit, thus ensuring that it stays private but still proves the source as who they are. This can get complicated, but because there is an application process and because it won't change from the vendor, this can be done over HTTP. This does not mean per-user, this means per-developing-company-that-uses-your-api.
So what you want to have happen is that for the app accessing your data, that you want to make sure it's an authorized app, you can do negotiation using private keys for signing at runtime. This ensures that you're talking to the app you want to talk to. But remember, this does not mean that the user is who they say they are.
HOWEVER.
What you can do is you can use the API key and the associated public/private keys to encode the username and password information for sending them over the wire using HTTP. This is very similar to how HTTPS works but you're only encrypting the sensitive part of the message.
But to let a user track their information, you're going to have to assign a token based on login based on a user. So let them login, send the data over the wire using the appropriate system, then return some unique identifier that represents the user back to the app. Let the app then send that information every time that you are doing user specific tasks. (generally all the time).
The way you send it over the wire is you tell the client to set a cookie, and all the httpClient implementations I've ever seen know that when they make a request to the server, they send back all cookies the server has ever set that are still valid. It just happens for you. So you set a cookie on your response on the server that contains whatever information you need to communicate with the client by.
HTH, ask me more questions so we can refine this further.
One option would be to use forms authentication and use the authentication cookie. Also, make sure all the service calls are being sent over SSL.