Results 1 to 9 of 9

Thread: accessing protected resource from Excel via WinHTTP

  1. #1
    Join Date
    Sep 2004
    Location
    Boston, US
    Posts
    130

    Default 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. #2
    Join Date
    Sep 2004
    Location
    Boston, US
    Posts
    130

    Default

    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

  3. #3
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default Re: accessing protected resource from Excel via WinHTTP

    Quote 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.

  4. #4
    Join Date
    Sep 2004
    Location
    Boston, US
    Posts
    130

    Default

    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

  5. #5
    Join Date
    Sep 2004
    Location
    Boston, US
    Posts
    130

    Default

    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

  6. #6
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    Quote 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

  7. #7
    Join Date
    Sep 2004
    Location
    Boston, US
    Posts
    130

    Default

    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

  8. #8
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    Quote 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.

  9. #9
    Join Date
    Sep 2004
    Location
    Boston, US
    Posts
    130

    Default

    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

Similar Threads

  1. Context initialization failed
    By kanonmicke in forum Container
    Replies: 7
    Last Post: Sep 29th, 2005, 12:35 AM
  2. Replies: 2
    Last Post: Jul 21st, 2005, 04:07 AM
  3. Replies: 4
    Last Post: Jun 27th, 2005, 11:32 AM
  4. Multiple value Property and JLists
    By afida in forum Swing
    Replies: 9
    Last Post: Aug 29th, 2004, 09:09 PM
  5. Quartz problem
    By khem in forum Web
    Replies: 4
    Last Post: Aug 17th, 2004, 02:34 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •