How to get JSON data via Javascript with cookies authentication? - javascript

I'm building an application with Ruby on Rails. The application is a Javascript application that get data by JSON calls from the api application. It also provide the cross domain authentication for the application itself and the api.
I handle the cross domain authentication via making both application cookies with same secret session key and same name e.g. _app_an_api_session.
Now, I'll write down the senario and I'll show you when it fails.
The application domain is domain.local the api domain api.domain.local
Lets say that api.domain.local/me is a protected page. When I open it i got unauthenticated
When I go to the application and sign in and go to api.domain.local/me again, I can see the data in it. [Pass] [it works also for the opposite actions].
The problem is, for example, after sign in I want to load api.domain.local/me contents [JSON data] in domain.local, I can see in the console that the status is (canceled).
In addition for debugging sake. I tried to see the env variable on each request to the api. So, when I access the api.domain.local/medirectly, I can see the cookies hash in the console, else if it via the real application, there's no cookies/sessions at all.
So, how to make it possible to done this right?

Your issue is the Same-Origin Policy that prevents communication between different domains and subdomains. You can resolve this either through using a proxy, JSON-P or an external proxy.

Related

How to share one token between multiple Vue apps

I want to find a method how to share one token between multiple vue apps. With this i can create multiple single page application mimicking the microservices on back end. I was thinking about putting it into Vuex and save the state in localstorage/cache however i cannot retrieve the same state for another app. Any suggestions?
For such case using cookies would be appropriate.
Unlike localStorage, it is possible to share same cookie across parent domain (example.com) and subdomains (sub-domain.example.com). It is done by specifying domain property of cookies as wildcard - .example.com (note the leading dot in front of the domain name). Relevant answer
Depending on application architecture, you can manually read cookie in front-end on application startup, verify if user is singed in and save it to the store.
In case API is hosted on a subdomain as well, it is possible to make a request to the API (if cookies domain is specified, cookies header will be sent with a request) and verify if user is authorized to access the app. It is only suggested, if API doesn't check token in different way (e.g. in payload or Authorization header).
In both cases, it would be suggested to create API endpoint to verify token, call it on application mount and handle appropriately.
Also, since managing cookies manually may get quite uncomfortable, using third party libraries will provide similar API as using localStorage. For example: js-cookie.

How can I send cookies of a Web Api back to it from a different front-end application

I have a web application that serves only static contents - HTML, CSS and JavaScript. I have another application which is an ASP.NET Web API. Both applications are on same machine on different ports (for testing purpose and they could be on different machine or domain in production environment). When I browse the web application, it gets both cookie as well as form token of Anti CSRF on first ajax call from Web API. So I am setting the body token as header with setRequestHeader function of XMLHttpRequest. It doesn't seem there is any need to set the cookie token since cookies are restricted with HttpOnly Attribute for a security reason and as far as I know browser is responsible to send the cookie to whichever domain the cookie belongs to.
However, when I make consecutive ajax calls, instead of both these tokens being passed back to server, only the header token is being received by the server.
Currently the Web API is set with CORS restriction for the web application. But if the problem was related to cross origin then I guess, headers could not have been passed as well, correct me if I am mistaken.
So can anyone help me with this problem? I just want to be able to send cookies from one application to another without compromising in terms of security.
Take a look Cookies With My CORS and Set-Cookie in HTTP header is ignored with AngularJS

Reading a cookie from a different domain

I'm developing a page/form for a campaign inside my company. However, the first step is to check if the person is logged in. This is easily checked against a cookie - CUSTOMER - that is set once they're logged in.
However:
1) I'm developing locally, not on the same domain, and, as a result can't see that cookie
2) The final campaign may or may not end up residing on the actual domain. They may end up using a vanity URL or something.
For purposes of this, let's assume I do NOT have access to the main domain where the cookie was set.
How can I read that cookie from off the domain? Oh, and since IT folks don't let us touch the back-end grumble, it has to be a JS solution.
Thanks!
You can't.
The only cookies you can read with client side JavaScript are those belonging to the host of the HTML document in which the <script> is embedded.
By setting withCredentials you can support cookies in cross-origin requests, but they are handled transparently by the browser and JS has no direct access to them (the XHR spec goes to far as to explicitly ban getAllResponseHeaders from reading cookie related headers). The only way for a cross-origin request to get access to cookies is for the server (which you say you don't have access to) to copy the data into the body or a different response header).
You can if you can install server side components.
You can use a dedicated domain to host your cookie and then share it using XSS technics
When dom1.foo.com logs in then you register a cookie on cookie.foo.com using an Ajax XSS call then when you go on dom2.foo.com you have to query cookie.foo.com with your XSS api
I' ve played with it some time ago
https://github.com/quazardous/mudoco/blob/master/mudoco/README.txt
It's just some sort of POC..

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.

WCF REST Authentication - Determine Web Request

What is the best way to determine if a request being made to my REST service originated from a web client. I know I can look at the user-agent, but my concern is that is very easy to spoof.
The reason I want to know who originated the request is because of the following. It is natively built into web-browser that you can't do cross-domain requests. Therefore I don't need to worry about the authentication, because I know the request originated from my website.
My site is built entirely in HTML and Javascript, any suggestions?
Or is there a good way in Javascript to store a hidden username / password I can use just for my website, without it being displayed to the public?
Thanks,
Adam
Anything put in the javascript can be found by using a debugger, such as Firebug, so even though it isn't visible to the user, it can be found by a user.
But, if the javascript first calls to a REST service to get an encrypted token, then the token, which has a timestamp encrypted within it, could be the password, so you then pass the username and token to call the rest of the REST services.
Your server could then validate that it had created the token and that it is not expired, and that the username matches what was encrypted in the token.
But, this depends on if you have any control over the REST service.
The reason I want to know who originated the request is because of the following. It is natively built into web-browser that you can't do cross-domain requests. Therefore I don't need to worry about the authentication, because I know the request originated from my website.
This is not a good assumption. For the reasons you already gave (easily spoofed User-Agent), anyone could make a request to your application. You can even disable cross origin policy in firefox and chrome from the client side - so even if you could verify the request came from a browser, it's still possible to get around your security measures:
Disable same origin policy in Chrome
There are a couple of standard ways to implement security for this kind of service (as James mentioned, assuming you have control over the REST service).
Use Basic Authentication - If your application is communicating with the WCF service via HTTPS, basic authentication is probably the easiest method. See this question
If both your website and your WCF service are implemented using .NET, and your ASP.NET web application is using Forms Authentication, you could share the Forms Auth cookie and use that for authentication. See this question

Categories

Resources