-
Notifications
You must be signed in to change notification settings - Fork 88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix redirect loop when oic credentials have expired but jenkins session is still valid #357
Fix redirect loop when oic credentials have expired but jenkins session is still valid #357
Conversation
@@ -1420,7 +1419,8 @@ public boolean handleTokenExpiration(HttpServletRequest httpRequest, HttpServlet | |||
private void redirectOrRejectRequest(HttpServletRequest req, HttpServletResponse res) | |||
throws IOException, ServletException { | |||
if (req.getSession(false) != null || Strings.isNullOrEmpty(req.getHeader("Authorization"))) { | |||
WebApp.get(Jenkins.get().servletContext).getSomeStapler().invoke(req, res, Jenkins.get(), getLoginUrl()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@krezovic i was not familiar with this - was it essentially meant to perform a redirect?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mikecirioli I believe I was addressing feedback from the review where it was noted that it would be user-friendly to redirect user back to login when the token expires. Original implementation contained 401 only.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #357 +/- ##
============================================
- Coverage 72.02% 71.44% -0.58%
+ Complexity 234 232 -2
============================================
Files 11 11
Lines 990 991 +1
Branches 142 142
============================================
- Hits 713 708 -5
- Misses 199 205 +6
Partials 78 78 ☔ View full report in Codecov by Sentry. |
webClient.assertFails(jenkins.getSecurityRealm().getLoginUrl(), 302); | ||
|
||
// use an actual HttpClient to make checking redirects easier | ||
HttpResponse<String> rsp = getPageWithGet("/manage"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is JenkinsRule#createWebClient
not enough for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not the way the test was originally written - AFAICT JenkinsRule.WebClient
follows http redirects, which was causing the test to fail. The test was passing before because JenkinsRule.WebClient
was erroring out due to the redirect loop. I used the HttpClient
because you can tell it not to follow redirects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@amuniz just to be certain, i took a look at the original test and confirmed that it does indeed suffer from the same redirect loop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@michael-doubez i realize that i did not add a label to this PR before it was merged, and i don't have permissions to trigger a release - is that something you can do? |
@mikecirioli my mistake - it didn't check |
@@ -48,7 +48,7 @@ public OicCredentials( | |||
|
|||
if (expiresInSeconds != null && expiresInSeconds > 0) { | |||
long allowedClockSkewFixed = Util.fixNull(allowedClockSkewSeconds, 60L); | |||
this.expiresAtMillis = currentTimestamp + (expiresInSeconds - allowedClockSkewFixed) * 1000; | |||
this.expiresAtMillis = (currentTimestamp + expiresInSeconds + allowedClockSkewFixed) * 1000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change seems to be incorrect. currentTimestamp
is already in millis. Therefore, this line should be this.expiresAtMillis = currentTimestamp + (expiresInSeconds + allowedClockSkewFixed) * 1000
.
to reproduce:
Although the proposed PR fixes the issue AFAICT, I am not 100% confident it is the correct fix. This issue first appears in release 4.297.vcddb_d8a_e4694, but i have not been able to identify exactly what i believe changed to cause this behavior. My theory is that because the jenkins web session is still valid, it allows the request, which is then flagged as invalid because the OIC credentials have expired, kicking the whole loop off again. Hopefully you can confirm or deny this @krezovic
I also believe that the clock skew was mistakenly being subtracted from the credentials "expires in X seconds" calculation - my understanding was the clock skew should add an additional "buffer" to the lifetime of the credentials in order to accommodate slight variances in different clocks.
Testing done
Lots of manual testing....
I've also fixed 2 tests that i believe cover the changes made in this PR:
testRefreshTokenAndTokenExpiration_withoutRefreshToken()
The test was originally using
JenkinsRule.WebClient
to check for a302
respoonse when theOicCredentials
are expired. NormallyWebClient
would follow redirects, and the test was only passing with the expectedBlocked - 302
due to the redirect loop that was occurring. Fixing that caused this test to fail, so i've replaced that bit of test code with a javaHttpClient
set to not follow redirects.the expire helper method was using the wrong number of
ms
to force the credentials to be expired. This apparently worked previously because the clock skew was actually being subtracted from the credential lifetime (instead of augmenting it). Since all we care about is ensuring the credentials appear expired I simply set the creation instant to1
(ie. the first millisecond of time ever).Submitter checklist