Skip to content

NPE in HttpSessionSecurityContextRepository.isTransientAuthentication #8947

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

Closed
windmueller opened this issue Aug 6, 2020 · 7 comments · Fixed by #9813
Closed

NPE in HttpSessionSecurityContextRepository.isTransientAuthentication #8947

windmueller opened this issue Aug 6, 2020 · 7 comments · Fixed by #9813
Assignees
Labels
in: web An issue in web modules (web, webmvc) type: bug A general bug

Comments

@windmueller
Copy link

Describe the bug
On our systems we see a NullPointerException for cached static resources with spring-security-web-5.3.3:

java.lang.NullPointerException: null
	at org.springframework.security.web.context.HttpSessionSecurityContextRepository.isTransientAuthentication(HttpSessionSecurityContextRepository.java:444) ~[spring-security-web-5.3.3.RELEASE.jar:5.3.3.RELEASE]
	at org.springframework.security.web.context.HttpSessionSecurityContextRepository.access$300(HttpSessionSecurityContextRepository.java:82) ~[spring-security-web-5.3.3.RELEASE.jar:5.3.3.RELEASE]
	at org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper.createNewSessionIfAllowed(HttpSessionSecurityContextRepository.java:389) ~[spring-security-web-5.3.3.RELEASE.jar:5.3.3.RELEASE]
	at org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper.saveContext(HttpSessionSecurityContextRepository.java:363) ~[spring-security-web-5.3.3.RELEASE.jar:5.3.3.RELEASE]
	at org.springframework.security.web.context.SaveContextOnUpdateOrErrorResponseWrapper.onResponseCommitted(SaveContextOnUpdateOrErrorResponseWrapper.java:85) ~[spring-security-web-5.3.3.RELEASE.jar:5.3.3.RELEASE]
	at org.springframework.security.web.util.OnCommittedResponseWrapper.doOnResponseCommitted(OnCommittedResponseWrapper.java:252) ~[spring-security-web-5.3.3.RELEASE.jar:5.3.3.RELEASE]
	at org.springframework.security.web.util.OnCommittedResponseWrapper.checkContentLength(OnCommittedResponseWrapper.java:242) ~[spring-security-web-5.3.3.RELEASE.jar:5.3.3.RELEASE]
	at org.springframework.security.web.util.OnCommittedResponseWrapper.access$200(OnCommittedResponseWrapper.java:34) ~[spring-security-web-5.3.3.RELEASE.jar:5.3.3.RELEASE]
	at org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.write(OnCommittedResponseWrapper.java:644) ~[spring-security-web-5.3.3.RELEASE.jar:5.3.3.RELEASE]
	at org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.write(OnCommittedResponseWrapper.java:645) ~[spring-security-web-5.3.3.RELEASE.jar:5.3.3.RELEASE]
	at org.springframework.util.FastByteArrayOutputStream.writeTo(FastByteArrayOutputStream.java:249) ~[spring-core-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.util.ContentCachingResponseWrapper.copyBodyToResponse(ContentCachingResponseWrapper.java:215) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.util.ContentCachingResponseWrapper.copyBodyToResponse(ContentCachingResponseWrapper.java:199) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.filter.ShallowEtagHeaderFilter.updateResponse(ShallowEtagHeaderFilter.java:132) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.filter.ShallowEtagHeaderFilter.doFilterInternal(ShallowEtagHeaderFilter.java:109) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618) ~[jetty-servlet-9.4.28.v20200408.jar:9.4.28.v20200408]
	at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doFilter(AbstractPreAuthenticatedProcessingFilter.java:124) ~[spring-security-web-5.3.3.RELEASE.jar:5.3.3.RELEASE]
	[...]

This seems to happen because the authentication returned by SecurityContextHolder.getContext() is null.

To Reproduce
Unknown, because the error does not happen often.

Expected behavior
I am not sure if the authentication may be null at all, but instead of a NullPointerException resulting in an "Internal Server Error" I would expect a plain "Unauthorized".

