Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

npm login fails after adduser #73

Closed
leecookson opened this Issue Jul 23, 2012 · 14 comments

Comments

Projects
None yet
2 participants

With a clean install of couchdb 1.1.1, node 0.8.3, and npm 1.1.44, I am unable to perform 'npm login' nor 'npm publish' successfully after a successful adduser. I can see the the user in the /-/user/ document,

With an existing instance, this broke some time between July 12 and July 14, so I decided to set up a completely new instance with a single, unique user name.

The same error occurs with npm 1.1.35 + node 0.8.3, and also occurs with npm 1.1.44 + node 0.6.14, so it seems to be an issue with the couch app.

Short output:
npm http PUT http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
npm http 409 http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
npm http GET http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
npm http 200 http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
npm ERR! Error: login error
npm ERR! at RegClient. (/usr/local/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:81:22)
npm ERR! at CouchLogin. (/usr/local/lib/node_modules/npm/node_modules/couch-login/couch-login.js:104:12)
...
npm ERR! System Linux 2.6.18-274.3.1.el5
npm ERR! command "node" "/usr/local/bin/npm" "login"
npm ERR! cwd /home/XXXXXXXX/tmp/tesla.tool.release.test
npm ERR! node -v v0.8.3
npm ERR! npm -v 1.1.44

debug output:

0 info it worked if it ends with ok
1 verbose cli [ 'node', '/usr/local/bin/npm', 'login' ]
2 info using npm@1.1.44
3 info using node@v0.8.3
...

4 verbose config file /home/XXXXXXXX/.npmrc
5 verbose config file /usr/local/etc/npmrc
6 verbose config file /usr/local/lib/node_modules/npm/npmrc
7 verbose adduser before first PUT { name: 'wsjbuilder',
7 verbose adduser salt: 'XXXXXXXX',
7 verbose adduser password_sha: 'XXXXXXXX',
7 verbose adduser email: 'com.dj.tesla@gmail.com',
7 verbose adduser _id: 'org.couchdb.user:wsjbuilder',
7 verbose adduser type: 'user',
7 verbose adduser roles: [],
7 verbose adduser date: '2012-07-23T14:30:57.925Z' }
8 verbose url raw /-/user/org.couchdb.user:wsjbuilder
9 verbose url resolving [ 'http://registry.npm.wsjfdev.dowjones.net/',
9 verbose url resolving './-/user/org.couchdb.user:wsjbuilder' ]
10 verbose url resolved http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
11 info retry registry request attempt 1 at 10:30:57
12 http PUT http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
13 http 409 http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
14 verbose adduser update existing user
15 verbose url raw /-/user/org.couchdb.user:wsjbuilder
16 verbose url resolving [ 'http://registry.npm.wsjfdev.dowjones.net/',
16 verbose url resolving './-/user/org.couchdb.user:wsjbuilder' ]
17 verbose url resolved http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
18 info retry registry request attempt 1 at 10:30:57
19 http GET http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
20 http 200 http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
21 verbose adduser userobj { name: 'wsjbuilder',
21 verbose adduser salt: XXXXXXXX',
21 verbose adduser password_sha: 'XXXXXXXX',
21 verbose adduser email: 'com.dj.tesla@gmail.com',
21 verbose adduser _id: 'org.couchdb.user:wsjbuilder',
21 verbose adduser type: 'user',
21 verbose adduser roles: [],
21 verbose adduser date: '2012-07-23T14:30:57.925Z',
21 verbose adduser _rev: '2-b7f7c8b836ce073eab2c6ff24ab4e9ae',
21 verbose adduser _etag: '"2-b7f7c8b836ce073eab2c6ff24ab4e9ae"' }
22 verbose url raw /-/user/org.couchdb.user:wsjbuilder/-rev/2-b7f7c8b836ce073eab2c6ff24ab4e9ae
23 verbose url resolving [ 'http://registry.npm.wsjfdev.dowjones.net/',
23 verbose url resolving './-/user/org.couchdb.user:wsjbuilder/-rev/2-b7f7c8b836ce073eab2c6ff24ab4e9ae' ]
24 verbose url resolved http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder/-rev/2-b7f7c8b836ce073eab2c6ff24ab4e9ae
...
...
25 verbose adduser headers:
25 verbose adduser { date: 'Mon, 23 Jul 2012 14:30:57 GMT',
25 verbose adduser server: 'CouchDB/1.1.1 (Erlang OTP/R14B03)',
25 verbose adduser 'content-type': 'application/json',
25 verbose adduser 'content-length': '43',
25 verbose adduser 'cache-control': 'must-revalidate',
25 verbose adduser 'set-cookie': [Object],
25 verbose adduser connection: 'close' },
...
...
25 verbose adduser statusCode: 200,
...
...
25 verbose adduser body: { ok: true, name: null, roles: [Object] } },
25 verbose adduser { ok: true, name: null, roles: [ '_admin' ] } ]
26 error Error: login error
26 error at RegClient. (/usr/local/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:81:22)
26 error at CouchLogin. (/usr/local/lib/node_modules/npm/node_modules/couch-login/couch-login.js:104:12)
26 error at Request.init.self.callback (/usr/local/lib/node_modules/npm/node_modules/request/main.js:120:22)
...
...
28 error System Linux 2.6.18-274.3.1.el5
29 error command "node" "/usr/local/bin/npm" "login"
30 error cwd /home/XXXXXXXX/tmp/tesla.tool.release.test
31 error node -v v0.8.3
32 error npm -v 1.1.44
33 verbose exit [ 1, true ]

