How to share authentication between website and service for Ajax - javascript

I have a WebSite (MVC 4) and WebService (Web API). WebSite has an authentication cookie and it decrypts that in order to send a secure token on to WebService when the WebSite server side code calls the service. That works fine.
However, the WebSite has JavaScript that I would like to call the WebService directly. I've tried sharing the MachineKey and Auth information, but the cookie is not carried across the WebApi.
My fallback is to route all calls to the WebService via the WebSite; but that's ugly and slow.
Any ideas?

The correct answer is Darin's. In order to share a login cookie between a services site and a web site, they will both have to be on the same domain; so e.g. the services site could be at
http://svc.mysite.com
And the web site could be at
http://www.mysite.com
Then the browser will allow the two sites to share the same cookie.
An alternative would be to have the site authenticate to the services site and get a token of some kind it could pass to the javascript. However, unless you were running on HTTPS this would be highly insecure, as the token would be available "in the clear".
A final mechanism (and the most common solution I think) would be to route all API accesses through the web site, but this is not ideal in many circumstances.

Related

Spa app w/ Web API security concern. Can a logged in user with a JWT make random requests to API

I have a security concern about building a SPA application.
What is stopping an end user to make calls to my Web API as long as they have a token?
For example: I am an end user to a Spa web application and I login through the login form. Get access to the JWT token provided to me (assuming this is easy). Then open up postman and try making every call possible putting that token in the header of every request.
I am assuming the only calls I would be able to make are the ones I would be authorized to make through the UI due to Web API authorization.
Is there any type of security out there to prevent this or is it basically just make sure your Web API has proper authorization?
There is absolutely no difference here to regular websites/web applications. Yes, anyone can try to make any HTTP calls they wish to your server. That holds for plain websites, jQuery sites, SPA sites, mobile applications or Flash games. Your server needs to do the proper authorisation and validation to ensure the user is allowed to do what they're attempting to do.

How to secure user name/password in JavaScript client interfacing with REST API

I am developing a RESTfull web services. This web services will serve as a Web API to the outside world to get some data from our system. So, it will be consumed by other external clients: Mobile Apps, JavaScript clients, etc. For security, it will require Basic HTTP Authentication: user name and password sent as clear text over HTTPS.
So, I want to put together a proof of concept JavaScript application to demonstrate how one would use this API. But I don't want to hard-code user name/password in JavaScript code, since it can be viewed in page HTML source. In fact I don't want JavaScript to be involved in Authentication at all. So, I was thinking having another web page for server to server authentication. So that client's server sends credential to WEB Appi server, then Web API server issues a token valid for one session only, after that Client server uses this token in JavaScript.
Is this the right approach? If not, what's the "best" solutions for this scenario? I am sure this was done before. Any articles, or code samples will be much appreciated. Thank you

Authenticate client-side app to REST API using CORS with local strategy

The Problem:
Serving a secure API to a client side app using only a local authentication strategy. The red arrows are part of the knowledge gap.
Context:
That is --- client.example.com is making a POST to api.example.com/login where on success client.example.com can gain access to a GET service like api.example.com/secret.
An idea!
Implimentation of OAuth 2.0 with hybrid grant type sitting in front of API.
Why hybrid?
It wouldn't be an Implicit Grant Flow aka Client-Side Web Applications Flow because there is no redirection to API server too grant access token. (i.e.) "Is it ok for so-and-so to access your data?"
It wouldn't be a Resource Owner Password Flow because a Client ID and Client Secret are passed along with the request so it's assumed the client app is server-side.
OK... so what about a little bit of both?
What if we used a CRSF token on page load of client-side app, and POST it with user credentials too OAuth 2.0 authentication endpoint to exchange for access token? You would authenticate each subsequent request with the access token and CRSF token after a successful login.
A good Node.js OAuth 2.0 library I found:
https://github.com/ammmir/node-oauth2-provider
Help Me!
I can not find a working example of an authentication measure that solves this problem! Point me in the right direction?
Ultimately, the goal here is too authenticate a client side app to a REST api using CORS with a local strategy --- i.e. username & password --- even if the convention above isn't possible.
To Accommodate Bounty:
This is a client side app, so let's stay trendy.
I'm looking for a working example using the Node.js OAuth 2.0 seed above for the API/Auth server and a front end framework like Angular.js or Backbone.js to make requests.
The example should match the context described above.
I'm working on an app with a pretty similar architecture though the services are .NET Web API rather than Node and we're using DotNetOpenAuth for the OAuth provider. Rather than the hybrid approach you're suggesting we're doing the following:
x.com serves up a login page
login page POSTs back credentials to x.com
server side logic at x.com combines client_id and client_secret with the credentials to submit a token request (resource owner password credentials grant that you've
mentioned above) receiving back both a temporary access token and a
refresh token
the refresh token is encrypted into a cookie issued by x.com
both the cookie (with encrypted refresh token) and the temporary access token are then sent to the browser
the client app (angular in my case) can now use the access token to hit api.x.com for services (It appears you're well aware of the limitations of CORS... we hacked a version of angular's $resource to facilitate this but it wasn't pretty since we wanted to use all HTTP verbs and support IE9)
when the access token expires, the client side app can request a new access token from x.com
server-side, x.com decrypts the cookie to get at the refresh token and issues another oauth call for a new access token
This is fairly high-level but hopefully gives you a sense for how to tackle your situation. In my case, and it appears in yours, we didn't want to use session state or a database to store the refresh token but obviously exposing that to the browser introduces security concerns so the encryption of the refresh token is important (among other security considerations) and the use of the cookie eliminates the need for session state or other persistent storage on x.com.
Not an answer running for the prize. Just my 2 cents :)
On my web server,
I do my authentication through a rest call with login/password with basic authentication over https. This call delivers a key to the client (a one page web app).
Then every subsequent REST call is signed with the key. The server checks that the signature is correct and everything still happen in https.
This mechanism is quite used I believe.
I don't see the issue with cross domain. I have a single source anf if I need something from another source, I'd use JSONP.
I use nginx as an https->http forwarder.
Not sure how it competes with an OAuth2 solution.
I've built this example using Node and PassportJS to show how to authenticate the users with Facebook or Local Strategy. Both sides are on different domains as you described and it requires CORS enabled.
GitHub: https://github.com/pablodenadai/Corsnection
Live demo: http://corsnection-client.herokuapp.com/
I can't promise that I have time to write working example but I can show you 2 paths :)
The biggest deal is CORS. After you solve that problem it is easy to use $http service. So, first and probably easiest may be to configure reverse proxy in x.com webserver which points to api.x.com. I wrote article here
Second approach is better, and created for exactly this purpose, to authorise specific domain to use your resource. It involves a bit of coding in api.x.com so you don't have to change anything in new web applications served in other domains. You simply need to authorise CORS requests in api.x.com service.
Create table in database where you can manage list of authorised domains
Add in that table record "x.com"
in api.x.com add request filter/interceptor what ever tech term you use for method which should be invoked after request is handled and add in response Access-Control-Allow-Origin: x.com if request comes from x.com (in other words check in request header refer value match to any value in table above and put that value in Access-Control-Allow-Origin response header).
That is all :) After this if you know how to use $http or jQuey.ajax you will be able to POST/PUT/DELETE/... any request to api.x.com from any authorised domain in just few minutes.
I very similar idea using vinilla js web app and cross domain authentication to GAE backend or OpenID connect.
The web app is run on CDN. When click login link, it goes to respective login server and redirect back to the web app (with XSRF security token and HTTPS only cookie). Login server accept cross domain request with credentials. XSRF token has to be set (in header) with every request. cookie is set by the browser. Since it is HTTP only cookie, JS cannot read it. The technique is very secure.
Once login, you can get secure assess from login server.
For detail description, you can find here and open source repo here.

How can I use CAS with a Javascript Client that will be hosted as well as used in Phonegap?

I am writing a Phonegap application that needs to be able to call remote webservices that are secured by CAS. The application will also be hosted on our webfarm (minus the hardware specific parts) as a mobile web site.
Our CAS server is hosted by server1 and our webservices are hosted on server2. The mobile web site is hosted on server2.
Any calls I make from Javascript get a cross-domain error. I realize this isn't an issue for the phone, but it would be nice to avoid it due to development being so much easier when running on the desktop.
Currently, I have a working setup that consists of the following:
Javascript calls a server-side script on server2 over https, including the username and password in the header.
The script calls CAS' RESTful api and gets a ticket granting cookie. The script creates a Set-Cookie header in the response or it reports back with a login error.
Javascript gets the response and creates the cookie (though this cookie is undetectable in Phonegap (nothing in document.cookie), even though it's getting passed around).
Javascript then calls a server-side script which calls a webservice for it, passing the cookie with the request (I had to manually insert the cookie into the request header, even though it automatically was passed in the request from javascript).
The server-side script sends the results to javascript.
Is there a better way to do this? I've seen mention of proxy tickets in CAS, but cannot find enough information to know whether it's what I need or how to use them.
Thank you.

API Authentication via JavaScript SDK

I am building a JavaScript SDK for our API. The API currently requires (2-legged) OAuth authentication. Obviously this isn't suitable for a JS SDK since the key and secret are in plain site (in the JS code).
Facebook only requires your app id when you init their JS SDK, so I would like to implement something similar (or of similar simplicity). When a developer requests a key we require their app's domain. I was thinking of detecting the IP address of the submitted domain (for example myclientapp.com has 192.168.0.0 IP). And then authenticating JavaScript requests by confirming the remote hosts IP address matches.
Is this the best/easiest way of doing this?
UPDATE: As Rup pointed out the remote IP will be the client and thus not match the apps URL's IP. So that's out. So to reiterate I'm looking for a solution that will allow me to enforce some form of authentication in my JavaScript sdk for my API that can't be spoofed by someone else (trying to be someone elses app).
Thanks,
Gavin
Authenticate the user instead.
Have the (claimed, but untrustworthy) app id passed into your init(), jsonp out to your domain, then either:
Return a code valid for making API requests with, if the user is logged in* and has already authorized the app.
Pop up a window to your site (or redirect, or whatever) to have the user login (if needed) and authorize the app.
You'll have control of the user experience during authentication, and can do some human verification of the app id (show the claimed logo, name, etc.).
This does assume that you even have a notion of users, like Facebook does.
*Check cookies, not all browsers accept them in response to ajax requests; but all browsers will send them.

Categories

Resources