@windmueller windmueller added status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Aug 6, 2020
@jzheaux
Copy link
Contributor

jzheaux commented May 15, 2021

@stovocor, I agree that a NullPointerException in this case is not desirable.

Since isTransientAuthentication cannot determine whether or not the authentication is transient in this case, I think it's reasonable to have it return false.

@jzheaux jzheaux self-assigned this May 15, 2021
@jzheaux jzheaux added in: web An issue in web modules (web, webmvc) and removed status: waiting-for-triage An issue we've not yet triaged labels May 15, 2021
@marcusdacoregio
Copy link
Contributor

marcusdacoregio commented May 18, 2021

@stovocor, thank you for pointing this out.

I was looking into the code and the authentication is checked for null before the method is called:

if (authentication == null || trustResolver.isAnonymous(authentication)) { // authentication is being checked for null
	if (logger.isDebugEnabled()) {
		logger.debug("SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.");
	}

	if (httpSession != null && authBeforeExecution != null) {
		// SEC-1587 A non-anonymous context may still be in the session
		// SEC-1735 remove if the contextBeforeExecution was not anonymous
		httpSession.removeAttribute(springSecurityContextKey);
	}
	return;
}

if (httpSession == null) {
	httpSession = createNewSessionIfAllowed(context); // the method that is throwing NPE call
}

So in the scenario where the authentication is null it shouldreturn from this method and not reach the createNewSessionIfAllowed.

It seems to be a concurrency issue where the authentication is getting removed after the authentication == null test and before the createNewSessionIfAllowed method call.

To narrow the problem down, could you provide a sample that replicates the behavior?

@marcusdacoregio marcusdacoregio added the status: waiting-for-feedback We need additional information before we can continue label May 18, 2021
@windmueller
Copy link
Author

To narrow the problem down, could you provide a sample that replicates the behavior?

I am very sorry, but as I mentioned in the original bugreport, I am not able to reproduce this problem and it occurs rarely.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels May 19, 2021
@marcusdacoregio
Copy link
Contributor

@stovocor I see, thanks for the feedback. We are planning to work on a more general solution that would address more scenarios. @jzheaux do we have already an issue open for that?

@jzheaux
Copy link
Contributor

jzheaux commented May 21, 2021

Yes, #9634

@marcusdacoregio marcusdacoregio removed the status: backported An issue that has been backported to maintenance branches label May 25, 2021
@marcusdacoregio
Copy link
Contributor

Hi @stovocor, we have now a proposed PR #9813 to address this problem.

marcusdacoregio added a commit to marcusdacoregio/spring-security that referenced this issue May 26, 2021
Ensure that isTransientAuthentication reuses the same authentication object from saveContext

Closes spring-projectsgh-8947
jzheaux pushed a commit that referenced this issue May 26, 2021
Ensure that isTransientAuthentication reuses the same authentication object from saveContext

Closes gh-8947
marcusdacoregio added a commit that referenced this issue May 26, 2021
Ensure that isTransientAuthentication reuses the same authentication object from saveContext

Closes gh-8947
marcusdacoregio added a commit that referenced this issue May 26, 2021
Ensure that isTransientAuthentication reuses the same authentication object from saveContext

Closes gh-8947
marcusdacoregio added a commit that referenced this issue May 26, 2021
Ensure that isTransientAuthentication reuses the same authentication object from saveContext

Closes gh-8947
@marcusdacoregio
Copy link
Contributor

Hello @stovocor, the PR is now merged and is aimed at the milestone 5.6.0-M1. Thanks for the report and feel free to discuss here if you want anything else.

akohli96 pushed a commit to akohli96/spring-security that referenced this issue Aug 25, 2021
Ensure that isTransientAuthentication reuses the same authentication object from saveContext

Closes spring-projectsgh-8947
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web An issue in web modules (web, webmvc) type: bug A general bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants