Wednesday, April 7, 2010

More on WLI and UsernameToken

if you provide this policy file to protect your WLI process:

@WSSecurityService(file="mypolicy.xml")


<wssecuritypolicy xsi:schemalocation="WSSecurity-policy.xsd">
xmlns="http://www.bea.com/2003/03/wsse/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<wssecurityin>
    <token tokentype="username">
</token></wssecurityin></wssecuritypolicy>


you get this error message:


java.rmi.RemoteException: EJB Exception: ; nested exception is:
com.bea.wli.knex.runtime.jws.wssecurity.exception.WLWWSSEException: Policy requires Message to contain UsernameToken, UsernameToken not found in the Message.
Caused by: com.bea.wli.knex.runtime.jws.wssecurity.exception.WLWWSSEException: Policy requires Message to contain UsernameToken, UsernameToken not found in the Message.


this is fantastic. I wonder why WLI manuals say that JPD don't support security... they are funny.


Now I try passing a Username in the Soap Header:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:open="http://www.openuri.org/">
<soapenv:Header>
<wsse:Security
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
soapenv:mustUnderstand="1">
<wsse:UsernameToken wsu:Id="SecurityToken-1">
<wsse:Username>username</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
password
</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>

<soapenv:Body>
<open:clientRequestwithReturn>
<!--Optional:-->
<open:x0>pippo</open:x0>
</open:clientRequestwithReturn>
</soapenv:Body>
</soapenv:Envelope>


and I get a fantastic:

javax.security.auth.login.FailedLoginException: [Security:090304]Authentication Failed: User username at weblogic.security.providers.authentication.LDAPAtnLoginModuleImpl.login(LDAPAtnLoginModuleImpl.java:230)
    at com.bea.common.security.internal.service.LoginModuleWrapper$1.run(LoginModuleWrapper.java:110)
    at com.bea.common.security.internal.service.LoginModuleWrapper.login(LoginModuleWrapper.java:106)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
    at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
    at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
    at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
    at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
    at com.bea.common.security.internal.service.JAASLoginServiceImpl.login(JAASLoginServiceImpl.java:113)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.bea.common.security.internal.utils.Delegator$ProxyInvocationHandler.invoke(Delegator.java:57)
    at $Proxy16.login(Unknown Source)
    at weblogic.security.service.internal.WLSJAASLoginServiceImpl$ServiceImpl.login(Unknown Source)
    at com.bea.common.security.internal.service.JAASAuthenticationServiceImpl.authenticate(JAASAuthenticationServiceImpl.java:82)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.bea.common.security.internal.utils.Delegator$ProxyInvocationHandler.invoke(Delegator.java:57)
    at $Proxy34.authenticate(Unknown Source)
    at weblogic.security.service.WLSJAASAuthenticationServiceWrapper.authenticate(Unknown Source)
    at weblogic.security.service.PrincipalAuthenticator.authenticate(Unknown Source)
    at weblogic.security.service.PrincipalAuthenticator.authenticate(Unknown Source)
    at weblogic.webservice.util.ServerSecurityHelper.assertIdentity(ServerSecurityHelper.java:45)
    at com.bea.wli.knex.runtime.jws.wssecurity.inbound.WLWInboundWSSEImpl.assertIdentity(WLWInboundWSSEImpl.java:458)



Exciting!
I can see in the stacktrace interesting stuff like: ServerSecurityHelper.assertIdentity(), PrincipalAuthenticator.authenticate(), JAASAuthenticationServiceImpl.authenticate(), LDAPAtnLoginModuleImpl.login()...

Now I create the username "username" in the default security realm, with password "anotherpassword"

I still get the

javax.security.auth.login.FailedLoginException: [Security:090302]Authentication Failed: User username denied

(so we understand that "User xxx denied" could also mean "bad password")

When I provide the right password, everything works.

I am using SOAPUI to submit the request.

If I remove the Security header from the SOAP message, and I select the WSS-Password Type= password text, and I provide username and password in the appropriate properties, things work again fine. (tip: look in the SOAPUI http log, you should see the password being trasmitted in the clear with the SOAP request).

If you choose WSS-Password Type=digest, you transmit this:

<soapenv:Envelope xmlns:open="http://www.openuri.org/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header><wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:UsernameToken wsu:Id="UsernameToken-5" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><wsse:Username>username</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">DNBu/78N8l0BgBzKPvJglF8zlqw=</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">Kb64xrWI9XLLjdmTcIZATQ==</wsse:Nonce><wsu:Created>2010-04-07T12:27:21.353Z</wsu:Created></wsse:UsernameToken></wsse:Security></soapenv:Header>[\n]"

As recommended by OASIS http://www.oasis-open.org/committees/wss/documents/WSS-Username-02-0223-merged.pdf , also Nonce and Timestamp ("Created") are supplied (they are supplied also in the "password text" case).

Now, just for fun I hack the header and set Created to 2009-04-07T12:33:17.551Z
The Web Service still process it.... how to tell Web Service to reject a request which is 1 year old?

I look into http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/ws-securitypolicy.xsd if there is any such option. I don't see anything inspiring.

Theoretically the "Created" info should be embedded into a  wsu:Timestamp element.... the WS-Security specs seem very loose and fuzzy, I have the impression that SOA is built on a under-specified standard which imposes every solution to reinvent the wheel adapting a generic standard to its own internal needs.
I guess some billion dollars have been lost so far because of this fuzziness.

Anyway... this is the standard:

           <wsse:Security xmlns:wsse="..." xmlns:wsu="..."
soapenv:mustUnderstand="1">
                <wsu:Timestamp wsu:Id="Timestamp-31497800">
                    <wsu:Created>2009-11-02T14:00:00Z</wsu:Created>
                    <wsu:Expires>2009-11-02T15:00:00Z</wsu:Expires>
                </wsu:Timestamp>


       <wsse:UsernameToken wsu:Id="UsernameToken-10697954">
                    <wsse:Username>...</wsse:Username>
                    <wsse:Password Type="...#PasswordText">...</wsse:Password>
                </wsse:UsernameToken>

so the "created" is associated to the Timestamp, not to the Username... in fact I have read that the "Created" clause can be attached to any Element.

No comments: