authenticity token and iphone - iphone

I would like to add security measurements against CSFR for my iphone app, which uses a server as backend, and the same server also serves web requests. server is written in ruby on rails.
for regular requests I'm using an special kind of authenticity token hidden inside the form, which is posted with every request from that page to establish trust.
my problem is I cannot simulate this behavior from iphone since it doesn't actually pull a form before posting.
I've thought of something along the lines of first sending request to server to generate some kind of token and then adding it to requests, but still given someone stills the token + authentication cookie etc from the iphone, sniffs it out or something. I'm still exposed to CSRF.
thoughts?

Here's an excellent post that should help to point you in the right direction.

Related

Advice on implementing web server security in iPhone app

I have a relatively successful app in the app store that allows people to view metrics on their iDevice using a JSON file hosted on the their server. The app has a simple settings screen in which you simply type the URL of your JSON file and the app takes care of visualising the data in the file. I use AFNetworking for this.
For example the URL might be: http://www.mylargecompany.com/factorykpi.json
Customers are now coming back to me and asking for the ability to connect to their servers more securely. Problem is there is a myriad of ways you can secure your server.
I need some advice. What kind of standard security features would I need to build into my app. I am confused by OAuth, HTTPS, etc.
I believe OAuth would mean the customers server would have to use it? Can you make a generic OAuth login screen in an app or do you need to know which web server you are connecting to authenticate.
Any advice on even the most basic of security measure would be very welcome!
Regards,
MonkeyBusiness
Security is really a very broad topic. There is no short answer. In any case, both web service and client app need to implement security mechanisms. I would recommend, you provide both the web service and client app.
You likely need some user login with a password, "server verifies user identity" and "client verifies server identity" using certificates. Then you utilize HTTPS which ensures to transport confident data in a secure way. The web service should be implemented with one of the well known web application frameworks since security is a scary business, and tricky. Implementing everything yourself, might end in a suboptimal insecure application.
You should now read more about the complex topic and come back when you have specific questions.
... most basic would be to use https, which would secure the transaction, but anybody accessing the same link would be able to access the same data. Thus you will need some kind of authentication, starting with a simple secret key passed as POST request, username and password and/or via certificates.

Questions regarding authentication workflow with REST, and Backbone

I am currently working on a website built with Backbone.js. The site has a RESTful API built in Symfony with FOSRestBundle. Developing was going fine, until I stumbled in to some user-related tickets.
From what I understand, the best way to handle this type of problem is with a token based system, where the user gets an access token after an approved login. I will describe my current perception of the workflow, and ask questions along the way. More importantly, please correct me if I have misunderstood.
First, the user the accesses the login form, then the user types in credentials, and an AJAX request is send to the server. From what I understand this should all be handled with SSL, but with Backbonejs, you can't simply say that the login page should be accessed with HTTPS, as Backbone is a one-page framework. So will this force me to use HTTPS through out the application?
In the next step, the REST server validates the credentials, and they are approved, then the REST server sends an access token to the client. Is this token saved (on the client-side) in local storage or a cookie?
Also is the login stored at the server, so that the REST server can log the user out after a certain amount of time?
Now, the client sends this access token along with other request, so that the server can identify the client, and approve the request or not. So the access token is also stored on the REST server?
Lastly is this what the smart people call "oauth", or does it relate to it?
Thank you.
Let's take your questions one at a time.
From what I understand this should all be handled with SSL, but with Backbonejs, you can't
simply say that the login page should be accessed with HTTPS, as Backbone is a one-page
framework. So will this force me to use HTTPS through out the application?
Ok, there's a lot to unpack there. Let's start with SSL/HTTPS. HTTPS is a protocol; in other words it defines how you send packets to/from the server. It has nothing whatsoever to do with whether your application is single or multi-page; either type of site can use either HTTP or HTTPS.
Now, that being said, sending login info (or anything else containing passwords) over HTTP is a very bad idea, because it makes it very easy for "bad people" to steal your users' passwords. Thus, whether you're doing a single-page or a multi-page app, you should always use HTTPS when you are sending login info. Since it's a pain to have to support both HTTP and HTTPS, and since other, non-login data can be sensitive too, many people choose to just do all of their requests through HTTPS (but you don't have to).
So, to answer your actual question, Backbone isn't forcing you to use HTTPS for your login at all; protecting your users' passwords is forcing you.
In the next step, the REST server validates the credentials, and they are approved, then
the REST server sends an access token to the client. Is this token saved (on the
client-side) in local storage or a cookie?
While any given framework might do it differently, the vast majority use cookies to save the token locally. For a variety of reasons, they're the best tool for that sort of thing.
Also is the login stored at the server, so that the REST server can log the user out
after a certain amount of time?
You've got the basic right idea, but the server doesn't exactly store the login ... it's more like the server logs the user in and creates a "session". It gives that session an ID, and then whenever the user makes a new request that session ID comes with the request (because that's how cookies work). The server is then able to say "oh this is Bob's session" and serve the appropriate content for Bob.
Now, the client sends this access token along with other request, so that the server can
identify the client, and approve the request or not. So the access token is also stored
on the REST server?
If you're running two separate servers they're not going to magically communicate; you have to make them talk to each other. For this reason your life will be easier if you can just have one (probably REST-ful) server for your whole app. If you can't, then your REST server is going to have to ask your other server "hey tell me about session SESSION ID" every time it gets a request.
Lastly is this what the smart people call "oauth", or does it relate to it?
Kind of, sort of, not really. OAuth is an authorization standard, so it's sort of tangentially related, but unless your login system involves a whole separate server you have no reason to use it. You could use OAuth to solve your "two servers, one REST-ful one not" problem, but that would probably be overkill (and regardless it's outside the scope of what I can explain in this one Stack Overflow post).
Hope that helps.

Optional SPNEGO Kerberos authentication

Is it possible to do optional kerberos authentication?
What I want is: if the client (browser) is not on the domain it is redirected to a username/password web login. Otherwise it will do SPNEGO do Kerberos authentication.
If I just send the WWW-Authenticate: Negotiate header to a non domain browser it just does nothing further.
Is there some option to tell the browser to try something different if it doesn't know how to authenticate? Or do I have to determine if user is part of the domain before sending the "WWW-Authenticate" header?
I haven't found anynone who has solved this publicly and in a standard way. Yes, as mentioned, one could fall back to Basic but that doesn't work for authentication schemes which involve requesting a username and password from a CGI form where, as far as the browser sees things, you're falling back to no authentication if Negotiate fails. Maybe that is suggestive that the authentication scheme is broken? I don't know.
I'll tell you what I know, first. Our site is, effectively, Cosign-protected, so we have a similar problem to you: only specially-configured machines respond to the WWW-Authenticate header, so by default we must send all users to our Cosign login page. The trick is that the Cosign server also allows authenticated GSSAPI/Kerberos hosts to complete the authentication process without entering login details, but only on certain browsers, by means of a workaround.
This workaround consists simply of a block of JavaScript within the login page which attempts a HEAD of an SPNEGO-protected resource; if successful, the script redirects the browser to an SPNEGO-protected version of the same page, which grants appropriate Cosign cookies and completes the process without password entry. If the browser lacks any one of JavaScript, Kerberos support or adequate credentials, then the user will see the cosign login page as usual.
So, the above alone might count as an answer to your question; personally though I don't think this goes far enough and what follows is more of a discussion...
The above seems unsatisfactory as it insists that any connecting user agent supports either JavaScript (unlikely to be the case for text-based browsers and HTTP client libraries) or knowledge of the arbitrary path to which we redirect Kerberos-capable users (useless to anything which has not been hard-coded for our site). I've come to the conclusion that there might be a better workaround, or if not, a gap where a standard should be. The best practical suggestion I have is this:
A normal part of the SPNEGO process is that the client attempt to retrieve a page whose initial response is an HTTP 401 but with the header WWW-Authenticate: Negotiate. This is the cue for a GSSAPI/Kerberised client to respond appropriately; a "regular" client will simply display the error page. Perhaps the solution is simply to modify the Cosign server to deliver the human-friendly login page as part of this error response?
It might be technically difficult with off-the-shelf Apache and modules, and might go against various standards (or at least principles). I'm no expert on the systems involved, so can only speculate unless (or until) I get a chance to try it out...
Send additionally WWW-Authenticate: Basic for username/password challenge.
It depends on the application server, for example in JBoss you can set <auth-method>SPNEGO,FORM</auth-method> in web.xml and it should fall back to a login form "in cases where Kerberos/SPNEGO tokens are not present":
See https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_application_platform/7.2/html/how_to_set_up_sso_with_kerberos/additional_features

Best practice for handling secondary page requests

When building a Facebook tab application the first page receives the signed request, my question is what is the best practice to handle the secondary requests. You could save the related information in a cookie to have it on the secondary requests but that seems a little unsecured to me.
I am just curious what is the recommend way to handle this basic situation.
The signed request is just an intermediate step to getting the access_token and userid.
I put the access token into Session, and I also encrypt it and save it in a cookie. Facebook app development has taught me to go belt-and-suspenders when it comes to authentication.

How do I implement authentication the restful way?

I'm building a picture diary on web application google app engine using python. Users can sign up and post pictures to their diary.
Also, I'm trying to conform as much as I can to the REST architecture of doing things.
The authentication scheme is based like this for the web application:
1. Post username/password from the frontend
2. Backend sets up a cookie if authentication is successful
3. The rest of the AJAX calls made are authenticated using this cookie.
Is there any way to conform to REST without using cookies ?
Now, I'm also building an android application where users can sign in and post/view their picture diary. I need to expose the data from web application's datastore so I'll be building a webservice to fetch data from the datastore.
The authentication scheme for the android client:
OPTION a
1. Post username/password over https to the web service
2. Web service returns a unique authorization token (store the token in the username/pwd table on the datastore)
3. Request subsequent services by adding this token to the Request Header of the request
4. Server maps the token to the username/pwd table and returns data if token is found
5. Authorization token expires after a certain period of time
OPTION b
1. Set up a secret key on the client and server side
2. Use "username:hash of password and secret key" in the authorization header of every request
3. server generates the password by extracting the password from the hash value using the same hash algorithm ; if successful returns data
btw, I didn't wanna use basic authorization because of its security vulnerabilities.
Which is better ?
Are there other significantly better ways to accomplish what I'm trying to do ? Security is quite a concern for me btw.
I'd appreciate if anyone has any insight into this issue. thanks.
I've been doing some research myself as to what would be the best solution. I think the 2-legged oauth might work in my case as Leonm suggested.
In this case the server has to provide the client with a consumer key/secret which in my case is hardcoded in the app.
The steps now would be:
1. Generate a signature using the oauth_parameters(consumer_key, signature_method, timestamp), request url, request parameters, and the SECRET.
2. Include the signature, oauth parameters when making a request.
3. Server verifies the request by generating the signature again except in this case it uses the SECRET that corresponds to the key
I think this way I am pretty much confirming to the REST principles. The server is statless as I far I understand now.
What are the pros/cons on doing things this way?
If "security is a concern" then I would say that you'd be a lot better off using open standards and a library to achieve what you want. The main reason for this is that if you do it yourself, you're very likely to forget something; these standards have had a lot of eyes looking at them, looking for holes.
Your options include (in increasing level of complexity)
Basic authentication and HTTPS
Everything is encrypted, which makes it impossible to compress or look into, it increases the overhead somewhat, using more horsepower on the server, and more perhaps battery power on the client. Simple to implement, since it's well supported by libraries.
Digest authentication
Unencrypted messages pass the wire, but the authentication is securely managed in the Authorization headers. See the wikipedia entry for more information.
OAuth
See how Google is providing OAuth for installed applications. I believe it isn't what you're looking for, since you're not asking to share data between applications, just authenticating users.
Roll your own
If you want to roll your own, I suggest looking at e.g. how Google's (now deprecated ?) ClientLogin used to work.
Clients would GET a protected resource, and get a 401 with instructions to perform a GoogleLogin authentication, including a URI for where to perform the login itself
Clients (knowing how to do this) POST a request in a specific manner to that URI
The server responds with a specific response including a (long) token
The client can now perform GET requests to the protected resource with that token.
Statelessness
You cite REST, which dictates that requests should not specifically depend on prior interaction: "... each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server." (fielding) This means that a server shouldn't store conversational context (like an authentication token) in a table.
One way of fixing this is by using any of the token based approaches (where the server tells the client about a token it should use for future requests) where the token is not a random number, but a message to the server itself. To protect yourself from client tampering, it can be signed, and if you're afraid of clients looking at it, you can encrypt it.
Edit: Although I'm not certain, it seems unlikely that Google has a table of all authentication tokens ever issued; The length of their tokens suggests that the token is some encrypted message proving that whoever holds this token actually provided real credentials in some realm at some time.
OAuth does exactly what you want to do in a standard way.
You could use a combination of HTTPS and HTTP Basic Auth. Both are existing standards and should be secure enough when used together.