title: Why would I receive An Authentication object was not found in the SecurityContext when dot or period is included in the Path Variable?
body: <p>After reading numerous posts that were relevant to the following Spring error message.</p>
  
  <p>An Authentication object was not found in the SecurityContext</p>
  
  <p>I believe i maybe dealing with a bug in Spring... but I'd like to validate. I am using Spring Authentication to protect a Rest WebService. Here is the Request Mapping.</p>
  
  <pre><code>@RequestMapping(value = "/users/{login:.+}/", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
  @Timed
  @RolesAllowed(AuthoritiesConstants.ADMIN)
  ResponseEntity&lt;User&gt; getUser(@PathVariable String login) {
      log.debug("REST request to get User : {}", login);
      return userRepository.findOneByLogin(login)
              .map(user -&gt; new ResponseEntity&lt;&gt;(user, HttpStatus.OK))
              .orElse(new ResponseEntity&lt;&gt;(HttpStatus.NOT_FOUND));
  }
  </code></pre>
  
  <p>I have to support legacy users that are using emails for their logins. Which means that some of the users will contain dots in their names.  The issue of handling dots in a path variable seems to be solved numerous times over and it is recommended to simply change your standard path variable of {login} to {login:.+}.  </p>
  
  <p>Given the following two requests.  </p>
  
  <p>curl '<a href="http://localhost:8080/api/users/areifers/?cacheBuster=1448012530942" rel="nofollow">http://localhost:8080/api/users/areifers/?cacheBuster=1448012530942</a>' -H "AuthHeader : supersecrectstuff"</p>
  
  <p>The above request will work as designed and return the appropriate user information.</p>
  
  <p>curl '<a href="http://localhost:8080/api/users/arei.fers/?cacheBuster=1448012530942" rel="nofollow">http://localhost:8080/api/users/arei.fers/?cacheBuster=1448012530942</a>' -H "AuthHeader : supersecrectstuff"</p>
  
  <p>Adding a single dot or period into the path variable the request will no longer work. The Authentication Filter is not invoked which has made dedugging difficult. The response returned is as follows : </p>
  
  <pre><code>{"timestamp":1448014341997,"status":500,"error":"Internal Server Error","exception":"org.springframework.security.authentication.AuthenticationCredentialsNotFoundException","message":"An Authentication object was not found in the SecurityContext","path":"/api/users/areif.ers/"} 
  </code></pre>
  
  <p>Is there something I am missing? Why would two identical requests with the exact same headers be handled differently when only adding a period to the path? The only rationale I can come up with is that the {login:.+} is being overridden/ignored somewhere. Unfortunately I'm not sure what the best approach for diving into that possibility would be.  Any and all guidance appreciated. </p>
  
  <p><strong>UPDATE</strong>
  I tried experimenting with this more by changing the code to </p>
  
  <pre><code>@RequestMapping(value = "/users/{login:.+}/", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
  @Timed  
  ResponseEntity&lt;User&gt; getUser(@PathVariable String login) {
  
      if(!SecurityUtils.isUserInRole(AuthoritiesConstants.ADMIN)){
           return new ResponseEntity&lt;&gt;(HttpStatus.FORBIDDEN);
      }
  
      log.debug("REST request to get User : {}", login);          
      return userRepository.findOneByLogin(login)
              .map(user -&gt; new ResponseEntity&lt;&gt;(user, HttpStatus.OK))
              .orElse(new ResponseEntity&lt;&gt;(HttpStatus.NOT_FOUND));
  }
  </code></pre>
  
  <p>The Request Controller is properly invoked however as the original error would indicate given two requests when the only difference is the dot/period in the path variable the SecurityUtils Context is indeed Null when dot/period is included in the path variable.  This approach at least gave me a location to dump all the headers to inspect the break down of the request.  Here is a breakdown of the working request vs the null security context request</p>
  
  <p><strong>Working Request Debug</strong></p>
  
  <pre><code>[INFO] com.dcc.cpmadmin.web.rest.UserResource - url: http://localhost:8080/api/users/areifers/?cacheBuster=1448018046034
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - method:GET
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: host:localhost:8080
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: accept-encoding:gzip, deflate, sdch
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: accept-language:en-US,en;q=0.8
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: user-agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: accept:application/json, text/plain, */*
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: referer:http://localhost:8080/
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: x-auth-token:areifers:1448378026027:586ca2d1295c333e58ae1a249e8fc04e
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: cookie:_ga=GA1.1.1411040107.1423942263; NG_TRANSLATE_LANG_KEY=%22en%22; JSESSIONID=A4F3003CDCAF1CE26EFBF220739EEBAC
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: connection:keep-alive
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - Attribute: 'cacheBuster', Value: '1448018046034'
  [DEBUG] com.dcc.cpmadmin.web.rest.UserResource - REST request to get User : areifers
  Hibernate: select user0_.id as id1_31_, user0_.created_by as created_2_31_, user0_.c
  </code></pre>
  
  <p><strong>Secuity Context NULL Request Details</strong></p>
  
  <pre><code>[INFO] com.dcc.cpmadmin.web.rest.UserResource - url: http://localhost:8080/api/users/arei.fers/?cacheBuster=1448018046034
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - method:GET
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: host:localhost:8080
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: accept-encoding:gzip, deflate, sdch
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: accept-language:en-US,en;q=0.8
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: user-agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: accept:application/json, text/plain, */*
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: referer:http://localhost:8080/
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: x-auth-token:areifers:1448378026027:586ca2d1295c333e58ae1a249e8fc04e
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: cookie:_ga=GA1.1.1411040107.1423942263; NG_TRANSLATE_LANG_KEY=%22en%22; JSESSIONID=A4F3003CDCAF1CE26EFBF220739EEBAC
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - header: connection:keep-alive
  [INFO] com.dcc.cpmadmin.web.rest.UserResource - Attribute: 'cacheBuster', Value: '1448018046034'
  </code></pre>
  
  <p><strong>Summary</strong>
  Note that absolutely everything (that I can see in my frustrated state) in the requests is IDENTICAL including the x-auth-header and the JSessionID which are both relevant for authentication in this application. I'm becoming more convinced this is a bug, can anyone confirm?</p>
  
  <p>For Completeness Here is a complete error log</p>
  
  <pre><code>[ERROR] org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext] with root cause
  org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
      at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:339) ~[spring-security-core-3.2.7.RELEASE.jar:3.2.7.RELEASE]
      at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:198) ~[spring-security-core-3.2.7.RELEASE.jar:3.2.7.RELEASE]
      at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:60) ~[spring-security-core-3.2.7.RELEASE.jar:3.2.7.RELEASE]
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at com.ryantenney.metrics.spring.TimedMethodInterceptor.invoke(TimedMethodInterceptor.java:48) ~[metrics-spring-3.0.3.jar:na]
      at com.ryantenney.metrics.spring.TimedMethodInterceptor.invoke(TimedMethodInterceptor.java:34) ~[metrics-spring-3.0.3.jar:na]
      at com.ryantenney.metrics.spring.AbstractMetricMethodInterceptor.invoke(AbstractMetricMethodInterceptor.java:59) ~[metrics-spring-3.0.3.jar:na]
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) ~[spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at com.dcc.cpmadmin.web.rest.UserResource$$EnhancerBySpringCGLIB$$20b66579.getUser(&lt;generated&gt;) ~[spring-core-4.1.6.RELEASE.jar:na]
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_65]
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_65]
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_65]
      at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_65]
      at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776) ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705) ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:618) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) ~[spring-webmvc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:725) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at com.codahale.metrics.servlet.AbstractInstrumentedFilter.doFilter(AbstractInstrumentedFilter.java:104) ~[metrics-servlet-3.1.1.jar:3.1.1]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:291) ~[spring-boot-actuator-1.2.3.RELEASE.jar:1.2.3.RELEASE]
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:186) ~[spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
      at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) ~[spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:102) ~[spring-boot-actuator-1.2.3.RELEASE.jar:1.2.3.RELEASE]
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) ~[tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) [tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516) [tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086) [tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659) [tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223) [tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558) [tomcat-embed-core-8.0.20.jar:8.0.20]
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515) [tomcat-embed-core-8.0.20.jar:8.0.20]
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_65]
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_65]
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.20.jar:8.0.20]
      at java.lang.Thread.run(Thread.java:745) [na:1.8.0_65]
  </code></pre>
  
  <p><strong>UPDATE NUMBER TWO</strong>
  Per the recommendation to add a trailing slash I updated the code to the following removing the :.+ on the variable and adding a / the error log remained the same with more complicated user names. </p>
  
  <pre><code>@RequestMapping(value = "/users/{login}/", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
      @Timed  
      @RolesAllowed({ AuthoritiesConstants.ADMIN, AuthoritiesConstants.FACULTY })
      ResponseEntity&lt;User&gt; getUser(@PathVariable String login, HttpServletRequest req) {
  
          printRequestInfo(req);
  
          log.debug("REST request to get User : {}", login);          
          return userRepository.findOneByLogin(login)
                  .map(user -&gt; new ResponseEntity&lt;&gt;(user, HttpStatus.OK))
                  .orElse(new ResponseEntity&lt;&gt;(HttpStatus.NOT_FOUND));
      }
  </code></pre>
  
  <p>The error log remains the same.  </p>