Announcement Announcement Module
Collapse
No announcement yet.
A valid SecureContext was not provided in the RequestContext Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • A valid SecureContext was not provided in the RequestContext

    Using 0.7.0 on Tomcat 5.0.28, and I get the dreaded "net.sf.acegisecurity.AuthenticationCredentialsNot FoundException: A valid SecureContext was not provided in the RequestContext" exception...

    I've Googled around, and found some mail and forum threads about this specific error message. Using that information, and the Java Lobby article, I can't seem to make my application work anyhow...

    On to the good stuff. Basically, I followed the steps outlined in the Suggested Steps document. I copied applicationContext-acegi-security.xml, and changed the file to use an InMemoryDaoImpl. I copied the RoleVoter declaration from applicationContext-common-authorisation.xml. Finally, I copied the filters section from web.xml.

    When I deploy, on Tomcat 5.0.28, my log shows the following, after attempting authentication:
    Code:
    2005-01-27 03:45:32,328 [DEBUG] web.SecurityEnforcementFilter - Authentication failed - adding target URL to Session: http://localhost:8080/cn/careernudge/listContacts.html
    net.sf.acegisecurity.AuthenticationCredentialsNotFoundException: A valid SecureContext was not provided in the RequestContext
    	at net.sf.acegisecurity.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:505)
    	at net.sf.acegisecurity.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:381)
    	at net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:67)
    ...
    2005-01-27 03:45:32,359 [INFO ] view.InternalResourceViewResolver - Cached view 'login'
    2005-01-27 03:45:34,984 [DEBUG] web.SecurityEnforcementFilter - Chain processed normally
    2005-01-27 03:45:40,281 [DEBUG] cache.EhCacheBasedUserCache - Cache hit: false; username: fbos
    2005-01-27 03:45:40,296 [WARN ] event.LoggerListener - Authentication failed due to incorrect password for user: fbos; details: 127.0.0.1
    2005-01-27 03:45:40,328 [INFO ] view.InternalResourceViewResolver - Cached view 'loginFailed'
    2005-01-27 03:45:41,156 [DEBUG] web.SecurityEnforcementFilter - Chain processed normally
    My web.xml file looks like this:
    Code:
    <web-app version="2.4"
             xmlns="http&#58;//java.sun.com/xml/ns/j2ee"
             xmlns&#58;xsi="http&#58;//www.w3.org/2001/XMLSchema-instance"
             xsi&#58;schemaLocation="http&#58;//java.sun.com/xml/ns/j2ee http&#58;//java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >
    ...
        <!-- Remove the comments from the following <filter-mapping> if you'd
        like to ensure secure URLs are only available over HTTPS -->
        <!--
        <filter-mapping>
            <filter-name>Acegi Channel Processing Filter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        -->
    
        <filter-mapping>
            <filter-name>Acegi Authentication Processing Filter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <filter-mapping>
            <filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <filter-mapping>
            <filter-name>Acegi Security System for Spring HttpSession Integration Filter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <filter-mapping>
            <filter-name>Acegi HTTP Request Security Filter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    ...
    </web-app>
    My InMemoryDaoImpl declaration looks like this:
    Code:
    <bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl">
        <property name="userMap">
            <value>
                fbos=abc123,ROLE_USER,ROLE_SUPERVISOR
            </value>
        </property>
    </bean>
    What am I doing wrong ? According to Ben, on http://www.mail-archive.com/acegisec.../msg00313.html (see the next to last paragraph):
    in most cases the "A valid SecureContext was not provided in the RequestContext" indicates the net.sf.acegisecurity.ui package isn't being called or not being called at the appropriate time. Most of the time people use the AutoIntegrationFilter. Just double-check it is in your web.xml, as it is what is responsible for setting up the ContextHolder in a web container deployed application.
    I understand AutoIntegrationFilter was deprecated in favor of the new AuthenticationProcessingFilter, so I can't really verify that the auto integration filter is there...

    Anyway, any help would be gladly appreciated.

    Thanks !
    François

  • #2
    First up, AutoIntegrationFilter has been replaced by HttpSessionIntegrationFilter. Although your web.xml configuration looks fine (HttpSessionIntegrationFilter is defined).

    If the logging provided is after you have already logged in, an interesting entry is:

    cache.EhCacheBasedUserCache - Cache hit: false; username: fbos
    This suggests to me the initial login operation didn't happen. Otherwise fbos should be in the cache.

    Would you please try again, this time including the logging that took place from the original request, when you logged in, and when the access denied message occurs?

    Comment


    • #3
      Hello Ben,

      Here is a more complete log. I first restarted the server, then visited index.html. On that page, I have a form for logon. I logged on, and I was sent back to my failed login page.

      The log is separated in three parts. First, the initial application startup, and "index.html" processing:
      Code:
      2005-01-28 16&#58;01&#58;59,750 &#91;DEBUG&#93; basicauth.BasicProcessingFilter - Authorization header&#58; null
      2005-01-28 16&#58;01&#58;59,781 &#91;DEBUG&#93; ui.AbstractIntegrationFilter - Authentication not added to ContextHolder &#40;could not extract an authentication object from the container which is an instance of Authentication&#41;
      2005-01-28 16&#58;01&#58;59,812 &#91;DEBUG&#93; web.RegExpBasedFilterInvocationDefinitionMap - Converted URL to lowercase, from&#58; '/index.html'; to&#58; '/index.html'
      2005-01-28 16&#58;01&#58;59,812 &#91;DEBUG&#93; web.RegExpBasedFilterInvocationDefinitionMap - Candidate is&#58; '/index.html'; pattern is \A/careernudge/admin/.*\Z; matched=false
      2005-01-28 16&#58;01&#58;59,812 &#91;DEBUG&#93; web.RegExpBasedFilterInvocationDefinitionMap - Candidate is&#58; '/index.html'; pattern is \A/careernudge/.*\Z; matched=false
      2005-01-28 16&#58;01&#58;59,812 &#91;DEBUG&#93; intercept.AbstractSecurityInterceptor - Public object - authentication not attempted
      2005-01-28 16&#58;01&#58;59,890 &#91;DEBUG&#93; servlet.DispatcherServlet - DispatcherServlet with name 'careernudge' received request for &#91;/cn/index.html&#93;
      2005-01-28 16&#58;01&#58;59,890 &#91;DEBUG&#93; servlet.DispatcherServlet - Testing handler map &#91;org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping@1642bd6&#93; in DispatcherServlet with name 'careernudge'
      2005-01-28 16&#58;01&#58;59,890 &#91;DEBUG&#93; servlet.DispatcherServlet - Testing handler adapter &#91;org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter@179f36b&#93;
      2005-01-28 16&#58;01&#58;59,921 &#91;DEBUG&#93; servlet.DispatcherServlet - Will render view in DispatcherServlet with name 'careernudge'
      2005-01-28 16&#58;01&#58;59,921 &#91;INFO &#93; view.InternalResourceViewResolver - Cached view 'index'
      2005-01-28 16&#58;02&#58;03,796 &#91;DEBUG&#93; servlet.DispatcherServlet - Successfully completed request
      2005-01-28 16&#58;02&#58;05,671 &#91;DEBUG&#93; web.SecurityEnforcementFilter - Chain processed normally
      2005-01-28 16&#58;02&#58;05,671 &#91;DEBUG&#93; ui.AbstractIntegrationFilter - ContextHolder does not contain any authentication information
      Second, my logon attempt:
      Code:
      2005-01-28 16&#58;02&#58;10,359 &#91;DEBUG&#93; ui.AbstractProcessingFilter - Request is to process authentication
      2005-01-28 16&#58;02&#58;10,359 &#91;DEBUG&#93; providers.ProviderManager - Authentication attempt using net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider
      2005-01-28 16&#58;02&#58;10,359 &#91;DEBUG&#93; cache.EhCacheBasedUserCache - Cache hit&#58; false; username&#58; fbos
      2005-01-28 16&#58;02&#58;10,390 &#91;WARN &#93; event.LoggerListener - Authentication failed due to incorrect password for user&#58; fbos; details&#58; 127.0.0.1
      2005-01-28 16&#58;02&#58;10,390 &#91;DEBUG&#93; ui.AbstractProcessingFilter - Authentication request failed&#58; net.sf.acegisecurity.BadCredentialsException&#58; Bad credentials presented
      2005-01-28 16&#58;02&#58;10,421 &#91;DEBUG&#93; basicauth.BasicProcessingFilter - Authorization header&#58; null
      2005-01-28 16&#58;02&#58;10,421 &#91;DEBUG&#93; ui.AbstractIntegrationFilter - Authentication not added to ContextHolder &#40;could not extract an authentication object from the container which is an instance of Authentication&#41;
      Then, the redirect to loginFailed.html:
      Code:
      2005-01-28 16&#58;02&#58;10,421 &#91;DEBUG&#93; web.RegExpBasedFilterInvocationDefinitionMap - Converted URL to lowercase, from&#58; '/loginfailed.html'; to&#58; '/loginfailed.html'
      2005-01-28 16&#58;02&#58;10,421 &#91;DEBUG&#93; web.RegExpBasedFilterInvocationDefinitionMap - Candidate is&#58; '/loginfailed.html'; pattern is \A/careernudge/admin/.*\Z; matched=false
      2005-01-28 16&#58;02&#58;10,421 &#91;DEBUG&#93; web.RegExpBasedFilterInvocationDefinitionMap - Candidate is&#58; '/loginfailed.html'; pattern is \A/careernudge/.*\Z; matched=false
      2005-01-28 16&#58;02&#58;10,421 &#91;DEBUG&#93; intercept.AbstractSecurityInterceptor - Public object - authentication not attempted
      2005-01-28 16&#58;02&#58;10,421 &#91;DEBUG&#93; servlet.DispatcherServlet - DispatcherServlet with name 'careernudge' received request for &#91;/cn/loginFailed.html&#93;
      2005-01-28 16&#58;02&#58;10,421 &#91;DEBUG&#93; servlet.DispatcherServlet - Testing handler map &#91;org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping@1642bd6&#93; in DispatcherServlet with name 'careernudge'
      2005-01-28 16&#58;02&#58;10,421 &#91;DEBUG&#93; servlet.DispatcherServlet - Testing handler adapter &#91;org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter@179f36b&#93;
      2005-01-28 16&#58;02&#58;10,421 &#91;DEBUG&#93; servlet.DispatcherServlet - Will render view in DispatcherServlet with name 'careernudge'
      2005-01-28 16&#58;02&#58;10,421 &#91;INFO &#93; view.InternalResourceViewResolver - Cached view 'loginFailed'
      2005-01-28 16&#58;02&#58;11,718 &#91;DEBUG&#93; servlet.DispatcherServlet - Successfully completed request
      2005-01-28 16&#58;02&#58;11,750 &#91;DEBUG&#93; web.SecurityEnforcementFilter - Chain processed normally
      2005-01-28 16&#58;02&#58;11,750 &#91;DEBUG&#93; ui.AbstractIntegrationFilter - ContextHolder does not contain any authentication information
      My log4j.properties file contains the following:
      Code:
      log4j.logger.net.sf.acegisecurity = DEBUG
      log4j.logger.org.springframework.web.servlet.DispatcherServlet = DEBUG
      Any help greatly appreciated

      Bye !
      François

      Comment


      • #4
        It seems to be behaving exactly as it should if an incorrect password was presented. However, I'm guessing you're logging in as "fbos", password "abc123" as per your InMemoryDaoImpl.

        Could you post your DaoAuthenticationProvider XML, so I can just double-check you've modified it to use InMemoryDaoImpl? Also, can you try logging in with the acegilogin.jsp included with the Contacts sample, just to rule out incorrect presentation of the username and password form inputs?

        If neither of these work, please edit DaoAuthenticationProvider and add extra logging. You need to see what it is passing to the AuthenticationDao, and what AuthenticationDao is returning.

        Comment


        • #5
          Here is my daoAuthenticationProvider. As I previously said, this is a copy of what was in CVS when I copied. Maybe I should have used the 0.7.0 tag ?

          Here's a copy of my applicationContext-acegi-security.xml
          Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
          
          <!--
          - Application context containing authentication, channel
          - security and web URI beans.
          -
          - Only used by "filter" artifact.
          -
          - $Id&#58; applicationContext-acegi-security.xml,v 1.2 2004/12/05 04&#58;37&#58;03 benalex Exp $
            -->
          
          <beans>
          
              <!-- ======================== AUTHENTICATION ======================= -->
          
              <bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
                  <property name="providers">
                      <list>
                          <ref local="daoAuthenticationProvider"/>
                      </list>
                  </property>
              </bean>
          
              <bean id="passwordEncoder" class="net.sf.acegisecurity.providers.encoding.Md5PasswordEncoder"/>
          
              <bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
                  <property name="authenticationDao">
                      <ref bean="inMemoryDaoImpl"/>
                  </property>
                  <property name="userCache">
                      <ref local="userCache"/>
                  </property>
                  <property name="passwordEncoder">
                      <ref local="passwordEncoder"/>
                  </property>
              </bean>
          
              <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
          
              <bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
                  <property name="cacheManager">
                      <ref local="cacheManager"/>
                  </property>
                  <property name="cacheName">
                      <value>userCache</value>
                  </property>
              </bean>
          
              <bean id="userCache" class="net.sf.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
                  <property name="cache">
                      <ref local="userCacheBackend"/>
                  </property>
              </bean>
          
              <!-- Automatically receives AuthenticationEvent messages from DaoAuthenticationProvider -->
              <bean id="loggerListener" class="net.sf.acegisecurity.providers.dao.event.LoggerListener"/>
          
              <bean id="basicProcessingFilter" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter">
                  <property name="authenticationManager">
                      <ref local="authenticationManager"/>
                  </property>
                  <property name="authenticationEntryPoint">
                      <ref local="basicProcessingFilterEntryPoint"/>
                  </property>
              </bean>
          
              <bean id="basicProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">
                  <property name="realmName">
                      <value>CareerNudge.com Realm</value>
                  </property>
              </bean>
          
              <bean id="httpSessionIntegrationFilter" class="net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter"/>
          
              <!-- ===================== HTTP CHANNEL REQUIREMENTS ==================== -->
          
              <!-- You will need to uncomment the "Acegi Channel Processing Filter"
              <filter-mapping> in web.xml for the following beans to be used -->
          
              <bean id="channelProcessingFilter" class="net.sf.acegisecurity.securechannel.ChannelProcessingFilter">
                  <property name="channelDecisionManager">
                      <ref local="channelDecisionManager"/>
                  </property>
                  <property name="filterInvocationDefinitionSource">
                      <value>
          			    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
          				\A/careernudge/.*\Z=REQUIRES_SECURE_CHANNEL
          				\A/login.html.*\Z=REQUIRES_SECURE_CHANNEL
          				\A/j_acegi_security_check.*\Z=REQUIRES_SECURE_CHANNEL
          				\A.*\Z=REQUIRES_INSECURE_CHANNEL
                      </value>
                  </property>
              </bean>
          
              <bean id="channelDecisionManager" class="net.sf.acegisecurity.securechannel.ChannelDecisionManagerImpl">
                  <property name="channelProcessors">
                      <list>
                          <ref local="secureChannelProcessor"/>
                          <ref local="insecureChannelProcessor"/>
                      </list>
                  </property>
              </bean>
          
              <bean id="secureChannelProcessor" class="net.sf.acegisecurity.securechannel.SecureChannelProcessor"/>
              <bean id="insecureChannelProcessor" class="net.sf.acegisecurity.securechannel.InsecureChannelProcessor"/>
          
              <!-- ===================== HTTP REQUEST SECURITY ==================== -->
          
              <bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
                  <property name="filterSecurityInterceptor">
                      <ref local="filterInvocationInterceptor"/>
                  </property>
                  <property name="authenticationEntryPoint">
                      <ref local="authenticationProcessingFilterEntryPoint"/>
                  </property>
              </bean>
          
              <bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
                  <property name="authenticationManager">
                      <ref bean="authenticationManager"/>
                  </property>
                  <property name="authenticationFailureUrl">
                      <value>/loginFailed.html</value>
                  </property>
                  <property name="defaultTargetUrl">
                      <value>/careernudge/listContacts.html</value>
                  </property>
                  <property name="filterProcessesUrl">
                      <value>/j_acegi_security_check</value>
                  </property>
              </bean>
          
              <bean id="authenticationProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
                  <property name="loginFormUrl">
                      <value>/login.html</value>
                  </property>
                  <property name="forceHttps">
                      <value>false</value>
                  </property>
              </bean>
          
              <bean id="httpRequestAccessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
                  <property name="allowIfAllAbstainDecisions">
                      <value>false</value>
                  </property>
                  <property name="decisionVoters">
                      <list>
                          <ref bean="roleVoter"/>
                      </list>
                  </property>
              </bean>
          
              <!-- Note the order that entries are placed against the objectDefinitionSource is critical.
              The FilterSecurityInterceptor will work from the top of the list down to the FIRST pattern that matches the request URL.
              Accordingly, you should place MOST SPECIFIC &#40;ie a/b/c/d.*&#41; expressions first, with LEAST SPECIFIC &#40;ie a/.*&#41; expressions last -->
              <bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor">
                  <property name="authenticationManager">
                      <ref bean="authenticationManager"/>
                  </property>
                  <property name="accessDecisionManager">
                      <ref local="httpRequestAccessDecisionManager"/>
                  </property>
                  <property name="objectDefinitionSource">
                      <value>
                          CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                          \A/careernudge/admin/.*\Z=ROLE_SUPERVISOR,ROLE_USER
                          \A/careernudge/.*\Z=ROLE_USER
                      </value>
                  </property>
              </bean>
          </beans>
          And here is my login.jspf:
          Code:
          <%@ include file="taglibs.jspf" %>
          <c&#58;url var="target" value="/j_acegi_security_check"/>
          <form method="post" action="$&#123;target&#125;">
              <div class="field">
                  <label for="j_username">Username&#58;</label>
                  <input length="12" maxlength="20" type="text"
                      id="j_username" name="j_username" />
              </div>
          
              <div class="field">
                  <label for="j_password">Password&#58;</label>
                  <input length="12" maxlength="20" type="password"
                      id="j_password" name="j_password" />
              </div>
          
              <input type="submit" value="Login !"/>
          </form>
          taglibs.jspf declares tag libraries, and sets the Content-Type to application/xhtml+xml.

          Now, when I tried testing with acegilogin.jsp, I got the same thing, with the following error message: " Your login attempt was not successful, try again. Reason: Bad credentials presented". The only change I had to make to acegilogin.jsp was to use the JSTL 2.0 URI instead of the 1.1.

          I deployed acegi-security-sample-contacts-filter on the same instance of Tomcat, and it ran perfectly (except for Log4J - see my other post).

          I am really baffled. I diffed my applicationContext-acegi-security.xml with the one in the sample filter DB, and the only changes are to switch to the InMemoryDao implementation, and some URL changes...

          I am using Firefox 1.0 RC1 on WinXP SP2 with Tomcat 5.0.28/Spring 1.1.1 and Acegi Security 0.7.0.

          I think I'll restart my config from scratch, and see if I can make it work this time around.

          Thanks !
          François

          Comment


          • #6
            Very odd. Can you confirm Acegi Channel Processing Filter is not being used, as I see you've configured it (although it was disabled in the earlier provided web.xml). Perhaps there's some odd interaction going on there?

            Comment


            • #7
              RESOLVED !

              Hehe, got it... The solution was right there in our faces all the time... Let's see the error message again:
              Code:
              2005-02-04 09&#58;56&#58;07,390 &#91;WARN &#93; event.LoggerListener           - Authentication failed due to incorrect password for user&#58; fbos; details&#58; 127.0.0.1
              Incorrect password, right ? What if we look at the config again:
              Code:
              <bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
                  <property name="authenticationDao">
                      <ref bean="inMemoryDaoImpl"/>
                  </property>
                  <property name="userCache">
                      <ref local="userCache"/>
                  </property>
                  <property name="passwordEncoder">
                      <ref local="passwordEncoder"/>
                  </property>
                  <property name="hideUserNotFoundExceptions">
                      <value>false</value>
                  </property>
              </bean>
              Let's now look at the javadocs for DaoAuthenticationProvider#setPasswordEncoder(Passw ordEncoder):
              Code:
                  /**
                   * Sets the PasswordEncoder instance to be used to encode and validate
                   * passwords. If not set, &#123;@link PlaintextPasswordEncoder&#125; will be used by
                   * default.
                   *
                   * @param passwordEncoder The passwordEncoder to use
                   */
              And now, for the final resolution:
              Code:
              <bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
                  <property name="authenticationDao">
                      <ref bean="inMemoryDaoImpl"/>
                  </property>
                  <property name="userCache">
                      <ref local="userCache"/>
                  </property>
              <!--
                  <property name="passwordEncoder">
                      <ref local="passwordEncoder"/>
                  </property>
              -->        
                  <property name="hideUserNotFoundExceptions">
                      <value>false</value>
                  </property>
              </bean>
              Don't forget I'm using an InMemoryDaoImpl, which doesn't encode passwords Phew !

              I rest my case, your Honor.

              Bye !
              François

              Comment


              • #8
                Well spotted.

                Comment

                Working...
                X