Skip to content

Example of a midPoint overlay project that implements a custom web service

License

Notifications You must be signed in to change notification settings

Evolveum/midpoint-custom-soap-service-wsdl

Repository files navigation

Midpoint custom SOAP WS overlay

Example of a midPoint overlay project that implements a custom SOAP-based web service. Head of the master normally follows the current development version of midPoint. See tag v4.4 for the last stable version.

The web service is implemented in the midpoint-custom-service-server. It is implemented by using JAX-WS contract-first development. WSDL file is part of the project and the service interface code is generated from that.

ℹ️
There is also simple code-first SOAP example using basic authentication via midPoint’s built-in flexible authentication. You can combine the code-first style with WS-Security described in this overlay.

The midpoint-custom-service-overlay is an overlay project that is using the web service client and integrates it with midPoint.

See also README from the basic overlay example, including also midPoint Overlay development notes. Check also related wiki page.

⚠️
This project is no attempt to demonstrate the best WS/CXF practices - it only shows CXF overlay. Some WS/WS-Security/CXF considerations are mentioned below, but we expect you know even better.

This overlay includes custom initial objects to add two roles with the authorizations for WS access. It also includes user jack with email address used in testing later.

Building and running

Just use the simple mvn clean package in the top-level project. It will build the service, create the overlay and build the client. The final midpoint.jar will be built in midpoint-custom-service-overlay/target. It can be run directly as executable JAR:

java -jar midpoint-custom-service-overlay/target/midpoint.jar

The web service will be listening at: http://localhost:8080/midpoint/soap/example-1

To run in an IDE choose com.evolveum.midpoint.web.boot.MidPointSpringApplication as the main class. Be sure to add "provided" scope to the classpath in the run configuration.

Testing

To test the service you may use SoapUI or similar software and point it to the example service WSDL. Try searching for user with email address [email protected]. Complete list of services is available via browser on http://localhost:8080/midpoint/soap/.

You may also use curl like this (also try -v if -si is not enough):

curl -si -d @- -H "Content-Type: text/xml;charset=UTF-8" http://localhost:8080/midpoint/soap/example-1 <<< '
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:exam="http://midpoint.example.com/xml/ns/example-1">
    <soap: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"
                soap:mustUnderstand="1">
            <wsse:UsernameToken wsu:Id="UsernameToken-1">
                <wsse:Username>administrator</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">5ecr3t</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </soap:Header>
   <soap:Body>
      <exam:searchUserByEmailRequest>
         <exam:email>[email protected]</exam:email>
      </exam:searchUserByEmailRequest>
   </soap:Body>
</soap:Envelope>
'

You may also try the request as user jack (password jack123) or create a new user and experiment with denied access - see the section about authorizations lower.

If the test returns 302 it typically indicates that the midPoint home is not initialized properly. Stop the java process, delete (or move) the default midPoint home directory and try again. See also the discussion lower.

Security policy changes

Before we talk about WS-Security there is one thing you should know. Because SOAP web service manages authentication separately we don’t want midPoint’s flexible authentication to interfere. This project overrides default midPoint security policy object to bypass flexible authentication for requests under /soap/ context.

Our midPoint Overlay development guide describes initial objects import and also how to override built-in objects.

Manual security policy change

ℹ️
This section is also relevant if you ran the overlay with already existing midPoint home directory that does not have changed security policy. If, for whatever reasons, you don’t want to delete midPoint home or specify different location you can still use the manual steps described below.

This is not necessary now, but if the security policy was not overridden the situation would be different. Trying the command from testing section above, it would try to redirect (HTTP 302) to /midpoint to authenticate.

To manually change the default security policy:

  • Open the browser, go to http://localhost:8080/ and login with user administrator and password 5ecr3t.

  • In the main menu on the left select Repository objects and then All objects below it.

  • On the All objects page change type of objects in the select box from System configuration to Security policy.

  • Open the only result Default Security Policy by clicking on it.

  • Edit the XML object by adding the following before the closing </securityPolicy> tag:

        <authentication>
           <ignoredLocalPath>/soap/**</ignoredLocalPath>
        </authentication>
  • Save the object and restart the midPoint.

This is a minimal change to the flexible authentication that does not replace the default setup, only alters it. The default authentication is however cached in the authentication filter and this minor change is not detected. (BTW, if authentication sequences were redefined such a change would be.) That’s why restart is required and realistically it’s a minor hassle so it’s unlikely this will be fixed.

Now with simple default object override this is all taken care of.

Authorizations

We mentioned that two roles with authorizations allowing access to the service are part of the overlay. You can check the initial-objects under midpoint-custom-service-overlay/src/main/resources. Role Custom WS User allows full WS access, Custom WS User - SearchUserByEmail allows only access to a single operation - as there is just this one operation it is merely for demo purposes.

User jack has the second role assigned and can access the only operation provided. Authorizations are checked in WsAuthorizationInterceptor:

  • First check is for "all" authorization, which also lets in any user with Superuser role.

  • Second step checks authorization for the currently called operation.

If these checks pass the call will get to the web-service method. It’s up to the method implementation to assure that authorizations are not the last line of defence and that model API is used properly to ensure other authorizations are applied as expected.

Logging and auditing

This overlay example has some minimal logging added for demonstration purposes. Most logging is on INFO level so logging does not need to be configured to see it. Any undesired case is logged as ERROR which should be fine-tuned in real-live implementation. Perhaps some cases should be just WARN without full exception logging, etc. This would require finer-grained catch clauses and/or some cause analysis in WsFaultListener.

For the web-service call we don’t recommend audit user login/logout, as that is more a notion for longer lasting session which doesn’t match stateless web-service calls. You can use AuditService.audit() to add audit records as needed.

Example uses channel constant CHANNEL_WEB_SERVICE_URI for Task and ConnectionEnvironment, but you may introduce your own channel constant.

WS-Security notes

There are many options how to set up WS-Security and this overlay shows only a simple solution. Please check CXF WS-Security documentation and/or other example projects, e.g. here. There were WS-Security changes in CXF around version 3.1, so be careful with online sources like StackOverflow.

It is also possible to use headers or body of the message for authentication information. Or you can protect the WS with firewall, have no authorization information in the SOAP messages whatsoever and set predefined technical user in some interceptor. There are many scenarios and solutions and this overlay does not tackle these at all.

Validator vs PasswordCallback

The most important part of the overlay setup is usage of custom Validator for UsernameToken. By default CXF uses UsernameTokenValidator that expects us to implement CallbackHandler to fill WSPasswordCallback with password so that validator can compare it with the one in the message. This can’t work if midPoint passwords are hashed and WS-Passwords are plaintext. It seemed better to implement Validator with custom WsUsernameTokenValidator that extracts the user name and password and tries to authenticate with it without reading stored user’s password.

This validator is much simpler than the original implementation and may not be suitable for other options how UsernameToken element can be used - this must be customized if needed.

Type attribute in Password element

Attribute Type in wsse:Password element is required by Basic Security Profile (BSP) 1.1 rules. This can be relaxed if you add property into jaxws:endpoint setup in cxf-example-service.xml:

<jaxws:endpoint id="exampleWS" ...>
...
    <jaxws:properties>
        <entry key="ws-security.is-bsp-compliant" value="false"/>
    </jaxws:properties>

If this property is set, you can omit Type attribute from Password element. This also means you can’t utilize Type in any decision related to password validation. This property is set in our example and Type is just optional attribute.

About

Example of a midPoint overlay project that implements a custom web service

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages