Announcement Announcement Module
Collapse
No announcement yet.
accessing protected resource from Excel via WinHTTP Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • accessing protected resource from Excel via WinHTTP

    Hi,
    I am trying to post data from an Excel spreadsheet using VBA to my Web app which is secured using Acegi.

    I am using the SetCredentials method of the MS Http Services library

    http://msdn.microsoft.com/library/de...redentials.asp

    however this does not seem to be working. The response I get is the html data of the web apps login screen.

    I'm guessing Acegi's form based authentication is not compatible with the MS HttpServices SetCredentials method. (which is based on basic authentication?? not sure.. )

    Here is some sample VBA code to GET data from a secure url.

    (Note that you will need to adda reference to 'Microsoft WinHTTP Services' from the VBA Macro Editor).

    Code:
        Dim myReq As WinHttpRequest
        Set myReq = New WinHttpRequest
        
        myReq.Open "GET", "http://mywebapp:8080/orders/data.do", False
    
        'Set credentials
        myReq.SetCredentials "myUserName", "myPassword", HTTPREQUEST_SETCREDENTIALS_FOR_SERVER
    
        myReq.Option(WinHttpRequestOption_EnableRedirects) = True
        myReq.Send
    
        Dim res As String
        res = myReq.ResponseText
    Basically I need to post data to a Acegi secured URL from VBA. In my client app, I know the username, password, url and data to be posted. How do I go about this?

    Thanks,
    Sanjiv

  • #2
    The MS Http Services library does seem to be using Basic Authentication. I guess I've have to map my Acegi form and basic authentication filter urls accordingly.

    I am curious about the behaviour of defined in the web.xml file of the Acegi contacts filters sample. Both, the form auth. filter and basic auth. filter are mapped to /*.

    Anyway I'll try it out myself tomorrow.

    Sanjiv

    Comment


    • #3
      Re: accessing protected resource from Excel via WinHTTP

      Originally posted by sjivan
      The response I get is the html data of the web apps login screen.
      Sounds like you're not using BasicProcessingFilterEntryPoint against your SecurityEnforcementFilter.setAuthenticationEntryPo int(). If you're getting a login page, you're probably using AuthenticationProcessingFilterEntryPoint instead.

      Comment


      • #4
        I want most of my application to continue using form based authentication. However for the one URL that I'll be posting to via Excel, I need it to use basic authentication.

        If I set SecurityEnforcementFilter.setAuthenticationEntryPo int() to BasicProcessingFilterEntryPoint I'll end up using basic authentication throughout my app, wouldn't I?

        Is possible to configure one web app such that certain urls only are based on basic authentication while the rest are based on form authentication?

        I'm still not clear what the behavior is when the filterChainProxy is configured with both : authenticationProcessingFilter and basicProcessingFilter as below. Is this a valid configuration?


        Code:
        	<bean id="filterChainProxy" class="net.sf.acegisecurity.util.FilterChainProxy">
              <property name="filterInvocationDefinitionSource">
                 <value>
        		    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
        		    PATTERN_TYPE_APACHE_ANT
              /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,basicProcessingFilter,securityEnforcementFilter    
         
                 </value>
              </property>
            </bean>
        Thanks,
        Sanjiv

        Comment


        • #5
          I finally got things working but it wasn't without some extra investigative effort ...

          For the benefit of others I'll go over the details :

          My requirements were similar to those mentioned in another thread http://forum.springframework.org/viewtopic.php?t=2321

          so I knew that one could configure Acegi to work with FORM and BASIC authentication by providing the following filter chain

          Code:
          httpSessionContextIntegrationFilter,authenticationProcessingFilter,basicProcessingFilter,securityEnforcementFilter
          I configured my server with both FORM and BASIC authentication however despite my setting the credentials for BASIC authentication in the client VBA code, the response I'd get was still the contents of my login page.

          After reading "Basic Authentication Scheme" in RFC 1945 #11.1, I learnt how BASIC authentication is supposed to work.

          The client issues a request for a URL and the server denies access with a 401 status code AND a response header WWW-Authenticate that looks like the following

          Code:
          WWW-Authenticate&#58; Basic realm="MyRealm"
          When the browser receives a 401 status response it looks for the authentication scheme in the "WWW-Authenticate" header. When it finds an authentication scheme of 'Basic' it pops up a dialog box prompting the user login and when the user clicks 'Ok' it resubmits the request but this time encodes the user name and password in the header.

          Here is an example of the wire contents in a BASIC authentication based login.

          Code:
          REQUEST
          
          GET /test.html HTTP/1.1
          Accept&#58; */*
          User-Agent&#58; Mozilla/4.0 &#40;compatible; Win32; WinHttp.WinHttpRequest.5&#41;
          Host&#58; localhost
          Connection&#58; Keep-Alive
          
          GET /test.html HTTP/1.1
          Accept&#58; */*
          User-Agent&#58; Mozilla/4.0 &#40;compatible; Win32; WinHttp.WinHttpRequest.5&#41;
          Host&#58; localhost&#58;9000
          Connection&#58; Keep-Alive
          Authorization&#58; Basic VVNFUk5BTUU6UEFTU1dPUkQ=
          
          
          
          RESPONSE
          HTTP/1.1 401 Authorization Required
          Date&#58; Tue, 29 Mar 2005 16&#58;28&#58;08 GMT
          Server&#58; Apache/1.3.31 &#40;Unix&#41;
          WWW-Authenticate&#58; Basic realm="MyRealm"
          Set-Cookie&#58; path=/; expires=Wednesday, 29-Mar-2006 23&#58;59&#58;59 GMT
          Keep-Alive&#58; timeout=15, max=100
          Connection&#58; Keep-Alive
          Transfer-Encoding&#58; chunked
          Content-Type&#58; text/xml; charset=utf-8
          
          
          HTTP/1.1 401 Authorization Required
          Date&#58; Tue, 29 Mar 2005 16&#58;28&#58;08 GMT
          Server&#58; Apache/1.3.31 &#40;Unix&#41;
          WWW-Authenticate&#58; Basic realm="MyRealm"
          Set-Cookie&#58; path=/; expires=Wednesday, 29-Mar-2006 23&#58;59&#58;59 GMT
          Vary&#58; Authorization
          Keep-Alive&#58; timeout=15, max=99
          Connection&#58; Keep-Alive
          Transfer-Encoding&#58; chunked
          Content-Type&#58; text/xml; charset=utf-8
          
          121
          <html>
          <head>
          </head>
          <body>
          Hello World!
          </body>
          </html>
          When running with both FORM and BASIC authentication where the authentication entry point is AuthenticationProcessingFilterEntryPoint,
          Acegi does not add the "WWW-Authenticate" header in the response because it needs to redirect to the login form url of the configured AuthenticationProcessingFilterEntryPoint.


          Now back to my VBA code
          Code:
              Dim myReq As WinHttpRequest
              Set myReq = New WinHttpRequest   
              myReq.Open "GET", "http&#58;//mywebapp&#58;8080/orders/data.do", False
          
              'Set credentials
              myReq.SetCredentials "myUserName", "myPassword", HTTPREQUEST_SETCREDENTIALS_FOR_SERVER
          The SetCredentials method on the WinHttpRequest object wasn't working because it expects the same (2 phase) exchange protocol as a browser when running with BASIC auth alone. On a denied request, the WinHttpRequest object would examine the "WWW-Authenticate" header to figure out the authentication scheme and accordingly apply the provided user name password. However since Acegi does not set on the response when running with FORM + BASIC auth, the credentials were not being applied to by the WinHttpRequest object. (Besides the 'Basic' auth scheme, WinHttpRequest supports Digest, NTLM, Passport and Negotiate)

          So to get this working, I read the format of the user name/passoword that is required in the request header for Basic authentication and I'm setting it manually in the VBA code.

          Code:
          Authorization&#58; Basic Base64&#40;<username>&#58;<password>&#41;
          Now everything works perfectly.

          Acegi Rocks!! and being opensource definitely helps.

          Thanks,
          Sanjiv

          Comment


          • #6
            Originally posted by sjivan
            Acegi does not add the "WWW-Authenticate" header in the response because it needs to redirect to the login form url of the configured AuthenticationProcessingFilterEntryPoint.
            Good to see you sorted it out.

            Trying to mix form-based and BASIC/Digest-based AuthenticationEntryPoints in the same application comes up a bit. eg:

            http://forum.springframework.org/viewtopic.php?t=1266
            http://forum.springframework.org/viewtopic.php?t=3180

            Comment


            • #7
              When running with FORM + BASIC authentication, I am able to successfully access a URL via BASIC auth when I place the correct credentials in the "Authorization" header.

              However I'm seeing an unexpected behaviour when incorrect BASIC auth. credentials are passed.

              If the request contains an "Authorization" header element, its pretty clear that the client is trying to use BASIC authentication. However Acegi redirects to the FORM login page when incorrect basic auth credentials are passed. This makes is hard for a client to report that the user has passed bas credentials.

              I think it makes sense to return with status HTTP_STATUS_DENIED(401) in such a situation. This was the client can test for response status code and report an error accordingly.

              Let me know your thoughts.

              Thanks,
              Sanjiv

              Comment


              • #8
                Originally posted by sjivan
                If the request contains an "Authorization" header element, its pretty clear that the client is trying to use BASIC authentication.
                If BasicProcessingFilter detects a BASIC header and the header presents credentials that are incorrect, it will pass to BasicProcessingFilter.authenticationEntryPoint, which should be BasicAuthenticationProcessingFilterEntryPoint. Please check your configuration, and then you'll see the correct behaviour as per the RFC.

                Comment


                • #9
                  Yes, I am seeing this behavior. The problem turned out to be that I had delared an error page for 401 in my web.xml. duh..

                  Thanks,
                  Sanjiv

                  Comment

                  Working...
                  X