Owner

isaacs commented Jul 23, 2012

So, this is somewhat interesting... With npm 1.1.44, it should be logging in with a new session if it receives a 401. That appears to either be not happening, or not working.

I'm not sure if this is relevant, but the central iriscouch registry is on couchdb 1.2.0. Maybe try upgrading?

Also, make sure that you have the same design doc as this: https://isaacs.iriscouch.com/registry/_design/app

Is there a _token and/or _auth config in your ~/.npmrc file? If so, try removing _token, but leaving the _auth config setting as it is. Does publishing/etc work then? Does it create a new _token setting?

This broke first around 7/13 when the couchdb was 1.2.0. I didn't downgrade to 1.1.1 until I needed to trouble-shoot the login/publish problem a couple days ago.

The _design/app's for iriscouch and our registry are identical.

I tried deleting the _token in .npmrc and it failed the same way. After the failed 'npm login', I do get a new _token in .npmrc

BTW, it hits a 409 the first time, not a 401.

Based on the timing, could the commits on 7/10 are related?

Owner

isaacs commented Jul 23, 2012

Ok, I think that I found the problem.

If you have an empty .npmrc file, then you can do npm adduser, and it'll work. (npm login is just an alias to adduser; they're the same exact code.) Call this user-a

Then, if you do npm adduser with different user credentials (user-b), it'll try to use the user-a credentials when it does the GET to fetch the _rev for the user doc, if there was a token assigned for user-a, since the couchLogin util doesn't get cleared out.

Nice find. Fix coming soon.

Owner

isaacs commented Jul 23, 2012

So, that's why you get a 401 or a 404 -- the 401 is saying, "You gave me a token that makes no sense with the Authorization header, please re-login to correct this", and the 404 is saying, "You are requesting a user doc that isn't yours so I wouldn't tell you I had that even if I did."

@isaacs isaacs added a commit to npm/npm-registry-client that referenced this issue Jul 23, 2012

@isaacs isaacs Properly handle user-switching in adduser 5badc2f

@isaacs isaacs closed this Jul 23, 2012

Owner

isaacs commented Jul 23, 2012

Fixed in npm. It'll be in the next release, included with node 0.8.4 (tomorrow-ish.)

Found a bug in the npm-registry-client fix...noted on the commit.

With latest adduser.js from npm-registry-client, I still get the same login error result, though the contents of .npmrc look very odd after each login:

**** cleared _auth, _token, etc. from .npmrc

[tmp]$ npm login
Username: wsjbuilder
Password:
Email: (com.dj.tesla@gmail.com)
npm http PUT http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
npm http 409 http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
npm http GET http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
npm http 200 http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
npm http PUT http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder/-rev/7-6723cb4a4ebc330f9e94c0ffb50f37cf
npm http 201 http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder/-rev/7-6723cb4a4ebc330f9e94c0ffb50f37cf

[tmp]$ more ~/.npmrc
registry = http://registry.npm.wsjfdev.dowjones.net/
unsafe-perm = true
email = com.dj.tesla@gmail.com
_auth = xxxx

[tmp]$ npm login
Username: (wsjbuilder)
Email: (com.dj.tesla@gmail.com)
npm http PUT http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
npm http 409 http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
npm http GET http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
npm http 200 http://registry.npm.wsjfdev.dowjones.net/-/user/org.couchdb.user:wsjbuilder
npm ERR! Error: login error
npm ERR! at RegClient. (/usr/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:81:22)
npm ERR! at CouchLogin. (/usr/lib/node_modules/npm/node_modules/couch-login/couch-login.js:104:12)
npm ERR! at Request.init.self.callback (/usr/lib/node_modules/npm/node_modules/request/main.js:120:22)

[tmp]$ more ~/.npmrc
registry = http://registry.npm.wsjfdev.dowjones.net/
unsafe-perm = true
email = com.dj.tesla@gmail.com
_auth = xxx
_token = null
hSession":"xxx","version":"1","path":"/","httponly":true}

Owner

isaacs commented Jul 24, 2012

Reproduced and resolved.

By the way, that _auth is just base64 encoded. It's not encrypted in any way. There's a reason npm won't print it out. I see that it's just some random characters, so hopefully it's some kind of throwaway password, because you ought to throw it away now. Just to be on the slightly safer side, I edited it out of your comment.

thanks for the info on the _auth value. Assuming the fix was only in npm-registry-client/lib/adduser.js, I applied the fix to my global npm and I still see the "broken" values in .npmrc:

_token = null
hSession":"XXXXXXXXX","version":"1","path":"/","httponly":true}

edit: I see this on one client, but not the other. After the changes below, the .npmrc file looks clean for all cases

The _token value is null, and the next line looks like it was partially overwritten when .npmrc was updated.

I still get the 'Error: login error' when running login or publish after a successful login.

I think I found the root cause...all of the debugging up to this point showed that the request was coming back as 200 from the _session request, but it looks like the couch_login#valid function is returning false due to a lack of expires value:

function valid (token) {
  var d = token && token.expires
  return token && token.expires > Date.now()
}

token.expires -> undefined, not greater than Date.now()

request.js then gets a "false" from couch.valid(couch.token), and immediately creates an Error object with 'login error' and processing stops.

Is this expires header supposed to come from the registry couchapp? It looks like token.expires is always missing and would fail the valid() test.

I can confirm that ignoring missing token.expires allows a publish to succeed:

From the unused var d in the original code it seems like the intent was to handle the expires value in a special way, but the code doesn't use it. I'm assuming that if the server does not return an expires value with the session response, that we can assume the token value is valid.

Updated code snippet from couch-login.js

function valid (token) {
  var d = token && token.expires
  return token && (!token.expires || token.expires > Date.now())
}

It seems to come back to npmjs.org. The response from the registry doesn't contain expires nor max-age response headers, so the token doesn't get an expires value:

[dj111091@sbkgtspasd01 tmp]$ curl -i -X POST http://localhost:5984/_session -H "cookie: AuthSession=d3NqYnVpbGQ6XXXXXXXXXXXXXQR729LGw" -H "content-type: application/json" -H "accept: application/json" --data-binary @sessionTest.body
HTTP/1.1 200 OK
Set-Cookie: AuthSession=d3NqYnVpbGQ6XXXXXXXXXXXXXXXXXXbPURsVI3g; Version=1; Path=/; HttpOnly
Server: CouchDB/1.1.1 (Erlang OTP/R14B03)
Date: Tue, 24 Jul 2012 14:38:15 GMT
Content-Type: application/json
Content-Length: 43
Cache-Control: must-revalidate

{"ok":true,"name":null,"roles":["_admin"]}

sessionTest.body
{"name":"wsjbuilder","password":"XXXXXXXX"}

Either the client can ignore missing cookie/expires values and response/max-age, or the server code needs to always set one of those.

Owner

isaacs commented Jul 24, 2012

Ah, ok. The issue is in couchdb's settings. In the couch_httpd_auth section, there's a field called timeout that determines whether or not the cookies have an expires or max-age value.

Updated couch-login to handle that not being set. The latest stuff on github should work now.

Works for me, thanks!

@motin motin referenced this issue in npm/npm Nov 19, 2012

Closed

npm publish fail #2651

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment