A simple question, I think.
If I use the google users accounts in appengine
from google.appengine.api import users
to authenticate my users, how secure is the rest of my app under http (not https), ie. where are the weak points of such a setup?
Thanks
Assume that anything you send over http can be intercepted and examined by an attacker. This includes whatever token you are storing in their browser to authenticate them - the attackers can see this too, and use it to fake requests.
If this sounds like a "theortical" vulnerability that you don't need to worry about, then you shouldn't do anything that involves safeguarding user data until you read up on FireSheep and understand how it works and how you would prevent something similar. (This is just one example of an attack you need to understand. It is not the only possible attack.)
In short, the weak points of such a setup are all the points where you are using http to send anything you want to keep private.
Your question is unclear, but if you're asking whether authenticating users with Google Accounts on an HTTP app could potentially expose passwords to an attacker, the answer is no.
Even though your app is not using SSL, passwords are never transmitted in plain text. When authentication starts, users are redirected to a secure page at google.com to enter their credentials. Credentials are posted via SSL, and if authentication succeeds, Google generates an authentication token that is passed back to your app and stored in a cookie. The Users API makes an internal RPC to resolve this token back into Google credentials.
The most that an attacker could do is intercept the authentication token and spoof the user for the duration of the token's validity (1 day by default; configurable up to 2 weeks). They would never have access to passwords. To prevent spoofing, you'd need to make sure all logged in activity happens on HTTPS and the auth cookie is never stored via HTTP.
Related
I'm developing the restful web app that using some popular web framework on the backend, say (rails, sinatra, flask, express.js). Ideally, I want to develop client side with Backbone.js. How do I let only my javascript client side interact with those API calls? I don't want those API calls to be public and be called by curl or simply by entering the link on browser.
As a first principle, if your API is consumed by your JS client, you have to assume, that it is public: A simple JS debugger puts an attacker into a position, where he can send a byte-for-byte identical request from a tool of his choice.
That said, if I read your question correctly, this is not, what you want to avoid: What you really don't want to happen is, that your API is consumed (on a regular basis) without your JS client being involved. Here are some ideas on how to if not enforce, then at least encourage using your client:
I am sure, your API has some sort of authentication field (e.g. Hash computed on the client). If not, take a look at This SO question. Make sure you use a salt (or even API key) that is given to your JS client on a session basis (a.o.t. hardcoded). This way, an unauthorized consumer of your API is forced into much more work.
On loading the JS client, remember some HTTP headers (user agent comes to mind) and the IP address and ask for reauthentication if they change, employing blacklists for the usual suspects. This forces an attacker to do his homework more thoroughly again.
On the server side, remember the last few API calls, and before allowing another one, check if business logic allows for the new one right now: This denies an attacker the ability to concentrate many of his sessions into one session with your server: In combination with the other measures, this will make an abuser easy detectable.
I might not have said that with the necessary clarity: I consider it impossible to make it completely impossible for an abuser to consume your service, but you can make it so hard, it might not be worth the hassle.
You should implement some sort of authentication system. One good way to handle this is to define some expected header variables. For example, you can have an auth/login API call that returns a session token. Subsequent calls to your API will expect a session token to be set in an HTTP header variable with a specific name like 'your-api-token'.
Alternatively many systems create access tokens or keys that are expected (like youtube, facebook or twitter) using some sort of api account system. In those cases, your client would have to store these in some manner in the client.
Then it's simply a matter of adding a check for the session into your REST framework and throwing an exception. If at all possible the status code (to be restful) would be a 401 error.
There's an open standard now called "JSON Web Token",
see https://jwt.io/ & https://en.wikipedia.org/wiki/JSON_Web_Token
JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for
creating tokens that assert some number of claims. For example, a
server could generate a token that has the claim "logged in as admin"
and provide that to a client. The client could then use that token to
prove that they are logged in as admin. The tokens are signed by the
server's key, so the server is able to verify that the token is
legitimate. The tokens are designed to be compact, URL-safe and usable
especially in web browser single sign-on (SSO) context. JWT claims can
be typically used to pass identity of authenticated users between an
identity provider and a service provider, or any other type of claims
as required by business processes.[1][2] The tokens can also be
authenticated and encrypted.[3][4]
Set a SESSION var on the server when the client first loads your index.html (or backbone.js etc.)
Check this var on the server-side on every API call.
P.S. this is not a "security" solution!!! This is just to ease the load on your server so people don't abuse it or "hotlink" your API from other websites and apps.
Excuse me #MarkAmery and Eugene, but that is incorrect.
Your js+html (client) app running in the browser CAN be set up to exclude unauthorized direct calls to the API as follows:
First step: Set up the API to require authentication. The client must first authenticate itself via the server (or some other security server) for example asking the human user to provide the correct password.
Before authentication the calls to the API are not accepted.
During authentication a "token" is returned.
After authentication only API calls with the authentication "token" will be accepted.
Of course at this stage only authorized users who have the password can access the API, although if they are programmers debugging the app, they can access it directly for testing purposes.
Second step: Now set up an extra security API, that is to be called within a short limit of time after the client js+html app was initially requested from the server. This "callback" will tell the server that the client was downloaded successfully. Restrict your REST API calls to work only if the client was requested recently and successfully.
Now in order to use your API they must first download the client and actually run it in a browser. Only after successfully receiving the callback, and then user entry within a short frame of time, will the API accept calls.
So you do not have to worry that this may be an unauthorized user without credentials.
(The title of the question, 'How do I secure REST API calls', and from most of what you say, that is your major concern, and not the literal question of HOW your API is called, but rather BY WHOM, correct?)
Here's what I do:
Secure the API with an HTTP Header with calls such as X-APITOKEN:
Use session variables in PHP. Have a login system in place and save the user token in session variables.
Call JS code with Ajax to PHP and use the session variable with curl to call the API. That way, if the session variable is not set, it won't call and the PHP code contains the Access Token to the API.
I'm a back-end developer who has to create the front-end too in the current project!
I'm using reactJs and I know that for authorizing users I should get an api_token from my back-end API then use the api_token in the next requests! so I should store the api_token (actually somewhere into the client's browser)! but where should I store it to be secure?
the first answer came to my mind was 'Local Storage' ! but I've read this article: Don't store tokens in local storage
I've searched and found #auth0/auth0-spa-js, but I don't know can I trust this package (and similar) or not?
these are the way's which I've found! but what's the correct way to store sensitive data like this?
The Auth Flow should be on the Web should be
Send User/Password Details to server
Server validates and returns encrypted token with some details inside and that's stored as a HTTP Cookie
Setup Protected endpoints so only users with token can access them
Security : HTTP Cookie only means that the browser doesn't have access to it on the client, only the server. But someone can simply just Copy Paste it into their cookies which if you're worried about or working on sensitive stuff, you will need to implement additional security measures such as the ones mentioned.
Generally, Device Management is not a web concern but you can also some validation on the token for things like make the token expire in 5 minutes, or expire on session end, DeviceId, Browser Id, IP address, send them an email that a new unknown IP has logged in, etc.
Never store private tokens in your frontend code
You should create a server that can only be accessed from a particular url (the url of your app). This server can have the secret tokens that you need to make calls. The that server can forward requests to the services you will use that need private tokens.
I have developed a single page AngularJS application. For data retrieval/storage, it communicates with REST APIs over https. As per client requirement, i need to implement Client Authentication. i.e., As the application is based on REST APIs, how can we ensure that the request made to API is from a valid client and not from fiddler or a tempered client.
the current approach is:
1> configure a client secret and a key in the angular app.
2> authenticate the client by requesting a token from server using this client secret and key.
3> server checks this secret and key, if validates, responds with a newly generated token.
4> all further requests from angularjs app would carry this token in header, to ensure that the request is from a valid client.
But it is not good enough, as attacker can easily capture the requests using fiddler and also can easily read the client secret and key. or can debug using firebug.
Is there any secure way to authenticate the client app?
No security possible in the case if your REST API call is been shield by any User Authentication. I mean if User need to put Username/Password then they are able to call those API then you can implement some security.
But if your requirement like follows :
Any GUEST user with any browser open your application pages, which intern call your REST API.
Then there is no security. Since any attacker can intercept your Request/Response and call it further.
Note : From security prepective, Whatever a Browser can do, any good attacker can do the same.
But if you shield REST CALL Pages with username/password validation, then you can restrict the calls from server side with proper session validation.
JSON Web Tokens (JWT - pronounced jot) might be what you're looking for. Auth0 has a swell blog post that specifically addresses AngularJS + JWT.
You cannot trust the client to validate anything. If the user is using Firebug or Fiddler to "trick" your application then all you can do is verify the information server side to ensure it is valid.
You can trust the client to keep the user's session safe (to some extent), but if you can't trust the user then you can't trust anything the client sends to you.
If you need to ensure the integrity of a piece of data that is held client side you can use a MAC (Message Authentication Code) which is effectively a hash of the message appended to a server-side secret key that can be later verified. Sometimes this is (incorrectly) called signing. JWTs are the current standard to accomplish this.
It depends at the end of the day what threat you are trying to keep your application safe against - if it is a game with high scores that runs on the client, there's not much you can do to prevent the user from altering their score before it is sent to the server. If you need to trust such data, run it server side.
I'm designing a REST API and I've hit somewhat of an odd point. 99% of this API will be secured, but there are a few functions that need to be publicly accessible. These pertain to account creation, and initial password setting. Once they have credentials, they can access the rest of the API.
The endpoint that allows a user to create a new account via a signup form is unauthenticated. Securing this endpoint isn't really possible because I'm using AngularJS on top of nodejs, and dog-fooding my API via AJAX calls. This means I can't hide credentials anywhere to access the AccountCreation endpoint. Currently, I have the webform make an AJAX call to another endpoint and create a token that says to form is valid. Upon submission that token is validated, then removed from the database. However, this token endpoint is obviously visible in code, so not much security there. Email verification is used to 'activate' the account, then the user is given a one-time link to set their initial password, which also resides on an unauthenticated endpoint(but requires the token sent in the email).
I guess my worry is someone spamming the 'CreateAccount' endpoint, and making a bunch of accounts. In reality I guess they could simply do this via the webform as well. Is this a valid security concern? How do most places handle unauthenticated account creation webforms?
Edit: the final application will be run over https
I have a GAE app, with a URL I restrict to admin:
- url: /admin
script: _go_app
login: admin
I want to PUT or POST to this url with another Go program. What code do I need to write for the client to authenticate to GAE and dev_server.py? Is there a more sensible way that just mocking a web-browser and logging in? I don't need to authenticate or authorise other users, just the admin account for that app.
Is this OAuth? OAuth2? OpenID? Federated? Something else?
I realise this is a bit of an awkward question, since I'm not even sure what the right way to ask it is. However I am able to post to (in this example) /admin using a web browser after logging in with my (admin) gmail account. In that case the request (sent by Chrome) contains the cookies: __cfduid, ACSID (and what I think are Google Analytics IDs). Presumably one of those is responsible for my authentication. How do I get one of those?
And as a side question, if someone MITMs my connection (over http), can they hijack my admin session by reusing that cookie?
GAE likes OAuth2
Have a look at goauth2 . It seems to be the canonical OAuth2 library for Go. They provide a fairly comprehensive example at https://code.google.com/p/goauth2/source/browse/oauth/example/oauthreq.go .
With regards to your question "Presumably one of those is responsible for my authentication. How do I get one of those?", they state:
To obtain Client ID and Secret, see the "OAuth 2 Credentials" section under
the "API Access" tab on this page: https://code.google.com/apis/console/
And, finally, my humble opinion on "if someone MITMs my connection (over http), can they hijack my admin session by reusing that cookie?" is that you should never provide any authenticated connection (nor the connection that does the authentication) over plain http. Especially an admin section.
EDIT: To elaborate on the MITM question, make sure you use HTTPS for any login requests and subsequent requests for the same session, and make sure to set Secure and HttpOnly flags on your cookies.
OAuth2 if you want to use Google Accounts.
See here for details: https://developers.google.com/appengine/docs/go/users/overview (this section specifically deals with admin views)