Bug 461226 - Error opening change in editor - Unable to login
Summary: Error opening change in editor - Unable to login
Status: RESOLVED FIXED
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Mylyn (show other bugs)
Version: 2.5   Edit
Hardware: PC Mac OS X
: P2 major (vote)
Target Milestone: 2.7   Edit
Assignee: Nicholas Folk CLA
QA Contact:
URL:
Whiteboard:
Keywords: contributed, greatfix, helpwanted
Depends on:
Blocks:
 
Reported: 2015-03-02 12:55 EST by Steve Elsemore CLA
Modified: 2015-04-23 19:27 EDT (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Steve Elsemore CLA 2015-03-02 12:55:41 EST
Trying to open a change from a Gerrit 2.9 instance, I inconsistently get an error dialog saying "Unable to login to <server>.  Please validate credentials via Task Repositories view".  But the repository credentials are correct and validate fine.  See error log entry at bottom of message.

I wonder if the problem is with this bit in GerritClient29:

String querysubmit = "/changes/" + Integer.toString(reviewId) + "/revisions/current/test.submit_rule?filters=SKIP"; //$NON-NLS-1$//$NON-NLS-2$
List<SubmitRecord> submitRecord = currentSubmitRecord(querysubmit, monitor);

Because the currentSubmitRecord method executes a POST request, perhaps the querysubmit parameter should use the authentication URI (with the "/a/" prefix)?

Just guessing.

org.eclipse.core.runtime.CoreException: Unable to login to <server>. Please validate credentials via Task Repositories view.
	at org.eclipse.mylyn.internal.gerrit.core.GerritConnector.toCoreException(GerritConnector.java:408)
	at org.eclipse.mylyn.internal.gerrit.core.remote.GerritReviewRemoteFactory.pull(GerritReviewRemoteFactory.java:137)
	at org.eclipse.mylyn.internal.gerrit.core.remote.GerritReviewRemoteFactory.pull(GerritReviewRemoteFactory.java:1)
	at org.eclipse.mylyn.reviews.core.spi.remote.emf.RemoteEmfConsumer.pull(RemoteEmfConsumer.java:128)
	at org.eclipse.mylyn.reviews.core.spi.remote.JobRemoteService$1.run(JobRemoteService.java:61)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:53)
Comment 1 Steve Elsemore CLA 2015-03-02 13:03:20 EST
I should add that in debug I see that the response body coming back from the post request is:

Invalid authentication method. In order to authenticate, prefix the REST endpoint URL with /a/ (e.g. http://example.com/a/projects/).
Comment 2 Sam Davis CLA 2015-03-02 13:53:35 EST
Thanks for the hint. I wonder when we should be using the /a/ prefix and when we shouldn't.
Comment 3 Dariusz Luksza CLA 2015-03-06 11:41:39 EST
According to this post[1] it is good idea to prefix all REST calls with '/a/' and always send user credentials. Unless you already have Gerrit's session id and x-gerrit-auth token, then you can drop '/a/' and provide both tokens (session as a cookie and x-gerrit-auth in request header).

[1] https://groups.google.com/d/msg/repo-discuss/KsPPUpFIz18/q2huCHazv0oJ
Comment 4 Sam Davis CLA 2015-03-06 16:10:39 EST
Thanks. It sounds like we should consider using digest authentication and dropping the xsrf stuff.
Comment 5 Steve Elsemore CLA 2015-03-09 15:31:53 EDT
Some additional information.  I've been struggling to debug this since it happens intermittently (and rarely when I'm debugging).  I've seen that the problem happens when, in GerritHttpClient, somehow obtainedXsrfKey = true, but xsrfKey = null.  Once this happens, the X-Gerrit-Auth header will never be set correctly.  It doesn't look like this should ever happen, but maybe a synchronize issue?  Also, when the header is not set, all the GETs that happen while getting the change still work fine, prior to the failure on the POST in GerritClient29.currentSubmitRecord.  Just throwing this out there in case it inspires anybody who understands all this better than I do!
Comment 6 Steve Elsemore CLA 2015-03-10 14:11:37 EDT
Could the problem be in GerritHttpClient.updateXsrfKey:

String xGerritAuth = processor.getXGerritAuth();
if (xGerritAuth != null) {
    setXsrfKey(xGerritAuth);
} else {
    setXsrfKey(processor.getXsrfKey());
}

Should there be a null check on processor.getXsrfKey() prior to calling setXsrfKey?  If null gets passed to setXsrfKey, it will still set obtainedXrfKey to true, and then it will never again try to get a key.

This would happen any time the response contains neither hostpagedata.xsrfToken nor hostpagedata.xGerritAuth.
Comment 7 Steve Elsemore CLA 2015-03-12 14:02:13 EDT
I hope I haven't cried wolf so many times that nobody is listening to me ;-)

I think that the problem might have to do with the cached GerritAccount cookie having expired.  This will result in GerritHttpClient.updateXsrfKey setting xsrfKey to null.  A 403 on a subsequent api call (X-Gerrit-Auth header null) will trigger re-authentication, which will get a new GerritAccount cookie but does not try again to obtain an xsrfKey.  It seems this might be fixed in GerritHttpClient:

if (code == HttpURLConnection.HTTP_UNAUTHORIZED || code == HttpURLConnection.HTTP_FORBIDDEN) {
   // login or re-authenticate due to an expired session
   authenticate(openIdProvider, monitor);

   updateXsrfKey(monitor);  // Add this line!

Note that this problem doesn't manifest itself for a lot of GET calls, but once you try to open the change editor with X-Gerrit-Auth:null, you will get an error on this one:

POST https://<host>/gerrit/changes/203/revisions/current/test.submit_rule?filters=SKIP

(for example)

Thanks
Comment 8 Nicholas Folk CLA 2015-04-17 17:05:01 EDT
Don't worry Steve, your comments were not going unnoticed. A review has been pushed with a fix similar to the code in your last comment.

Review
https://git.eclipse.org/r/#/c/46008/

Instead of updating the xsrfKey directly, we can set the obtainedXsrfKey boolean to be false. This way, the same effect takes place (we'll update the key) on the next attempt.
Comment 9 Steve Elsemore CLA 2015-04-17 17:10:55 EDT
Great, thanks!
Comment 10 Sam Davis CLA 2015-04-17 18:07:23 EDT
I've merged the change so we can see if it really solves the problem. We should still consider using digest authentication and/or improving the test coverage of this.
Comment 11 Tomasz Zarna CLA 2015-04-17 19:53:14 EDT
(In reply to Nicholas Folk from comment #8)
> Review https://git.eclipse.org/r/#/c/46008/

That worked for me, just updated to 2.6.0.N20150417-2059 and the problem is gone.
Comment 12 Sam Davis CLA 2015-04-20 12:54:08 EDT
The fix also seems to work for me.
Comment 13 Sam Davis CLA 2015-04-23 19:27:40 EDT
Thanks Nick for the fix! I've opened bug 465349 to follow up.