Angular app running on port 81, CouchDB running on 5984, how can I read Couch cookies?

548 views
Skip to first unread message

Mark Deibert

unread,
Sep 29, 2013, 2:26:05 PM9/29/13
to ang...@googlegroups.com
I have my web server running the AngularJS app on port 81. My database is CouchDB running on port 5984. They're both localhost but apparently since the ports are different, that means they're different domains. I read a thread in this group that says you can't access response cookies across domains. Which seems to be what I'm seeing in my code. So how can I read the CouchDB AuthSession cookie in AngularJS? Is this impossible?

Thanks a lot for your help. I'm spinning my wheels :-/


Sebastien Vincent

unread,
Sep 29, 2013, 2:43:58 PM9/29/13
to ang...@googlegroups.com
The cookie must be in the request to couchdb, not in the document. The "cannot access cookie across domain issue" is something different.

Mark Deibert

unread,
Sep 29, 2013, 2:59:28 PM9/29/13
to ang...@googlegroups.com
In the Chrome console Network tab, in response to my CouchDB _session post, I do see the Set-Cookie:AuthSession=blahblah... cookie. It's definitely in the response header, however in my AngularJS code I cannot get to the value. I tried getting to through javascript document.cookie and through the AngularJS ngCookie. In both tries, the cookie (looks the same in Chrome console) is unreadable (it has no get or text methods, no methods at all I can see), so I assumed it was this cross-domain (different localhost ports) that was making the cookie unreadable.

Sebastien Vincent

unread,
Sep 29, 2013, 3:03:48 PM9/29/13
to ang...@googlegroups.com
not in the document cookie, in the ajax request. 
Message has been deleted

Mark Deibert

unread,
Sep 29, 2013, 3:49:45 PM9/29/13
to ang...@googlegroups.com
Well, I totally agree with what you're saying, the cookie should be in the response from the post. Here is my authenticate method my services...

        authenticate: function(user,pass) {
             var loginData = '{"name":"' + user + '","password":"' + pass + '"}';
             console.log('loginData='+loginData);
             return $http({
                 method: "POST",
                 url: this.databaseUrl + "_session",
                 headers: {"Content-Type": "application/json"},
                 data: loginData
             });
        },

That return the http promise object. In the promise.success, the response does not have a cookie anywhere I can see. This why my original question assumes the cross-domain issue is blocking the cookie. Where in the response (specifically show me the response.what.whatever.etc dot notation) object will I see the cookie? I can't find it.

Mark Deibert

unread,
Sep 29, 2013, 3:54:21 PM9/29/13
to ang...@googlegroups.com
You keep saying in the "request". You mean "response" from the server right?

Sebastien Vincent

unread,
Sep 29, 2013, 4:25:26 PM9/29/13
to ang...@googlegroups.com
yes in the ajax response. Why don't you check how the jquery plugin works.

Mark Deibert

unread,
Sep 29, 2013, 5:01:30 PM9/29/13
to ang...@googlegroups.com
This is the AngularJS group right? jQuery is direct DOM manipulation which goes directly against everything AngularJS is about. So obviously I'm not using jQuery anwhere in this app.

Thanks a lot for your replies but I'll keep my fingers crossed that someone else can provide some insight.

Can anyone tell me about reading the CouchDB AuthSession cookie from within AngularJS code?

Thanks a lot for any tips :-)

Raul Vieira

unread,
Sep 29, 2013, 5:22:16 PM9/29/13
to ang...@googlegroups.com
Interesting problem.  Are you sure this isn't an HTTP only cookie? i.e., can't be accessed via javascript.

Raul
Sent from my iPad
--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/groups/opt_out.

Mark Deibert

unread,
Sep 29, 2013, 5:40:11 PM9/29/13
to ang...@googlegroups.com
I can find code where the "set-cookie" is read and parsed for the AuthSession value in node.js apps. So the cookie should (I would think) be available in the response param (this is what Sebastien was/is saying, which I do agree with) in the $http promise success, but it isn't. You know, I swear I've seen that AuthSession value in Chrome console in some past version of my code. I've tried 100 different ways of doing CouchDB authenticaiton. I finally figured out how to POST to _session which does work and does complete the login and does appear to return an AuthSession, but subsequent GET to the database generates a 401. So something is still wrong. I believe (someone correct me if I'm wrong) that I have to include the AuthSession cookie in the header of my subsequent GET, POST, PUT, etc. for authentication to be complete and work. Am I right?


--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/56yf9MsWby4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.

Raul Vieira

unread,
Sep 29, 2013, 5:53:33 PM9/29/13
to ang...@googlegroups.com
I can't comment on couchdb auth so I don't know if you're doing that right.  I want to know if the client has the cookie.  What do you chrome dev tools tell you about the cookie?  Is it http only?  When does it expire?  Is it being sent in subsequent requests?

Sent from my iPad

Sebastien Vincent

unread,
Sep 29, 2013, 8:37:42 PM9/29/13
to ang...@googlegroups.com
I meant, check how it was implemented in JQuery, but Node.js is another good one, but less similar use case.

I think maybe it has something to do with the withCredentials param in http://docs.angularjs.org/api/ng.$http.

Miguel Coquet

unread,
Sep 30, 2013, 4:00:32 AM9/30/13
to ang...@googlegroups.com
Have you been down the xdomain path completely and ruled it out? 

Here, check the question and answers here ( http://stackoverflow.com/questions/16882245/http-request-doesnt-send-cookies-cross-domain-in-angular-cors ) as they seem to me, to be pointing in the right direction. 

Reading your problem, I would say its a clear xdomain problem. 

best of luck! let us know if/how you solve it :)

Miguel Coquet

On 29/09/2013, at 19:26, Mark Deibert <mark.d...@gmail.com> wrote:

I have my web server running the AngularJS app on port 81. My database is CouchDB running on port 5984. They're both localhost but apparently since the ports are different, that means they're different domains. I read a thread in this group that says you can't access response cookies across domains. Which seems to be what I'm seeing in my code. So how can I read the CouchDB AuthSession cookie in AngularJS? Is this impossible?

Thanks a lot for your help. I'm spinning my wheels :-/


Mark Deibert

unread,
Sep 30, 2013, 6:59:17 AM9/30/13
to ang...@googlegroups.com
@Miguel: Preliminary testing seems to indicate it is exactly that. Sebastien's post and link above actually led me to this as the culprit. I had to tweak one of my CouchDB settings as outlined in that link and then I added a config object ( {withCredentials:true} ) to the end of all my $http calls. Now the 401 "Not auth" error is gone and I get data rows as expected. Huzzah!

So thank you Sebastien and Miguel, you guys nailed it :-)


A directly related followup question: I tried putting...

   $http.defaults.withCredentials = true;

early in my controller, and then removing the repeated {withCredentials:true} config object in each $http call, but this broke the code and the 401 error returned. I must not be using the $http.defaults object correctly or it's in the wrong location. Do you guys have any advice on this?



--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/56yf9MsWby4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.

Mark Deibert

unread,
Sep 30, 2013, 7:01:02 AM9/30/13
to ang...@googlegroups.com
Actually I have all the generic $http code in a dataFactory service, not in any controller as mentioned above. Just to clarify :-)

Sebastien Vincent

unread,
Sep 30, 2013, 7:42:58 AM9/30/13
to ang...@googlegroups.com
Just debug http.js there are only a few lines of codes to set the http default.

Mark Deibert

unread,
Sep 30, 2013, 8:19:14 AM9/30/13
to ang...@googlegroups.com
The line of $http.defaults code above is supposed to work according to docs and articles I've read. However, my test shows it does not or I don't know how to implement. I'll take a look at http.js and see if anything there helps resolve. Thanks :-)

Mark Deibert

unread,
Oct 1, 2013, 6:39:08 PM10/1/13
to ang...@googlegroups.com
And tonight, it's no longer working. Seems my initial thought of "it's working" was a false positive. The initial authenticate POST works, but subsequent GETs return 401 Not authorized. The only way I can make it work is to login into CouchDB as an admin. Then the app runs, authenticates as another user and GETs return data.

I'm ready to set this crappy Couch out by the curb. What Http/Rest databases do normal AngularJS programmers use?

Sebastien Vincent

unread,
Oct 1, 2013, 11:27:57 PM10/1/13
to ang...@googlegroups.com
It's probably because you need to reuse the same http object. You can just proxy the whole thing via the web server. It'll be more solid.

Miguel Coquet

unread,
Oct 2, 2013, 4:14:29 AM10/2/13
to ang...@googlegroups.com, ang...@googlegroups.com
From your posts I assume you are doing "raw requests" to couch using $http.  Before quitting on couch, I woud try to load their lib ( jquery.couch something ) and inject it into your app as a service, then use that for your couch interactions. 

You might have a better experience with that anyway. 

Also from your last email it sounded like you probably missed the xdomain setting on your $http config. Check my link again or hit the documentation for details. 

Best of luck :)

Miguel Coquet

Mark Deibert

unread,
Oct 2, 2013, 9:48:36 AM10/2/13
to ang...@googlegroups.com
Thanks a lot for the advice guys. I'll try again after work today.

Mark Deibert

unread,
Oct 2, 2013, 6:14:47 PM10/2/13
to ang...@googlegroups.com
Added the crossDomain:true to the $http.get config object, no change, still 401 on subsequent GET. I did a few screen clips and uploaded them to imgur to possibly make something visible to you guys that shows my error...

1. In my Angular app I have a login form that takes username and pass. I enter a valid username (it's in _users) and password. In the controller login method, in the sucess callback, I immediately make a cal to the .getMembers method. This GETs a view to show all members

--- This is what you see in the Chrome Console tab after usr/pass POST to _session...

http://i.imgur.com/pQGKzqf.png

 

2. This is what you see in the Chrome Network tab after usr/pass POST to _session. You can see the AuthSession cookie Couch gave in the response...

http://i.imgur.com/Z5wqDCH.png

 

3. This is what you see in the Chrome Network tab after the "getMembers" call to Couch. You can see in the request to Couch, the AuthSession cookie is not getting sent...

http://i.imgur.com/JDBzzS1.png?1


4. This is my authentication method in my base dataFactory service...

http://i.imgur.com/iNd68vB.png

 

5. This my generic GET method in my base dataFactory servcie...

http://i.imgur.com/z05D9w4.png

 

Steve Flitcroft

unread,
Oct 3, 2013, 3:45:55 AM10/3/13
to ang...@googlegroups.com
Why not simply use nginx or nodejs as a reverse proxy. Solves this issue in minutes.

Mark Deibert

unread,
Oct 3, 2013, 7:41:34 AM10/3/13
to ang...@googlegroups.com
I'm familiar with node.js but how will that "solve my issue in minutes"? Can you offer more advice?


On Thu, Oct 3, 2013 at 3:45 AM, Steve Flitcroft <steve.f...@ivendi.com> wrote:
Why not simply use nginx or nodejs as a reverse proxy. Solves this issue in minutes.

Steve Flitcroft

unread,
Oct 3, 2013, 8:11:03 AM10/3/13
to ang...@googlegroups.com
You can use simple-http-proxy within express to proxy the request to couch on a different port. From the browser it goes to the same domain http://localhost/couch -> the node proxy forwards those requests to your couch url:port.
Thus you dont fall foul of any same origin problems

e.g
   
var express = require('express'),
      proxy = require('simple-http-proxy'),
      app = express();
    
      
      app.use('/couch', proxy('http://localhost:5000'));

Mark Deibert

unread,
Oct 3, 2013, 9:37:53 AM10/3/13
to ang...@googlegroups.com
That's not a bad idea. Thanks for that. I'd like to try avoid creating another layer of code to maintain so I'd love to make this work from the Angular app directly to Couch. If I can't, I think you have the right idea. Your idea would also give me a place to provide some additional authorization to protect database assets. That would be good.

Steve Flitcroft

unread,
Oct 3, 2013, 9:40:30 AM10/3/13
to ang...@googlegroups.com
This method also allows flexibility, especially in production (think scaling out, load balancing etc) for you to chop and change the infrastructure without the client needing changes.
Good luck
Steve Flitcroft
vp software
iVendi Limited

Sebastien Vincent

unread,
Oct 3, 2013, 11:45:43 AM10/3/13
to ang...@googlegroups.com

Mark Deibert

unread,
Oct 3, 2013, 12:03:12 PM10/3/13
to ang...@googlegroups.com
Thanks Sebastien, I've read that article. A couple times actually. Carter does most of the work in authentication work in node.js as Steve is suggesting. Are you providing that link to support what Steve is saying or something else?

Sebastien Vincent

unread,
Oct 3, 2013, 12:21:02 PM10/3/13
to ang...@googlegroups.com
Definitely second Steve, It'll be a bit faster anyway, and more reliable across browser. I would even have issues with proxying to the database.

Mark Deibert

unread,
Oct 3, 2013, 12:48:05 PM10/3/13
to ang...@googlegroups.com
Ok I'll do it! ;-) 

I'll buid a node.js proxy. It seems like this will get me past this authentication roadblock between client/couch. In addition I'll get some scaling benefits (Steve mentions, good points) as well as a place to add authorization code to protect my database images from being directly accessed.

I think I'll write blog detailing this whole process once it's working. Seems like something that needs to be shared.

Mark Deibert

unread,
Oct 3, 2013, 5:05:26 PM10/3/13
to ang...@googlegroups.com
So doing this, now I'll could have 3 ports on localhost. The web app (81), this new proxy (???), and CouchDB (5984). Which won't work. So to get rid of the xdomain issues I'm gonna have to run the proxy on port 80 and pass _all_ http through it. Web page requests as well as Couch calls. Is that right?

Steve Flitcroft

unread,
Oct 3, 2013, 5:10:05 PM10/3/13
to ang...@googlegroups.com

Exactly right yes, you just need to ensure you have defined paths so you know which calls to proxy on

Miguel Coquet

unread,
Oct 7, 2013, 4:44:46 AM10/7/13
to ang...@googlegroups.com
One final contribution that might still be of use to you (OP). 

I don't know if you looked into PouchDB ( http://pouchdb.com ) but I successfully set up PouchDB and CouchDB with 2 way replication on a similar situation as yours (nodejs app serving Angular app on port 80 and couch on default port).

This might be useful even with your proxy setup, as pouchdb gives you some really nice extra niceties (localdb, offline first, sync).

Just a suggestion (not very angular related) but since I'm using that combo and loving it, i figured I'd share :)

Best regards.

-- 
Miguel Coquet


You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.

Mark Deibert

unread,
Oct 7, 2013, 9:55:40 AM10/7/13
to ang...@googlegroups.com
Thank for that Miguel! I haven't looked at PouchDB much yet, a little. It's big feature is a small footprint so that it can install on mobile devices right? Mac, Android and Windows, all of them. So you can give your mobile app "offline" capability, then Pouch syncs with a Couch when you're online. This is veeeery cool stuff!

I started to work on the node.js proxy. I search around for the easiest/quickest (meaning, mostly pre-built ;-) ) solution and didn't really find anything that I could get going fast. I got frustrated kinda quick. Probably too quick as I want to know how to do this. I will come back to this I'm certain.

So you know what I did and what is currently working? I setup Couchapp to push my AngularJS app into CouchDB. That ended up being very easy to do and completely eliminates CORS. It's all (both the app and the db) in Couch and working very nicely. I even added a Couchapp push "build" script in Sublime Text. So now in ST, I hit Ctrl-B and everything saves and pushes to Couch. I used Chrome console for debugging. So far so good :-)

Thank you again for that PouchDB tip. I definitely have plans to build a mobile version of my site and I think PDB is the way to go.


Miguel Coquet

unread,
Oct 7, 2013, 10:13:43 AM10/7/13
to ang...@googlegroups.com
If a couch app works for you, then I guess you'r set :)

Personally, I like PouchDB because of how much work it takes away. It took me a little bit of effort to get it going with Angular (i wanted changes to the DB to immediately reflect on the UI) because both are fairly new to me, but it ended up being a rather simple affair :)

Best of luck and have fun :)

-- 
Miguel Coquet


Mark Deibert

unread,
Oct 7, 2013, 10:38:40 AM10/7/13
to ang...@googlegroups.com
Are you building a mobile app or a web app? If just web, why did you choose Pouch over Couch? I need to go read more on Pouch ;-)

Miguel Coquet

unread,
Oct 7, 2013, 11:36:08 AM10/7/13
to ang...@googlegroups.com
I'm building a single page web app. Mobile is more of a nice to have. 

I chose pouch because: 
1) I wanted a nicer local data abstraction (the best I could find in Angular was $resource)
2) I didn't want to be bothered with communication and data syncing. 

Using Pouch+Couch gave me that :)

I use Pouch (local data) as my source of data for my models, and just turn on 2-way replication to the server. 

I have very small datasets that I'm pulling into the client, so this fits my use case very well (mostly transient data) as it is, and gives me the tools to do more complex stuff later.

Cheers
-- 
Miguel Coquet


Reply all
Reply to author
Forward
0 new messages