Latest Activity

Amazon EC2 plugin – 1.30 Released

Francis Upton's blog - Sun, 01/24/2016 - 01:46

A significant bug fix release was made in the plugin, thanks to all to helped test is and provided contributions.

The next release will probably be in the next month or so and will include the acceptance of enhancement PRs that have been filed.

Version 1.30 (Jan 23, 2016)
  • Add config to prefer the public IP to private IP when ssh-ing into slave
  • Added common method to compute tag value and also created constants for demand and spot
  • JENKINS-27601 instance caps incorrectly calculated
  • JENKINS-23787 EC2-plugin not spooling up stopped nodes
  • Depend on the aws-java-sdk plugin to limit AWS SDK duplication
  • Upgrade AWS SDK to 1.10.26
  • Terminate instance even if ec2 node deletion failed
  • JENKINS-27260 SPNEGO for Windows in the EC2 Plugin
  • JENKINS-26493 Use new EC2 API endpoint hostnames
  • JCIFS first tries to resolve a dfs path would timeout causing a long startup delay
  • JENKINS-28754 Jenkins EC2 Plugin should show timestamp in slave logs
  • JENKINS-30284 EC2 plugin too aggressive in timing in contacting new AWS instance over SSH
  • Use AWS4SignerType instead of QueryStringSignerType
  • Add minimum timeout for windows launching
  • Better exception handling in uptime check
  • JENKINS-29851 Global instance cap not calculated for spot instances
  • JENKINS-32439 JENKINS-32439 Incorrect slave template (AMI) found when launching slave
  • Improve logging to be less verbose

Categories: Francis Upton

Two Bays trail run 2016

Olivier Lamy - Sun, 01/24/2016 - 00:12
So I just started the year with a mid distance trail running.
Last year I did the 28km but decided to go for the 56km this year.
Training during summer and xmas period is a bit complicated and need some real motivation. But I finally managed to do a decent training.
The race was a bit complicated with the weather. I had some hard time with the hot (33° in some country bush part!!)
Bad eating strategy at the start. (eat too much...)
But so I did it. I would expect better time but the temperature really kills me on the way back. So I must be happy with this 7H for 56km and +1600m/-1600m.
I managed to build a video. So enjoy how is to run in Australia :-)
Strava activity here (Some GPS issues but I really did 56km :-) )
Next race is the rollercoaster 44km 27th February.
Then the big one of the year Ultra Trail Australia 100km in the Blue mountains.
And maybe the Surf coast century for a second time with a sub 12h goal (depends how the body will be in Jun :-) )
Categories: Olivier Lamy

Understanding Spring Web-Flow in Apache Fediz - Part 2

Jan Bernhardt - Sat, 01/16/2016 - 15:46
After explaining in Part 1 of this topic how the Spring Web-Flow will be initiated I'm going to review the actual flow in some more detail in this post.

The signin request flow can be customized within the WEB-INF/flows/federation-signin-request.xml file. The standard flow looks like this:


The bold line shows a normal login flow, when the user was not authenticated earlier and no 3rd party IDP is involved.
TO BE CONTINUED...
Categories: Jan Bernhardt

Amazon EC2 Plugin Release 1.30

Francis Upton's blog - Tue, 01/12/2016 - 16:24

I have just finished a bunch of work on this plugin to fix a number of bugs related to starting instances and respecting instance caps for spot instances. The plugin will now restart a stopped instance and always respect the instance caps. Other issues about the credentials working correctly in all regions should be fixed.

Before I make this release, I would like to have people test with the 1.30 Snapshot to see if there are any problems. Once this release is done, I will take some new features and move to require a more recent version of Jenkins.


Categories: Francis Upton

Understanding Spring Web-Flow in Apache Fediz - Part 1

Jan Bernhardt - Thu, 01/07/2016 - 16:20
When I started to work with Apache Fediz, most of the actions looked like magic to me, because I was not able to understand how Spring Security and Spring Web Flow have been used in Apache Fediz. After several hours of learning and investigation I finally understood how all this works together.

In this post I would like to share with you from what I understood of how Fediz works internally.
When you take a look inside the WEB-INF/web.xml you will find three URL mappings:
<servlet-mapping>
  <servlet-name>CXFServlet</servlet-name>
  <url-pattern>/services/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>idp</servlet-name>
  <url-pattern>/federation</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>metadata</servlet-name>
<url-pattern>/FederationMetadata/2007-06/FederationMetadata.xml</url-pattern>
</servlet-mapping>
  • /services/* provides access to all REST services for updating the IDP configuration
  • /FederationMetadata/2007-06/FederationMetadata.xml provides access to the generated IDP metadata document which is usually used in application wizards to setup the correct IDP configuration
  • /federation provides access to the configured Spring Web-Flow

If you take a look inside the WEB-INF/web.xml you will see that the /federation URL is linked with org.springframework.web.servlet.DispatcherServlet. The initialization of the Spring Flow however takes place within the WEB-INF/idp-servlet.xml.
So how is the DispatcherServlet linked to the idp-servlet.xml?
The key to the answer is Spring MVC which uses Convention over Configuration (CoC). Spring will search for a file with the same name as the servlet-name and ending with "-servlet.xml". To apply this knowledge you can see that the /federation URL is mapped to the servlet name idp and thus the default configuration spring file which will be loaded from the DispatcherServlet is idp-servlet.xml
Spring ConfigurationWithin the idp-servlet.xml you will find a spring configuration to setup the Spring Web Flow.
First Spring will do a component scan to instantiate and autowire all beans with a @Component annotation located within the beans package. These beans usually provide specific actions which are executed within the flows.
<context:component-scan base-package="org.apache.cxf.fediz.service.idp.beans" />
Now the JSP views and HTML resources like images will be made available for the spring web flow:
<mvc:resources mapping="/images/**" location="/resources/images/" />
<mvc:view-controller path="/" view-name="index" />
<mvc:view-controller path="/federation/up/login" view-name="signinform" />

<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>

<bean id="viewFactoryCreator"
class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers">
<list>
<ref local="viewResolver" />
</list>
</property>
</bean>

<bean id="expressionParser"
class="org.springframework.webflow.expression.WebFlowOgnlExpressionParser" />

<webflow:flow-builder-services id="builder"
view-factory-creator="viewFactoryCreator" expression-parser="expressionParser" />
At next the actual spring web flows will get registered. All beans setup within this spring config will be available within the web flows.
<webflow:flow-registry id="flowRegistry"
    flow-builder-services="builder">
    <webflow:flow-location
        path="/WEB-INF/flows/federation-validate-request.xml" id="federation" />
    <webflow:flow-location
        path="/WEB-INF/flows/federation-validate-request.xml" id="federation/up" />
    <webflow:flow-location
        path="/WEB-INF/flows/federation-validate-request.xml" id="federation/krb" />
    <webflow:flow-location
        path="/WEB-INF/flows/federation-validate-request.xml" id="federation/clientcert" />
    <webflow:flow-location 
        path="/WEB-INF/flows/federation-signin-request.xml" id="signinRequest" />
    <webflow:flow-location 
        path="/WEB-INF/flows/federation-signin-response.xml" id="signinResponse" />
</webflow:flow-registry>
Adding security restrictions to the flow will allow spring security to be included in the flow for user authentication.
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping" p:flowRegistry-ref="flowRegistry"
    p:order="2">
</bean>

<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
    <webflow:flow-execution-attributes>
        <webflow:always-redirect-on-pause value="false" />
    </webflow:flow-execution-attributes>

    <webflow:flow-execution-listeners>
        <webflow:listener ref="securityFlowExecutionListener" />
    </webflow:flow-execution-listeners>
</webflow:flow-executor>

<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter" p:flowExecutor-ref="flowExecutor" />

<bean id="securityFlowExecutionListener" class="org.springframework.webflow.security.SecurityFlowExecutionListener">
    <property name="accessDecisionManager" ref="accessDecisionManager" />
</bean>

<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
    <property name="decisionVoters">
        <list>
            <bean class="org.springframework.security.access.vote.RoleVoter">
                <property name="rolePrefix" value="ROLE_" />
            </bean>
            <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
        </list>
    </property>
</bean>
The spring security configuration can be found within the WEB-INF/security-config.xml file.
Categories: Jan Bernhardt

Register trusted 3rd party IDP with SAML Web Browser SSO Profile

Jan Bernhardt - Fri, 12/18/2015 - 23:35
In this Post I'll explain how to configure Apache Fediz IDP so that it can be used with a trusted 3rd party IDP based on SAML Web Browser SSO Profile.

In my previous posts about Apache Fediz I focused on the WS-Federation passive protocol only since it is the successor standard for the SAML Web Browser SSO Profile. But in some cases you will have to establish a federated trust relation with an IDP how does not support the WS-Federation Standard yet, but only the older SAML Web Browser SSO Profile.


I'll explain how to register a SAML trusted IDP at the IDP as well as how to setup a demonstrator. Please also take a look at Colms post about this topic. PreconditionsI would assume that you have the fedizhelloworld demo application already running within your Tomcat container, as well as the Fediz IDP & STS in a second Tomcat  container. If you don't know how to do this, you will find a detailed instruction in my previous post about Fediz, as well as this post from Colm.
Install SAML IDPFediz IDP itself does not support the SAML Web Browser Profile as a primary IDP protocol. So you cannot use Fediz IDP so login based on SAML Web Browser Profile. But you can register a 3rd party IDP based on that profile when Fediz is acting as a Service Provider (client).

For purposes of integration testing however the Fediz Project provides a mockup implementation of a SAML IDP which we will use for demonstration purposes here. To build the war file you should do the following:

1. Clone the Fediz Sources on your computer with GIT
> git clone -v https://github.com/apache/cxf-fediz.git
2. Goto the systestfolder and build the systest with maven
> cd cxf-fediz/systests/federation/samlIdpWebapp/
> mvn -Pfastinstall
3. Copy war file to tomcat webapps folder
> cp target/*.war ${tomcat.fediz.idp.home}/webapps
4. Start Fediz-IDP and Fediz Demo app (if not already done yet)
> ${tomcat.fediz.idp.home}/bin/startup.sh
> ${tomcat.fediz.rp.home}/bin/startup.sh Register 3rd Party IDPNext you must register the SAML SSO IDP at your Fediz-IDP so that you can choose it as your home realm at the login process. This can be done via a REST API since version 1.2.0.

The REST Service API requires a Basic user authentication. Default username is admin and password is password.
1. Register a new 3rd Party IDP
POST https://localhost:9443/fediz-idp/services/rs/trusted-idps
<ns2:trustedIdp id="0" xmlns:ns2="http://org.apache.cxf.fediz/">
   <realm>urn:org:apache:cxf:fediz:idp:realm-C</realm>
   <url>https://localhost:9443/samlssoidp/samlsso</url>
   <name>Realm C</name>
   <description>SAML Web SSO</description>
   <protocol>urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser</protocol>
   <trustType>PEER_TRUST</trustType>
   <certificate>realmb.cert</certificate>
   <federationType>FEDERATE_IDENTITY</federationType>
   <cacheTokens>true</cacheTokens>
   <parameters>
      <entry>
         <key>support.deflate.encoding</key>
         <value>true</value>
      </entry>
   </parameters>
</ns2:trustedIdp>2. Assign this new 3rd Party IDP to your Realm-A Fediz IDP
POST https://localhost:9443/fediz-idp/services/rs/idps/urn%3Aorg%3Aapache%3Acxf%3Afediz%3Aidp%3Arealm-A/trusted-idps
<ns2:trustedIdp xmlns:ns2="http://org.apache.cxf.fediz/">
    <realm>urn:org:apache:cxf:fediz:idp:realm-C</realm>  
</ns2:trustedIdp> Test: Perform a federated Login
Make sure to delete any localhost cookies within your browser. Otherwise your preferred home realm could be stored within a cookie and therefore your would not see a home realm selection screen.
Now you can perform a login by invoking the following URL:
https://localhost:8443/fedizhelloworld/secure/fedservlet

You should see a home realm selection screen, with our new SAML SSO IDP which you should select. Next you should see a Basic user authentication window. Here you can login with ALICE and ECILA as your password.


After some redirect you should see the demo page with your federated user account from alice:

Review Redirects in DetailIf you use a monitoring tool like Fiddler, you will be able to analyze the redirects in greater detail.

After invoking the fedizhelloworld demo app, I'll get redirected to the Fediz IDP:
GET https://localhost:9443/fediz-idp/federation
     ?wa=wsignin1.0
    &wreply=https%3A%2F%2Flocalhost%3A8443%2Ffedizhelloworld%2Fsecure%2Ffedservlet
    &wtrealm=urn%3Aorg%3Aapache%3Acxf%3Afediz%3Afedizhelloworld
     &wct=2015-12-18T17%3A45%3A36.860Z
    &wctx=b9220a8a-5802-41a2-9128-a2ba649a72bc
The Fediz IDP will show you the home realm selection page and after selection will redirect you to the SAML SSO IDP
GET https://localhost:9443/samlssoidp/samlsso
    ?SAMLRequest=nVNdb9owFP0rkd9TEkihuQIkBpqG1G0pZHvYm3FuiiXHznydlu3Xz07TlofBpL3545xzj8%2B9nhNv1LiFVeeOeoc%2FOyQXrYjQOmn02mjqGrR7tE9S4Lfd%2FYIdnWsJRiNlBFdHQw7yLJuMaqzk71hWbVih5YHOoo2Xk7rfXGQGB0QmUIcliz4aK7D3tGA1V4Qs2m4WTMzq5DDNeFxPJkmc3aXTOM9nWZxM0yrnh6ziSeqRVHAi%2BYTvXKIOt5oc127Bxkl6G6fjOL0r0xlktzDJb2Z5%2BoNFhTXOCKM%2BSF1J%2FbhgndVgOEkCzRskcAL2q8%2F3ML5J4PACIvhUlkVcfN2XLPqOlvq3egCLTo3SBC8JX9dqh8JsOe%2Fh0Du25wrXBfhry9iyh9lH4C0XRwRxqqFvDviEwSJXTbyaj87LDEVb%2BOJ1t5vCKCl%2BRSulzPPaE5wP0tkO%2B7Y03F13Ek5kFdc9FNoQCDnUjkX7Iug%2FdFzJWqIdZP7hlI3e3A3jiVU%2FGH42HZ5ctDZNy62kkDqeuHBvGZ7D1sontMP6%2FxO9BBMggrY%2FDlP3bGwVpgiF91larqk11r3G%2FTdHy%2BHywvver8%2B%2F6PIP
     &RelayState=962c9908-489c-4ea2-b1a4-090e180c91f3
    &SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1
    &Signature=PyFe4kjQLWUoatdKZ0uZig27CSgrIZpmgU%2FiGL86KW8JIeVgAEIm9StYwdPUWiJO9KMM5wKmd9o6tWjFM7oIEtv8yIYo%2Fcr1nX7qDj5QRd2ni2akDH61OdV%2FvPECS0auRolW1vDwT6qwnqBFNC1KWSJXXpHu0bk7HXRkfnyA3p557ZECunsYsPhMp1JfaGQJUP8tw2LR0HNweoL7NA%2FbKU8lzwKrIcmJ7kFsYC2OrW3TucfqruQ0hrQYIvHFyISwqc7uWRgiGo8KhvTuw1pg2JvpZJZq%2F50OWHGWLWuE5QKT2C5yjJeb7xch4gPkg4PIBJCqrENZSE7OZWIcb%2Fydjw%3D%3D
You can use for example Notepad++ to decode SAML-P Requests & Responses.


After decoding the SAMLRequest you will see the following SAML AuthnRequest:
<saml2p:AuthnRequest AssertionConsumerServiceURL="https://localhost:9443/fediz-idp/federation" Destination="https://localhost:9443/samlssoidp/samlsso" ForceAuthn="false" ID="c7f0b64a-f330-4816-9974-061d9ab4da01" IsPassive="false" IssueInstant="2015-12-18T17:45:39.791Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">urn:org:apache:cxf:fediz:idp:realm-A</saml2:Issuer>
    <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" SPNameQualifier="urn:org:apache:cxf:fediz:idp:realm-A"/>
    <saml2p:RequestedAuthnContext Comparison="exact">
        <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
    </saml2p:RequestedAuthnContext>
</saml2p:AuthnRequest>

After login at the SAML IDP the user will be redirected back to Fediz-IDP:
GET https://localhost:9443/fediz-idp/federation
    ?SAMLResponse=rVdZk6JMFn33V1TYj4YFCYhAdFUEiwsKgiIqvEywJIuySYLbrx%2B0ytqmqqfniwkfJC93OffcJDn8Rk6aEAW3gKjIMwQfZOmpzUBI9hkHdH2A97sUSwZdF7heF2dpD3dZlqEDov0gZ/egZf7U9voB7tKU0w1IEu9SDKC7LNunujgNfNZxKd/BQRODUA3lDFVOVj21CRz0uoDoAmYJ%2BhzV40j2kSFxu/2wgiWK86xxecTbD6c0yRD3gvSpXZcZlzsoRlzmpBBxlccZvKpwjStXlHmVe3nSfv59c%2BduBcuPGf6cwEEIllVTuv0cVVWBOAxLcs9JohxVHEtRJHZNglAe%2B8X98jf2sdZr5YIzKqeq0ZelmPvwYeUkNfwzDnTz5oza8yBCbez5tciXtBx/x3sb3L9YQDE0QzBdzyV7XQr0mC7ju0yXpkjAeC5OeX38/zCFv%2BXwNeaE4qf2lc6GzePx%2BHgkH/MyxAgcB9hGVQwvgqnTjW%2BAPNhEoZirzkVD0Zcml43xy2j/%2BZj8ht44zBo2S/gK1Ec/4MQxnMUaHx/F4a/2Wyz05SzIb0vRyfIsbiDEF%2BcKVYVVlPsPfBLmZVxF6Y8EAPyauAtPXtcDVPbrOuuP0P4y0SeEJXK6KHLAa64FDGAJG2ofzIX81P71d9vkFrosnQwFeZmiz8v/DQ/MDjDJC%2Bh30b2tV2h/n/B7prD/xCjFIUTVP6HtA2UvSW4P6jM7r1aVQScStV%2BeeJ3igaqVnjMrhOPTDcBH55vhjfCX5Zet8jbal4ghSA3AWtlZP1qzmglsIDn9%2BcLaXlYXRpdwYOIRT1L0ft9bDFczYjY3Ombp7Ox0Wep1NauKmtFxeROWKbVH/WGhRoJTVbxrni9o6MtLeWPLOl8SypJQsWQqOEzMFpI2cQNWm4S14eY4bxm8MdY3YDZVjkSA2QsKGEHQIS8nuTfWjoW58cb%2Bsq8IU1zbTGNKK5SL2wlPoifyNCmpaDE9r3GgT3HEb6roMoQBEpyOp5xlpIdqudrpQ8OzmfzSmXWGmTvU0m2fKdw5sdlsjsuB5UwjhtqPowu6jGpS1EUlV7cFpdRAHa51TzpT%2B10RwJnhgXHfww5jw%2BxjEFvXwWgsshB6grGa0HYmx8I0M87Hp6c36j9wfaV/Cs9vo9j0cFZyKudtIV4PmqB5jiv4rMqyeFyKIu%2BkIX%2BUBT6UB75DXIoLPxPC3T7axSP2iAv8HA15iV%2Boc%2BYozS1pNZ9Lg6NtLMyhujTl4zjyZq3m6jjbDo7NPz6TVGLdGNVtY5MG1Jtt%2B3OSMBzEKo%2BPRGM/ahmyS0rzQVPZ5HlKFqQjf3WY8nmDci4OvZ6A4Wd3aNmZsc1YgyZrfc/Kwnq%2BQgQ8ODZl4sdDAOnDKmnttZrXGDraTjB6EBpurY0TVY9lyyUTH1IpXO7pQWdTrPMTrgwY5WzM/RN2AAYDVsRkqoA862/iZiO4lNnCiRTfb2YwpvsLYIr83K7cqDgsoTdJ/SznHbfQ5MnO2CfzTKsYoqT8zWlgDXumXMb2KJ5bKr0zB41oOBQtfQgunfLEwHJLx8yomkNdW8fbKjMTex%2BOjsrgsMNnRH%2B0kEOgjTvJaFQQxWiHy%2BxYXbDaebnDFrvhYQcF1OKTvbIXk%2B15m4tbf4E0ewQ1tEaCR9jZqgOgop2yogeZ3KFjK5/V0t6ubEZNwSEZM5M1PQY6H6oCz4%2B2LXnJB6qAj3hg%2BlI4XwvCgoDYycysYguUgFY3qrbeL0pfWW2I7Tfbhdcabga8crLZFnAmEhwO1BAPPEhHghhtzqYHtIk3LE4nwk4vENcu61PEW%2BuQzDdEXzVn4aK389VcnwSBSEiRiUiTXHeElrWY4ltxX9S4ilnUIDxR8f4cjj3eWS54PcVGlb1DnaQDlcW4Y2BbfRWRl2m8xjEz2M2ts9Xb7e04ETJpo7fsodpkMDNPZyGrsDGRns364lUFu8lZdbS2lr3zcBojF2SH2TQkC2sydegqCwKgqGR4glvRSz1hPj0nZUtvzs2%2BnljRmXV2m9U4nUvlBYwR5E8l5lPWAXWsMhqXqR0N93W191V5YExGs%2Bb0Ho%2BtxTDVdBe/CGqNU1QLapHX0cwTpYzrCyywbFqlUj4bj0YnZ5pY5IB/PQC%2BPtRvxpfHHvt4IHw6MO4yw6jdLfSq%2B3LWyB1Zehg2rxun%2BlkHgUdws8R%2BN7i5cnWGCug1MKDffuYVWRzcBclLyi/1xDwL4mvgVdu9vMz%2BrLq8lHOhU8Ky/YdM16YfeN8vG1H51AZE/xFvfuCfiflZXmmZVvJBBcuvMrKHv8vIRdN2EcOr1vxBrAXQjy/dq1ZrrmB5g/queb9r5Ou9e8%2BNjx9fHdAVngAb8uFPEhfYf9dD4/cmt2s/vr7XG7KqMvZekHy%2B9XwbUhlyTuE0wpbzTgF3649r%2BuNK6CRpl7%2Bjfwv6avhUAPva23vNKsquHwQwbeh9uC3/u67/FN0kreCp%2Bs4mJo2Sb6TM8x/Fvsd5V7/GrDd/x7z033v5Jtd3Nz8b3/p5N9/1//tX0H23Pv8b    
    &RelayState=962c9908-489c-4ea2-b1a4-090e180c91f3Usually you would receive a POST message from the SAML IDP instead of a GET redirect, as done here by the mockup IDP.
A decoded SAMLResponse will look like this:
<saml2p:Response ID="1772f107-14b9-4d27-9d21-f3a1cf655648" InResponseTo="41e5c1dc-7cfe-446e-b475-3fb7a40b5432" IssueInstant="2015-12-18T14:16:24.456Z" Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://localhost:9443/samlssoidp/samlsso</saml2:Issuer>
    <saml2p:Status>
        <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
    </saml2p:Status>
    <saml2:Assertion ID="_42311918-c677-4773-86b7-e5b42340354d" IssueInstant="2015-12-18T14:16:24.456Z" Version="2.0" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="saml2:AssertionType">
        <saml2:Issuer>https://localhost:9443/samlssoidp/samlsso</saml2:Issuer>
        <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:SignedInfo>
                <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
                <ds:Reference URI="#_42311918-c677-4773-86b7-e5b42340354d">
                    <ds:Transforms>
                        <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                        <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                    </ds:Transforms>
                    <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                    <ds:DigestValue>IvKTW0enrkTeXynCf9Aj0053fXM=</ds:DigestValue>
                </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>GcHGaMUt6zM+tdKty0yXWOniNXh5V8JfYrCkjerx1LPI7K2w4oWCTfGtZ4TCnAhoKZQsyA3+VDpFg25HZIMjJVznazHPQ1idjvy5zlKdmG+jaHf+JWrKMuCb3w3UPJwWFEod49BnLGgLkBORr4rgWi0c4eloSK8NCnBHOXwhJHxkw5nUe+FIiuLpuIxbWnNddsWr7091ImuawDxfYfPDJuxaXX19EP2nx2zc7oQrmbqZAIIftao87OeAr2hfg4BDpAO7kFQC+Iw2B4pkmLUnJNyzspfU96bN9HaNvhBZSWD1HEdTzkHaNr9r1h9SSksBZLdmT8+p0+QidzNXN5H/sw==</ds:SignatureValue>
            <ds:KeyInfo>
                <ds:X509Data>
                    <ds:X509Certificate>MIICwTCCAamgAwIBAgIEda2zpzANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDEwZSRUFMTUIwHhcN
MTUwNjEwMTU0NDM2WhcNMjUwNDE4MTU0NDM2WjARMQ8wDQYDVQQDEwZSRUFMTUIwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCFc5B/0ybFYZnSjn9S63uPq9IBWQVs2evaZ4U0wvfe6vVl
qOuAO86hjJ/6EgSbuOHlMPiIYb3lde4meTq6E+XpWox0LE8LySQdx/v1S81V2JKL1on7XiCcCb4U
02m0qXNei67R1UCAQZtbhpvTecJmdnoAabpOIJkSqlQnOt82r4dXxEYF5UIriZGiQYM6kUE61dvp
PF1z+rx8erj6i8GtQePOWijtnUlZqgGwLEvk0N27GRIg1OH+lGGp2pGk0I9HMR9OyTk/RkFvkeBs
AlqLqCljyjoCjdRsOZGeOsWsBc2ZnV+1eLOxnp5e8oa6iYoNuDqZtZ8Mm1vlH8JW6H1PAgMBAAGj
ITAfMB0GA1UdDgQWBBR2e/xUnYpj1Lf6MXMOWqRrdLVX2jANBgkqhkiG9w0BAQsFAAOCAQEALxZ9
1aJDeFEMg0fce6hBChXyUc1OJcFpxx2Zmze0OzWxhAYWg3oX27MUNgR5kdMoPJffC2DhUs3U3W+B
YRK0jCqpu0M/Y4Egx4iqygHcAaTRAPm/GtZks+l+eLRH+S/jPVh3zKiW0/UfkQYyY5kqZilBnDXP
ZFMEgxUncP9e9L9i2myUuzctp9Xo9MGWYT5yFKisb1nvNKg3pYJKa6tnff1LM3gxejCcmcBQKylr
PA1M7PlYhy9akXVHmQDrz1HseAxr/d4Yvs+YrhHrmZhFqutqdMIESJGNithHHYRFmOPb0zBMu044
eOhc+OUx4LHuzep/nKtmDoNHGGxaKlY3EA==</ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
        </ds:Signature>
        <saml2:Subject>
            <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">ALICE</saml2:NameID>
            <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml2:SubjectConfirmationData Address="127.0.0.1" InResponseTo="41e5c1dc-7cfe-446e-b475-3fb7a40b5432" NotOnOrAfter="2015-12-18T14:21:24.456Z" Recipient="https://localhost:9443/fediz-idp/federation"/>
            </saml2:SubjectConfirmation>
        </saml2:Subject>
        <saml2:Conditions NotBefore="2015-12-18T14:16:24.456Z" NotOnOrAfter="2015-12-18T14:21:24.456Z">
            <saml2:AudienceRestriction>
                <saml2:Audience>urn:org:apache:cxf:fediz:idp:realm-A</saml2:Audience>
            </saml2:AudienceRestriction>
        </saml2:Conditions>
        <saml2:AuthnStatement AuthnInstant="2015-12-18T14:16:24.456Z">
            <saml2:AuthnContext>
                <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef>
            </saml2:AuthnContext>
        </saml2:AuthnStatement>
    </saml2:Assertion>
</saml2p:Response>


Fediz-IDP is configured to do a identity mapping and will return a SAML token back to the demo application according to WS-Federation.
POST https://localhost:8443/fedizhelloworld/secure/fedservlet

wa=wsignin1.0
&wresult=%3CRequestSecurityTokenResponseCollection+xmlns%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fws-sx%2Fws-trust%2F200512%22+xmlns%3Ans2%3D%22http%3A%2F%2Fwww.w3.org%2F2005%2F08%2Faddressing%22+xmlns%3Ans3%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fwss%2F2004%2F01%2Foasis-200401-wss-wssecurity-utility-1.0.xsd%22+xmlns%3Ans4%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fwss%2F2004%2F01%2Foasis-200401-wss-wssecurity-secext-1.0.xsd%22+xmlns%3Ans5%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fws-sx%2Fws-trust%2F200802%22%3E%3CRequestSecurityTokenResponse%3E%3CTokenType%3Ehttp%3A%2F%2Fdocs.oasis-open.org%2Fwss%2Foasis-wss-saml-token-profile-1.1%23SAMLV2.0%3C%2FTokenType%3E%3CRequestedSecurityToken%3E%3Csaml2%3AAssertion+xmlns%3Asaml2%3D%22urn%3Aoasis%3Anames%3Atc%3ASAML%3A2.0%3Aassertion%22+xmlns%3Axsd%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema%22+xmlns%3Axsi%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema-instance%22+ID%3D%22_d11b7fa4-3dc2-4b81-a29e-c80cc6e20436%22+IssueInstant%3D%222015-12-18T17%3A45%3A39.933Z%22+Version%3D%222.0%22+xsi%3Atype%3D%22saml2%3AAssertionType%22%3E%3Csaml2%3AIssuer%3ESTS+Realm+A%3C%2Fsaml2%3AIssuer%3E%3Cds%3ASignature+xmlns%3Ads%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23%22%3E%3Cds%3ASignedInfo%3E%3Cds%3ACanonicalizationMethod+Algorithm%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2F10%2Fxml-exc-c14n%23%22%2F%3E%3Cds%3ASignatureMethod+Algorithm%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256%22%2F%3E%3Cds%3AReference+URI%3D%22%23_d11b7fa4-3dc2-4b81-a29e-c80cc6e20436%22%3E%3Cds%3ATransforms%3E%3Cds%3ATransform+Algorithm%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23enveloped-signature%22%2F%3E%3Cds%3ATransform+Algorithm%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2F10%2Fxml-exc-c14n%23%22%3E%3Cec%3AInclusiveNamespaces+xmlns%3Aec%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2F10%2Fxml-exc-c14n%23%22+PrefixList%3D%22xsd%22%2F%3E%3C%2Fds%3ATransform%3E%3C%2Fds%3ATransforms%3E%3Cds%3ADigestMethod+Algorithm%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmlenc%23sha256%22%2F%3E%3Cds%3ADigestValue%3EOB6hSosPWjhA5dxCE%2BF3eFAC4dRu%2FZxFT9XO%2B9tXBAI%3D%3C%2Fds%3ADigestValue%3E%3C%2Fds%3AReference%3E%3C%2Fds%3ASignedInfo%3E%3Cds%3ASignatureValue%3EOAZHDiqlANZXtK0UPfrusUTAf1E9hrPHjUw9kB0sP24RMtxjIfcJ0UFTIb1gBHMqGz%2BbxPJozH7c6O%2F%2F2OYa5V3eRDadQOqnxKvReDh8YjHqs641uhdNqlJl9SogWsm7MPmznmwB5jRLqCaQpTQDfFnjwHXPgxwcASh1i3anfYSpJebnq4ipC3%2Flyuy99xXb1tQoai6hgdRiPs5ragYUPLqE9bIrULj%2FOTbuXY4ikKcNBHltKzAhPJtvaVDzgUkAKRYNBk64te1vRTCYYdMWXjMjA%2FC2obHhIB4zA5eMjxoMPmZHe7ZxVVRiB938S%2FJW%2B4ysJvoVdFX2FTmqRmIKhA%3D%3D%3C%2Fds%3ASignatureValue%3E%3Cds%3AKeyInfo%3E%3Cds%3AX509Data%3E%3Cds%3AX509Certificate%3EMIICwTCCAamgAwIBAgIEINqJ9TANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDEwZSRUFMTUEwHhcN%0D%0AMTUwNjEwMTU0NDE3WhcNMjUwNDE4MTU0NDE3WjARMQ8wDQYDVQQDEwZSRUFMTUEwggEiMA0GCSqG%0D%0ASIb3DQEBAQUAA4IBDwAwggEKAoIBAQCJDSXn2lDR%2BJM%2BAsJarFG3%2FXGH7K%2B9AfAbQIz2IgB9MCpO%0D%0AKVWTUPCvuo1I%2BFp5nEGreuHYLEwgIiam3o%2BC9tvpLgtDDaDkmXjDzkWpk8z6%2Bim72HZ%2FODF93Rqw%0D%0AjIiY5ZCzgDumFyPzdKiGwChThamidy%2Brd6oheSoi6qRVSMMcnwiEUmvkfFvV3izXRqeT5nGQwsin%0D%0Ay9mCEiGx8jkfxP%2B%2BH0RQjVjhOwzfQ7epsR7dTQNf2ZhkBR3o6wKV9QnF2IBWHZpA9EK58rWU9H6j%0D%0AG7b631rYvwsbOUF9HcZ8DI2BFh%2B4p18jDN%2FfnjNGSLr9rYOExpsIiF1cHBK7Tr7WwCmDAgMBAAGj%0D%0AITAfMB0GA1UdDgQWBBRHy0qYoLm9jx%2F1L6r61NznHKun2jANBgkqhkiG9w0BAQsFAAOCAQEAR9rU%0D%0A5Sp1FsOErdvKNFqeaKl0oq6Fuz7BWcGm2kK6%2B1ZbWE8IOv6Vh%2BBlLuOe5hF7aLUbm8UIjhKsmg0M%0D%0AEy5MBwkBZktT1qhQteMuiKgYR7CxayCxO0f125RYvvwntJa5rI7bUrzOqX29VQD1qQ%2FTb%2B08fULT%0D%0AL7oURP%2Bg88Ff99dn3IpO4VZxZdsbl4%2BKZRtqQvPAdXNYjOajJtPzS489%2B%2FDtfWJ6wPm%2F7YZ4did4%0D%0A1fYcrdwyEZ15L0%2F5i931z7sztNickm5WhO40qEVDKN6KrlV2Eyea0%2B933v2Pwe4resTlko9G2T5h%0D%0AdEaSbvht2Q%2FJOMMmT91daeto2oS8HTKhTA%3D%3D%3C%2Fds%3AX509Certificate%3E%3C%2Fds%3AX509Data%3E%3C%2Fds%3AKeyInfo%3E%3C%2Fds%3ASignature%3E%3Csaml2%3ASubject%3E%3Csaml2%3ANameID+Format%3D%22urn%3Aoasis%3Anames%3Atc%3ASAML%3A1.1%3Anameid-format%3Aunspecified%22+NameQualifier%3D%22http%3A%2F%2Fcxf.apache.org%2Fsts%22%3Ealice%3C%2Fsaml2%3ANameID%3E%3Csaml2%3ASubjectConfirmation+Method%3D%22urn%3Aoasis%3Anames%3Atc%3ASAML%3A2.0%3Acm%3Abearer%22%2F%3E%3C%2Fsaml2%3ASubject%3E%3Csaml2%3AConditions+NotBefore%3D%222015-12-18T17%3A45%3A39.890Z%22+NotOnOrAfter%3D%222015-12-18T18%3A45%3A39.890Z%22%3E%3Csaml2%3AAudienceRestriction%3E%3Csaml2%3AAudience%3Eurn%3Aorg%3Aapache%3Acxf%3Afediz%3Afedizhelloworld%3C%2Fsaml2%3AAudience%3E%3C%2Fsaml2%3AAudienceRestriction%3E%3C%2Fsaml2%3AConditions%3E%3Csaml2%3AAttributeStatement%3E%3Csaml2%3AAttribute+Name%3D%22http%3A%2F%2Fschemas.xmlsoap.org%2Fws%2F2005%2F05%2Fidentity%2Fclaims%2Frole%22+NameFormat%3D%22urn%3Aoasis%3Anames%3Atc%3ASAML%3A2.0%3Aattrname-format%3Aunspecified%22%3E%3Csaml2%3AAttributeValue+xsi%3Atype%3D%22xsd%3Astring%22%3EUser%3C%2Fsaml2%3AAttributeValue%3E%3C%2Fsaml2%3AAttribute%3E%3Csaml2%3AAttribute+Name%3D%22http%3A%2F%2Fschemas.xmlsoap.org%2Fws%2F2005%2F05%2Fidentity%2Fclaims%2Fgivenname%22+NameFormat%3D%22urn%3Aoasis%3Anames%3Atc%3ASAML%3A2.0%3Aattrname-format%3Aunspecified%22%3E%3Csaml2%3AAttributeValue+xsi%3Atype%3D%22xsd%3Astring%22%3EAlice%3C%2Fsaml2%3AAttributeValue%3E%3C%2Fsaml2%3AAttribute%3E%3Csaml2%3AAttribute+Name%3D%22http%3A%2F%2Fschemas.xmlsoap.org%2Fws%2F2005%2F05%2Fidentity%2Fclaims%2Fsurname%22+NameFormat%3D%22urn%3Aoasis%3Anames%3Atc%3ASAML%3A2.0%3Aattrname-format%3Aunspecified%22%3E%3Csaml2%3AAttributeValue+xsi%3Atype%3D%22xsd%3Astring%22%3ESmith%3C%2Fsaml2%3AAttributeValue%3E%3C%2Fsaml2%3AAttribute%3E%3Csaml2%3AAttribute+Name%3D%22http%3A%2F%2Fschemas.xmlsoap.org%2Fws%2F2005%2F05%2Fidentity%2Fclaims%2Femailaddress%22+NameFormat%3D%22urn%3Aoasis%3Anames%3Atc%3ASAML%3A2.0%3Aattrname-format%3Aunspecified%22%3E%3Csaml2%3AAttributeValue+xsi%3Atype%3D%22xsd%3Astring%22%3Ealice%40realma.org%3C%2Fsaml2%3AAttributeValue%3E%3C%2Fsaml2%3AAttribute%3E%3C%2Fsaml2%3AAttributeStatement%3E%3C%2Fsaml2%3AAssertion%3E%3C%2FRequestedSecurityToken%3E%3CRequestedAttachedReference%3E%3Cns4%3ASecurityTokenReference+xmlns%3Awsse11%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fwss%2Foasis-wss-wssecurity-secext-1.1.xsd%22+wsse11%3ATokenType%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fwss%2Foasis-wss-saml-token-profile-1.1%23SAMLV2.0%22%3E%3Cns4%3AKeyIdentifier+ValueType%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fwss%2Foasis-wss-saml-token-profile-1.1%23SAMLID%22%3E_d11b7fa4-3dc2-4b81-a29e-c80cc6e20436%3C%2Fns4%3AKeyIdentifier%3E%3C%2Fns4%3ASecurityTokenReference%3E%3C%2FRequestedAttachedReference%3E%3CRequestedUnattachedReference%3E%3Cns4%3ASecurityTokenReference+xmlns%3Awsse11%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fwss%2Foasis-wss-wssecurity-secext-1.1.xsd%22+wsse11%3ATokenType%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fwss%2Foasis-wss-saml-token-profile-1.1%23SAMLV2.0%22%3E%3Cns4%3AKeyIdentifier+ValueType%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fwss%2Foasis-wss-saml-token-profile-1.1%23SAMLID%22%3E_d11b7fa4-3dc2-4b81-a29e-c80cc6e20436%3C%2Fns4%3AKeyIdentifier%3E%3C%2Fns4%3ASecurityTokenReference%3E%3C%2FRequestedUnattachedReference%3E%3Cwsp%3AAppliesTo+xmlns%3Awsp%3D%22http%3A%2F%2Fwww.w3.org%2Fns%2Fws-policy%22+xmlns%3Awst%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fws-sx%2Fws-trust%2F200512%22%3E%3Cwsa%3AEndpointReference+xmlns%3Awsa%3D%22http%3A%2F%2Fwww.w3.org%2F2005%2F08%2Faddressing%22%3E%3Cwsa%3AAddress%3Eurn%3Aorg%3Aapache%3Acxf%3Afediz%3Afedizhelloworld%3C%2Fwsa%3AAddress%3E%3C%2Fwsa%3AEndpointReference%3E%3C%2Fwsp%3AAppliesTo%3E%3CLifetime%3E%3Cns3%3ACreated%3E2015-12-18T17%3A45%3A39.890Z%3C%2Fns3%3ACreated%3E%3Cns3%3AExpires%3E2015-12-18T18%3A45%3A39.890Z%3C%2Fns3%3AExpires%3E%3C%2FLifetime%3E%3C%2FRequestSecurityTokenResponse%3E%3C%2FRequestSecurityTokenResponseCollection%3E
&wctx=b9220a8a-5802-41a2-9128-a2ba649a72bc
&wtrealm=urn%3Aorg%3Aapache%3Acxf%3Afediz%3Afedizhelloworld
The final wresult which will be sent to the demo app looks like this:
<RequestSecurityTokenResponseCollection xmlns="http://docs.oasis-open.org/ws-sx/ws-trust/200512" xmlns:ns2="http://www.w3.org/2005/08/addressing" xmlns:ns3="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:ns4="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:ns5="http://docs.oasis-open.org/ws-sx/ws-trust/200802">
<RequestSecurityTokenResponse>
<TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</TokenType>
<RequestedSecurityToken>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ID="_d11b7fa4-3dc2-4b81-a29e-c80cc6e20436" IssueInstant="2015-12-18T17:45:39.933Z" Version="2.0" xsi:type="saml2:AssertionType">
<saml2:Issuer>STS Realm A</saml2:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#_d11b7fa4-3dc2-4b81-a29e-c80cc6e20436">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xsd"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>OB6hSosPWjhA5dxCE+F3eFAC4dRu/ZxFT9XO+9tXBAI=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>OAZHDiqlANZXtK0UPfrusUTAf1E9hrPHjUw9kB0sP24RMtxjIfcJ0UFTIb1gBHMqGz+bxPJozH7c6O//2OYa5V3eRDadQOqnxKvReDh8YjHqs641uhdNqlJl9SogWsm7MPmznmwB5jRLqCaQpTQDfFnjwHXPgxwcASh1i3anfYSpJebnq4ipC3/lyuy99xXb1tQoai6hgdRiPs5ragYUPLqE9bIrULj/OTbuXY4ikKcNBHltKzAhPJtvaVDzgUkAKRYNBk64te1vRTCYYdMWXjMjA/C2obHhIB4zA5eMjxoMPmZHe7ZxVVRiB938S/JW+4ysJvoVdFX2FTmqRmIKhA==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIICwTCCAamgAwIBAgIEINqJ9TANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDEwZSRUFMTUEwHhcN
MTUwNjEwMTU0NDE3WhcNMjUwNDE4MTU0NDE3WjARMQ8wDQYDVQQDEwZSRUFMTUEwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCJDSXn2lDR+JM+AsJarFG3/XGH7K+9AfAbQIz2IgB9MCpO
KVWTUPCvuo1I+Fp5nEGreuHYLEwgIiam3o+C9tvpLgtDDaDkmXjDzkWpk8z6+im72HZ/ODF93Rqw
jIiY5ZCzgDumFyPzdKiGwChThamidy+rd6oheSoi6qRVSMMcnwiEUmvkfFvV3izXRqeT5nGQwsin
y9mCEiGx8jkfxP++H0RQjVjhOwzfQ7epsR7dTQNf2ZhkBR3o6wKV9QnF2IBWHZpA9EK58rWU9H6j
G7b631rYvwsbOUF9HcZ8DI2BFh+4p18jDN/fnjNGSLr9rYOExpsIiF1cHBK7Tr7WwCmDAgMBAAGj
ITAfMB0GA1UdDgQWBBRHy0qYoLm9jx/1L6r61NznHKun2jANBgkqhkiG9w0BAQsFAAOCAQEAR9rU
5Sp1FsOErdvKNFqeaKl0oq6Fuz7BWcGm2kK6+1ZbWE8IOv6Vh+BlLuOe5hF7aLUbm8UIjhKsmg0M
Ey5MBwkBZktT1qhQteMuiKgYR7CxayCxO0f125RYvvwntJa5rI7bUrzOqX29VQD1qQ/Tb+08fULT
L7oURP+g88Ff99dn3IpO4VZxZdsbl4+KZRtqQvPAdXNYjOajJtPzS489+/DtfWJ6wPm/7YZ4did4
1fYcrdwyEZ15L0/5i931z7sztNickm5WhO40qEVDKN6KrlV2Eyea0+933v2Pwe4resTlko9G2T5h
dEaSbvht2Q/JOMMmT91daeto2oS8HTKhTA==</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2:Subject>
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" NameQualifier="http://cxf.apache.org/sts">alice</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"/>
</saml2:Subject>
<saml2:Conditions NotBefore="2015-12-18T17:45:39.890Z" NotOnOrAfter="2015-12-18T18:45:39.890Z">
<saml2:AudienceRestriction>
<saml2:Audience>urn:org:apache:cxf:fediz:fedizhelloworld</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AttributeStatement>
<saml2:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue xsi:type="xsd:string">User</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue xsi:type="xsd:string">Alice</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue xsi:type="xsd:string">Smith</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue xsi:type="xsd:string">alice@realma.org</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
</saml2:Assertion>
</RequestedSecurityToken>
<RequestedAttachedReference>
<ns4:SecurityTokenReference xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" wsse11:TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0">
<ns4:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID">_d11b7fa4-3dc2-4b81-a29e-c80cc6e20436</ns4:KeyIdentifier>
</ns4:SecurityTokenReference>
</RequestedAttachedReference>
<RequestedUnattachedReference>
<ns4:SecurityTokenReference xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" wsse11:TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0">
<ns4:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID">_d11b7fa4-3dc2-4b81-a29e-c80cc6e20436</ns4:KeyIdentifier>
</ns4:SecurityTokenReference>
</RequestedUnattachedReference>
<wsp:AppliesTo xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Address>urn:org:apache:cxf:fediz:fedizhelloworld</wsa:Address>
</wsa:EndpointReference>
</wsp:AppliesTo>
<Lifetime>
<ns3:Created>2015-12-18T17:45:39.890Z</ns3:Created>
<ns3:Expires>2015-12-18T18:45:39.890Z</ns3:Expires>
</Lifetime>
</RequestSecurityTokenResponse>
</RequestSecurityTokenResponseCollection>

Categories: Jan Bernhardt

Liferay Portal Integration with Fediz OpenID Connect

Jan Bernhardt - Thu, 12/17/2015 - 11:24
I was given the task to provide a security solution to enable SSO in a Liferay portal based on OpenID Connect with the Apache Fediz OIDC Service. In this post I'll explain how to get this done.

You will need Apache Fediz version 1.3.0 or higher, if you want to setup this use case by yourselfInstall Liferay Portal with Fediz PluginFirst download and extract Liferay bundled with Tomcat. (I used liferay-portal-6.2-ce-ga5)

Enable HTTPs port in liferay-portal-6.2-ce-ga5/tomcat-7.0.62/conf/server.xml
<Server port="8005" shutdown="SHUTDOWN">

     . . .

    <Service name="Catalina">

         . . .

        <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
             maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
             keystoreFile="idp-ssl-key.jks"
             keystorePass="tompass"
             clientAuth="false"
             sslProtocol="TLS" />

    </Service>
</Server>
I reused the idp-ssl-key.jks file from the IDP Tomcat to keep things simple. Of course you can also use a different keystore. Your keystore should be stored in your tomcat root folder liferay-portal-6.2-ce-ga5/tomcat-7.0.62/.

Now you can start Liferay for a first setup. Simply execute liferay-portal-6.2-ce-ga5/tomcat-7.0.62/bin/startup.sh

After Tomcat startup is complete you can invoke the server page at https://localhost:8443/.

I continued with the default values (except for the Email address) and simply clicked "Finish Configuration". After that you have to wait until Liferay installation is complete. Next you will see the license confirmation page, which you need to confirm. After that you can set your password reminder as well as the administration password.

The OpenID Connect Extension which we will install in the following section requires a user group UnityUser which will be applied for all new users when then login the very first time to the portal. Therefore we must create this user group first under control panel -> Users -> User Groups -> Add


Your Liferay Portal is now up and running so lets continue next on enabling OpenID Connect for your portal.
Register Liferay Portal at OIDC ProviderAfter starting your OIDC Service, you can register the Liferay Portal under the following URL: https://localhost:9443/fediz-oidc/clients/register.

You will need the client Identifier as well as the Client Secret in the following section.
Install OpenIdConnect Extension for LiferayYou will need the OpenIdConnectLiferay extension, which you can clone from Github. Further information on installing this extension can be found at the authors webpage.

You'll need to update the configuration within it.infn.ct.security.liferay.openidconnect.utils.Authenticator

public Authenticator(State state) {
    authC = new ClientSecretBasic(new ClientID("hLiSIY6b1X_0Jg"), new Secret("llPySiI1aEwyIgsnyBu6aA"));
    this.state = state;
    try {
        callback = new URI("https://localhost:8443/c/portal/login");
oauthS = new URI("https://localhost:9443/fediz-oidc/idp/authorize");
        tokenS = new URI("https://localhost:9443/fediz-oidc/oauth2/token");
        userS = new URI("https://localhost:9443/fediz-oidc/users/userinfo");
        tokenCertSign = new URI("https://localhost:9443/fediz-oidc/jwk/keys");
        issuer = "accounts.fediz.com";
        aud = "hLiSIY6b1X_0Jg";
    } catch (URISyntaxException ex) {
        _log.error(ex);
    }
}

Now you can build and deploy this extension.
$ mvn clean install
You will find a jar file with all extensions at OpenIdConnectLiferay/target/OpenIdConnectLiferay-0.1-jar-with-dependencies.jar. You need to copy this jar file to liferay-portal-6.2-ce-ga5/tomcat-7.0.62/lib/ext/.

Next you need to create (or modify if it already exists) the following file liferay-portal-6.2-ce-ga5/tomcat-7.0.62/webapps/ROOT/WEB-INF/classes/portal-ext.properties to activate the OpenID Connect Login handler:
auto.login.hooks=\
it.infn.ct.security.liferay.openidconnect.OpenIdConnectAutoLogin,\
com.liferay.portal.security.auth.CASAutoLogin,\
com.liferay.portal.security.auth.FacebookAutoLogin,\
com.liferay.portal.security.auth.NtlmAutoLogin,\
com.liferay.portal.security.auth.OpenIdAutoLogin,\
com.liferay.portal.security.auth.OpenSSOAutoLogin,\
com.liferay.portal.security.auth.RememberMeAutoLogin,\
com.liferay.portal.security.auth.SiteMinderAutoLogin

Now you should restart your tomcat and after that you can invoke the following login URL: https://localhost:8443/c/portal/login?openIdLogin=true. This time you should get redirected to Fediz-IDP for user authentication (login). After successful login you should be able to see your portal again with an active user.

For debugging purposes is can also be helpful to increase the log level by adding the following line at liferay-portal-6.2-ce-ga5/tomcat-7.0.62/conf/logging.properties
it.infn.ct.security.liferay.openidconnect.level = FINE
Test your Setup: Login with OpenID ConnectNow you can validate if your setup is working as expected. Open the following URL in your browser:
https://localhost:8443/c/portal/login?openIdLogin=true

Make sure to logout first, if you are still logged in at your portal.
You should get redirected to the Fediz IDP Login page and after login (bob:bob) you should get redirected back to your Liferay portal.
When you login the very first time, you should see a screen to confirm the "Terms of Use". After that you will be asked to enter a new password. This password can be used to login without SSO / OpenID Connect so you should choose a complex password. As long as you use SSO however you will never be ask again to enter this password. Same applies to the password reminder.
Once that is done, you will see the start screen of the Liferay Portal.
Now you can logout and login again with the above URL. This time you will login directly without any additional steps/questions.

You have been successful!
Categories: Jan Bernhardt

Fediz with OpenID Connect Support and WS-Federation Bridge (2/2)

Jan Bernhardt - Mon, 12/14/2015 - 14:46
Setup a DemonstratorIn this article I'll explain how to setup a demonstrator for the use case described in my previous post.
Setup Fediz IDP & OIDCFirst you need to setup the Fediz IDP as usual. To get the OIDC Service working you also need to do the following:
  1. Install Fediz Plugin for the Fediz IDP Server (usually you would do this for the client application only)
    For the fediz_config.xml you can use the sample provided with the OIDC Service.
  2. Download or build the OIDC service and then deploy the fediz-oidc.war file to your webapps folder (same place where you deployed STS & IDP)
Register an OpenID Connect Client From the perspective of OpenID Connect the Web Portal takes the role of a OIDC client. So the client must be registered up front. After starting the OIDC service you can invoke the following URL in your browser:

https://localhost:9443/fediz-oidc/clients/register
For Client Name and Client Description you can enter any human readable and meaningful value related to your service.
OIDC supports Confidential as well as Public as a Client Type. If your Client is a Public client (for example your client is java code running inside the browser of a user), no client secret will be generated, since the secret could not be protected anyway. The normal use case however should be Confidential.
Your redirect URI will be the final URL from which the OIDC service will redirect the user with the generated code. Normally this will be a OIDC Client service from your app consuming the code value and exchanging it for an access and ID token.
If your application (OIDC Client) is  bound to a fix Home Realm (all users from this app will always login at the same home realm), then you can select this HomeRealm here. In this case users will not see a home realm selection screen but will be redirected to the correct home realm IDP directly.

After submitting you client information you will see the generated client_id and client_secret. These values need to be set at the web portal.
Understanding the Web PortalYour web portal can by any kind of (java) web application. To enable OpenID Connect support at my web application I need to add a Relaying Party (RP) OIDC Handler at a URL of my choice.
<!--
OIDC RP endpoint: authenticates a user by redirecting a user to OIDC Provider, and redirects the user
to the initial application form once the authentication is done
-->
<jaxrs:server id="oidcRpServer" address="/oidc">
<jaxrs:serviceBeans>
<bean class="org.apache.cxf.rs.security.oidc.rp.OidcRpAuthenticationService">
<!-- This state manager is shared between this RP endpoint and the oidcRpFilter which protects
the application endpoint, the RP endpoint sets an OIDC context on it and the filter checks
the context is available -->
<property name="clientTokenContextManager" ref="stateManager" />
<!-- Where to redirect to once the authentication is complete -->
<property name="defaultLocation" value="/app/service/start" />
</bean>
</jaxrs:serviceBeans>

<jaxrs:providers>
<!-- the filter which does the actual work for obtaining an OIDC context.
It redirect to the OIDC Provider, exchanges an authorization code for access token,
extracts OIDC IdToken and makes it all available as OidcCientTokenContext
-->
<bean id="rpOidcRequestFilter" class="org.apache.cxf.rs.security.oidc.rp.OidcClientCodeRequestFilter">
<property name="clientCodeStateManager">
<!-- This state manager creates an OAuth2 'state' parameter and saves it in the HTTP session -->
<bean class="org.apache.cxf.rs.security.oauth2.client.MemoryClientCodeStateManager">
<property name="generateNonce" value="true"/>
</bean>
</property>
<property name="scopes" value="openid refreshToken" />
<property name="accessTokenServiceClient" ref="atServiceClient" />
<property name="idTokenReader">
<bean class="org.apache.cxf.rs.security.oidc.rp.IdTokenReader">
<!-- disable it if the local key store or the client secret is used to validate ID Tokens -->
<property name="jwkSetClient" ref="jwkSetClient"/>
<property name="issuerId" value="accounts.fediz.com"/>
</bean>
</property>
<property name="consumer" ref="consumer" />
<property name="authorizationServiceUri" value="https://localhost:9443/fediz-oidc/idp/authorize" />
<property name="startUri" value="rp" />
<property name="completeUri" value="/" />
</bean>

<!-- JAX-RS provider that makes OidcClientTokenContext available as JAX-RS @Context -->
<ref bean="clientTokenContextProvider" />
</jaxrs:providers>
</jaxrs:server>
 
<!-- The state manager shared between the RP and application endpoints -->
<bean id="stateManager" class="org.apache.cxf.rs.security.oauth2.client.MemoryClientTokenContextManager"/>
<!-- WebClient for requesting an OAuth2 Access token.
rpOidcRequestFilter uses it to exchange a code for a token -->

<jaxrsclient:client id="atServiceClient" threadSafe="true"
address="https://localhost:9443/fediz-oidc/oauth2/token"
serviceClass="org.apache.cxf.jaxrs.client.WebClient">
<jaxrsclient:headers>
<entry key="Accept" value="application/json"/>
</jaxrsclient:headers>
<jaxrsclient:providers>
<bean class="org.apache.cxf.jaxrs.provider.FormEncodingProvider">
<property name="expectedEncoded" value="true"/>
</bean>
</jaxrsclient:providers>
</jaxrsclient:client>

<!-- Client id and secret allocated by OIDC ClientRegistrationService -->
<bean id="consumer" class="org.apache.cxf.rs.security.oauth2.client.Consumer">
<property name="clientId" value="-7TdKEwzkf5BSQ"/>
<property name="clientSecret" value="q6ys7349uXMIgOu1kXNFTQ"/>
</bean>
 
<!-- JAX-RS provider that makes OidcClientTokenContext available as JAX-RS @Context -->
<bean id="clientTokenContextProvider" class="org.apache.cxf.rs.security.oauth2.client.ClientTokenContextProvider"/>

<!-- disable it if the local key store or the client secret is used to validate ID Tokens -->
<jaxrsclient:client id="jwkSetClient" threadSafe="true"
address="https://localhost:9443/fediz-oidc/jwk/keys"
serviceClass="org.apache.cxf.jaxrs.client.WebClient">
<jaxrsclient:headers>
<entry key="Accept" value="application/json"/>
</jaxrsclient:headers>
<jaxrsclient:providers>
<bean class="org.apache.cxf.rs.security.jose.jaxrs.JsonWebKeysProvider"/>
</jaxrsclient:providers>
</jaxrsclient:client>

For being able to use the access token when invoking a REST Backend-Service you must add the access token as an Authorization Header within your Request. For this purpose you must first create a JAX-RS Client and also inject the OIDC-Context to your application.
<jaxrsclient:client id="backendServiceClient" threadSafe="true"
   address="https://localhost:8082/backendService" serviceClass="org.apache.cxf.jaxrs.client.WebClient">
   <jaxrsclient:headers>
       <entry key="Accept" value="application/json"/>
   </jaxrsclient:headers>
   <jaxrsclient:providers>
      <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider"/>
   </jaxrsclient:providers>
</jaxrsclient:client>
Within your code you need to inject the OidcClientTokenContext, for example via @Context annotation:
@Context
private OidcClientTokenContext oidcContext;
Within your method when just before invoking the REST Service you must add the authorization header as follows:
ClientAccessToken accessToken = oidcContext.getToken();
backendServiceClient.authorization(accessToken);
Understanding the REST ServiceLets take a DemoService as an example to explain the OIDC/Auth2 Integration at the backend REST Service.First lets take a loog a the REST Interface. You will note an annotation @Scopes which will require that the used access token was provided for the scope userinfo. The other method will also require an access token, but without any scope enforcement.
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

import org.apache.cxf.rs.security.oauth2.filters.Scopes;

@Path("/")
public class DemoService {
   
    @GET
    @Path("/public")
    public String getGreeting() {
        return "Hello World!";
    }
   
    @GET
    @Path("/secure")
    @Scopes("userinfo")
    public String getPersonalGreeting(@QueryParam("name") String name) {
        return "Hello " + name + "!";
    }
}

Within your Spring configuration you need to add two filters. The OAuthRequestFilter is needed to ensure that the provided access token is still valid, and the OAuthScopesFilter checks that the required scope for invoking a certain method will matches with the scope of the access token.
<bean id="demoService" class="org.apache.service.DemoService"/>

<jaxrs:server id="demoService" address="/greeting">
    <jaxrs:serviceBeans>
        <ref bean="demoService"/>
    </jaxrs:serviceBeans>
    <jaxrs:providers>
        <bean class="org.apache.cxf.rs.security.oauth2.filters.OAuthRequestFilter">
         <property name="tokenValidator">
<bean class="org.apache.cxf.rs.security.oauth2.filters.AccessTokenValidatorClient">
         <property name="tokenValidatorClient" ref="tokenValidatorClient"/>
     </bean>
         </property>
  </bean>
    <bean class="org.apache.cxf.rs.security.oauth2.filters.OAuthScopesFilter">
        <property name="securedObject" ref="demoService"/>
    </bean>
  </jaxrs:providers>
</jaxrs:server>

<jaxrsclient:client id="tokenValidatorClient"
address="https://localhost:9443/fediz-oidc/oauth2/validate"
serviceClass="org.apache.cxf.jaxrs.client.WebClient">
<jaxrsclient:headers>
<entry key="Content-Type" value="application/x-www-form-urlencoded"/>
<entry key="Accept" value="application/xml"/>
</jaxrsclient:headers>
<jaxrsclient:providers>
<bean class="org.apache.cxf.jaxrs.provider.FormEncodingProvider">
<property name="expectedEncoded" value="true"/>
</bean>
</jaxrsclient:providers>
</jaxrsclient:client>
Since validation is not yet standardized  the tokenValidatorClient communicates with the OIDC service in a proprietary manner.

Categories: Jan Bernhardt

Fediz with OpenID Connect Support and WS-Federation Bridge (1/2)

Jan Bernhardt - Wed, 12/09/2015 - 16:53
I'm currently engaged for a big company to provide a solution that allows this company to offer various (REST) services to their partners while these services are hosted and maintained by the company but users can login to these services with accounts managed within their own partner network.

This solution should work for Web-Portals, Mobile Apps & Desktop Applications.

First I was skeptical if it will be possible to find one solution fitting all theses different use cases. But I think I actually did find a very interesting solution. In this post I'll explain the overall architecture of this solution. In my next posts I'll tell you how to get a Liferay Web-Portal integrated as well as a mobile App based on Android.

WS-Federation normally uses SAML Tokens for user authentication. This is fine for container based security solutions, when the user wants to login to a web-portal. But modern web applications (e.g. AJAX based) tend to be executed primarily in the Browser, invoking REST backend services directly from within the Browser.
Handling XML based tokens (incl. XML signature validation) is just a too heavy burden for this type of applications. Also handling lifetime issues with SAML Token could require a Token exchange with an STS. But an STS only provides a SOAP interface according to WS-Trust. It is not feasible for a AJAX Web Application to handle SOAP communication including XML security. Browser based applications should be light-weight and thus they prefer talking to REST services.

Token Types & Token Handling JSON Web Tokens (JWT) are similar to SAML tokens but instead of being XML based they are provided in a JSON format. Since JSON is the preferred document format for REST services, they fit much better to a REST Service compared to a XML based SAML Token.

One step closer to the solution could be to provide a STS that can issue JWT tokens as well as SAML tokens. This could help to exchange SAML token to JWT token and vice versa in cases when you need both. SAML for SOAP services and JWT for REST services. Colm O hEigeartaigh has already done some improvements to the CXF STS to support JWT tokens at the STS.

Instead of requesting a SAML Token with the following TokenType http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0 you can now also request a JWT token with this TokenType urn:ietf:params:oauth:token-type:jwt.

This way you can request or even exchange JWT tokens simply by setting the expected TokenType value. When sending a SAML or JWT token OnBehalfOf your token request you can exchange one format for the other.
What is currently missing to bridge both token types for SOAP and REST scenarios would be a REST interface for the STS. This would make it a lot easier for REST clients to interact with an STS. Since there are no standards for a STS REST API, I'll design a REST interface by myself discuss it with the CXF community and then add it to the STS soon.

OpenID ConnectI would see OpenID Connect as the successor standard for WS-Federation which was the successor standard of the SAML Web-Profile. You can see that the OIDC sequence flow is still similar to the prior protocols but that it also learned and improved a lot from the older standards.

OIDC is also based on the OAuth2 standard and thus inherits also all benefits and drawbacks of this protocol.

Many big internet companies support OpenID Connect like Google, Facebook, Twitter, etc..
OpenID Connect is related but not equal to OpenID on which some of the bigger companies dropped already the support for (like Google).
Simple Sequence FlowOpenID connect is based on OAuth2 and thus provides several sequence flows. Which one you will choose will depend on your circumstances. In this blog I'll focus on the authorization code flow only.

(1) The user invokes the WebPortal (same would apply if the user invokes a REST Service).
GET https://demo.portal.com/webPortal/index.html HTTP/1.1
Host: demo.portal.comto be continued...
(2) Since there is no existing session with the user, the server response with a redirect to the OIDC Server (line breaks added to improve readability).
HTTP/1.1 303 See Other
Location: https://your.oidc-server.com/idp/login
?client_id=Ro2hJVtj94oWLw
&scope=openid
&response_type=code
&redirect_uri=https%3A%2F%2Fdemo.portal.com%2FwebPortal%2Foidc
&state=a8a4ee9e8061a34f93539635ce02e32
&nonce=1d5c428ffbff3eed95721339e67c56e8c2aa4add6bb493e436249578c81f88
The user will see a login screen for authentication.
(3) After successful login the user will be redirected back to the provided redirect_uri with an authorization code:
HTTP/1.1 303 See Other
Set-Cookie: JSESSIONID=55638DC5FF717DD730B72978B70F088E; Path=/idp/; Secure; HttpOnly
Cache-Control: private
Expires: Thu, 01 Jan 1970 01:00:00 CET
Date: Thu, 19 Nov 2015 13:39:08 GMT
Location: https://demo.portal.com/webPortal/oidc
?state=a8a4ee9e8061a34f93539635ce02e32
&code=a1a822cd99da976f47c8a7218ae212
(4) This code can now be used by the service provider (web portal) to get a JWT token. For this reason the service provider needs to authenticate against the token endpoint with its client_id & client_secret within the Authorization header, as well as the code value and redirect_uri.
POST https://your.oidc-server.com/idp/oauth2/token
Host: your.oidc-server.com
Authorization: Basic Um8yaEpWdGo5NG9XTHc6RUFpemlWUU5PWVpmaHN5WGlSNmpxUQ==

grant_type=authorization_code
&code=a1a822cd99da976f47c8a7218ae212
&redirect_uri=https%3A%2F%2Fdemo.portal.com%2FwebPortal%2Foidc
As a result the token endpoint of the OIDC IDP will return the JWT Token as well as an access code. The access code will not be needed in this first scenario but is just part of the usual Oauth2 flow.
HTTP/1.1 200 OK
Content-Type: application/json

{
"access_token": "a8de6a544738c9e9036318ee78dfe7",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "openid",
"id_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJib2IiLCJhdWQiOiJVVUY5RmRzNjdubnA2QSIsImlhdCI6MTQ0OTY3NDMyNywiZXhwIjoxNDQ5NzM0MzI3LCJnaXZlbl9uYW1lIjoiQm9iIiwiZW1haWwiOiJib2J3aW5kc29yQHJlYWxtYS5vcmciLCJmYW1pbHlfbmFtZSI6IldpbmRzb3IiLCJuYW1lIjoiQm9iIFdpbmRzb3IiLCJub25jZSI6IjFkNWM0MjhmZmJmZjNlZWQ5NTcyMTMzOWU2N2M1NmU4YzJhYTRhZGQ2YmI0OTNlNDM2MjQ5NTc4YzgxZjg4IiwiaXNzIjoiYWNjb3VudHMuZmVkaXouY29tIiwiYXRfaGFzaCI6InZvc1h4a1lhcW1aYmJiTWlVdWdYRUEifQ.VQB4QfI1nrka5cfgq8aOGyT0iv3EEE7BBETIzQHbee1t9BDr8wPNV55pGY1YqU6F5C9KIkWiIGLz8MBlKwQVfU7FfzXqm4gEF2zbq4i_LyL-f_RW38-id4VmfF3n6ybWDqdmLLXagFL2UurTdIuGWxbZVW_bgnuIc5dJfnQ_b2wi9hxoL-1u4PPufDLfTLBYRtP5zaedR01me9T5i6PCn2jZSdvfd9304Jf6MOf98Cvv-faeZ87ilUrd5k3q4tQl6dIL3IefPBTfbR8Ni69viD29A-PvtKLquQcGp6p3NEXnwOYF7c72ZsjuZI2pcItoeBeo2Whz9Ni21vfWsd3Iaw"
}
The id_token contains three values of interest base64 encoded and separated by a dot '.':
eyJhbGciOiJSUzI1NiJ9

eyJzdWIiOiJib2IiLCJhdWQiOiJVVUY5RmRzNjdubnA2QSIsImlhdCI6MTQ0OTY3NDMyNywiZXhwIjoxNDQ5NzM0MzI3LCJnaXZlbl9uYW1lIjoiQm9iIiwiZW1haWwiOiJib2J3aW5kc29yQHJlYWxtYS5vcmciLCJmYW1pbHlfbmFtZSI6IldpbmRzb3IiLCJuYW1lIjoiQm9iIFdpbmRzb3IiLCJub25jZSI6IjFkNWM0MjhmZmJmZjNlZWQ5NTcyMTMzOWU2N2M1NmU4YzJhYTRhZGQ2YmI0OTNlNDM2MjQ5NTc4YzgxZjg4IiwiaXNzIjoiYWNjb3VudHMuZmVkaXouY29tIiwiYXRfaGFzaCI6InZvc1h4a1lhcW1aYmJiTWlVdWdYRUEifQ

VQB4QfI1nrka5cfgq8aOGyT0iv3EEE7BBETIzQHbee1t9BDr8wPNV55pGY1YqU6F5C9KIkWiIGLz8MBlKwQVfU7FfzXqm4gEF2zbq4i_LyL-f_RW38-id4VmfF3n6ybWDqdmLLXagFL2UurTdIuGWxbZVW_bgnuIc5dJfnQ_b2wi9hxoL-1u4PPufDLfTLBYRtP5zaedR01me9T5i6PCn2jZSdvfd9304Jf6MOf98Cvv-faeZ87ilUrd5k3q4tQl6dIL3IefPBTfbR8Ni69viD29A-PvtKLquQcGp6p3NEXnwOYF7c72ZsjuZI2pcItoeBeo2Whz9Ni21vfWsd3Iaw
After base64 decoding the first value will tell us which algorithm has been used to secure the ID token:
{"alg":"RS256"}
And the second value will contain the actual JWT token:
{
"sub": "bob",
"aud": "UUF9Fds67nnp6A",
"iat": 1449674327,
"exp": 1449734327,
"given_name": "Bob",
"email": "bobwindsor@realma.org",
"family_name": "Windsor",
"name": "Bob Windsor",
"nonce": "1d5c428ffbff3eed95721339e67c56e8c2aa4add6bb493e436249578c81f88",
"iss": "accounts.fediz.com",
"at_hash": "vosXxkYaqmZbbbMiUugXEA"
}
The third parameter will contain the digital signature (binary value) thus I cannot display it here.

After consuming the authorization code the user will be redirected back to the initially requested resource
HTTP/1.1 303 See Other
Location: https://demo.portal.com/webPortal/index.html

OpenID Connect with WS-Federation LoginNow after understanding the basic OpenID Connect flow lets extend this scenario by performing the login not directly at the OIDC service but instead using the Fediz-Plugin at the OIDC Service to redirect the user according to WS-Federation to the Fediz-IDP for user authentication. After successful login at the Fediz-IDP the user will be send back to the OIDC with a SAML token. This token can then be mapped to a JWT token for the OpenID connect login process.


(1) In the first step the user invokes the web portal.
(2) Since now existing session exists the user will be redirected to the OIDC Service according to OpenID Connect.
(3) An Apache Fediz Plugin is active on the OIDC Server. Since now previous session exists the Fediz Plugin will redirect the user to the RP-IDP according to WS-Federation.
(4) The user will see a login screen and will be redirected back to the OIDC server after successful authentication with a SAML token.
(5) The Fediz Plugin will store the SAML Token. OIDC will provide the requested code from step (2).
(6) The Web Portal can now exchange this code according to OAuth2 to get the JWT Token (transformation of the SAML token), as well as an access token to invoke another backend service.
(7) The REST Service will be invoked with the access token received in the previous step
GET https://my.services.com/backend/service
Host: my.services.com
Authorization: Bearer a8de6a544738c9e9036318ee78dfe7
(8) The REST Service will send the access token to the OIDC to ensure that this code is valid. (Unfortunately it is not defined within the standard how this validation should happen)

In my second part of this post, I'll explain how to setup a demonstrator for the above described use case.

Federated SSO with WS-Federation & OpenID ConnectAfter understanding OpenID Connect and WS-Federation Login I'll extend this scenario by one more degree of complexity thus providing us the flexibility which we discusses at the beginning to provide a SSO solution not just within one company but for multiple partners at the same time.

(1) A user from a partner company invokes the web portal.
(2) Since now existing session exists the user will be redirected to the OIDC Service according to OpenID Connect.
(3) An Apache Fediz Plugin is active on the OIDC Server. Since now previous session exists the Fediz Plugin will redirect the user to the RP-IDP according to WS-Federation.
(4) Since no existing session exists at the RP-IDP, the RP-IDP will perform a Home-Realm discovery and after that redirects the user to its own Requestor IDP (more details about this in the next section).
(5) After successful login the Requestor IDP will issue a SAML Token for the user and redirect the user back to the RP-IDP.
(6) The RP-IDP will to do a Claims or Identity Mapping and after that issue a new SAML token applicable for the OIDC Service and redirects the user back to the OIDC service.
(7) The Fediz Plugin at the OIDC service will store the SAML Token and OIDC will provide the requested code from step (2).
(8) The Web Portal can now exchange this code according to OAuth2 to get the JWT Token (transformation of the SAML token), as well as an access token to invoke a backend service.
(9) The REST Service will be invoked with the access token received in the step (8).
(10) The REST Service will send the access token to the OIDC to ensure that this code is valid. (Unfortunately it is not defined within the standard how this validation should happen)
Home Realm DiscoveryIf your web portal shall be used by users from multiple realms (e.g. partner networks), you need to find a way to discover the home realm of each user. The OpenID Connect Standard provides a parameter login_hint for this purpose whereas WS-Federation Standard offers a whr parameter for this purpose.

There are several ways to do a home realm discovery:
  1. Dedicated URLs
    You can provide different URLs for each user group. This can be done by adding the login_hint parameter directly to the URL which the user is invoking (e.g. link within a different portal which the user usually access first). Also very famous is the usage of different domain names with a reverse proxy in place which adds the login_hint / whr parameter.
  2. E-Mail Address
    If there is just a single page which will be used by all user groups it is also a good choice to ask the user for his/her E-Mail address and then use this as the  the login_hint.The OIDC service could use the domain name of this E-Mail Address to set it as the whr parameter for home realm discovery at the RP-IDP. The RP-IDP would need a mapping table of domain names and Requestor IDP URLs to send the user to its home IDP.
    One disadvantage of this solution is that the user will most likely be required to enter his/her E-Mail address twice. First at the portal to initiate the home realm discovery and later for the login at the Requestor IDP. This is because WS-Federation does not provide a felxible login_hint but instead only a more static whr parameter which will be the same value for all users within one group. You can improve the user experience if you use cookies to remember the selected home realm of a user until a user initiated logout takes place.
  3. IP Range
    IP ranges can also be used for home realm discovery but are usually not a good choice because users will not just login from a company network with a static IP but also from mobile devices with a dynamic IP range.
  4. Miscellaneous
    Any other way to securely identify the home realm of a user would also be acceptable, but will usually require custom development efforts to the services.
Categories: Jan Bernhardt

Javascript Object Signing and Encryption (JOSE) support in Apache CXF - part III

Colm O hEigeartaigh - Mon, 12/07/2015 - 18:03
This is the third article in a series of posts on support for Javascript Object Signing and Encryption (JOSE) in Apache CXF. The previous article described how to encrypt content using the JSON Web Encryption specification. This post covers support for JSON Web Tokens (JWT) in Apache CXF. The JWT spec is not strictly part of the JOSE specification set, but it makes sense to cover it in this series of posts, as it is a natural extension of the JOSE specs to convey claims.

1) Test Cases:

As before, let's start by looking at some practical unit tests on github:
  • cxf-jaxrs-jose: This project contains a number of tests that show how to use the JSON Security functionality in Apache CXF to sign and encrypt JSON payloads to/from a JAX-RS service.
These tests mostly follow the same basic format. The web service configuration defines a number of endpoints that map to the same web service implementation (a simple DoubleItService, which allows a user to POST a number and receive the doubled amount, where both the request and response are encoded via JSON). The client test code first constructs a JWT Token and then includes it in the message payload by adding a specific provider. The JWT Token is then processed by a provider on the receiving side. We will cover the individual tests in more detail below.

2) Constructing JWT Tokens

Apache CXF provides an easy to use API to create JWT Tokens. Let's look at how this is done in one of the tests - the JWTAuthenticationTest. The tests construct a JwtClaims Object, which has convenient set/get methods for the standard JWT Claims. For example:


The JwtClaims Object can be passed through to the constructor of a JwtToken Object. To serialize the JwtToken in the request simply add the JwtAuthenticationClientFilter to the client provider list, and specify the JwtToken Object as a message property under "jwt.token". Alternatively, the JwtClaims Object can be passed without having to construct a JwtToken via the property "jwt.claims". On the receiving side, a JWTToken can be processed by the JwtAuthenticationFilter provider.

3) Authentication and Authorization using signed JWT Tokens

By default, the JwtAuthenticationClientFilter signs the JWT Token. The signature configuration is the exact same as that used for JWS as covered in the first article. On the receiving side, the JwtAuthenticationFilter will set up a security context for the authenticated client, assuming that a public key signature algorithm was used to sign the token. The "sub" (Subject) claim from the token gets mapped to the principal of the security context.

As the JWT Token can convey arbitrary claims, it can be used for RBAC authorization. This is demonstrated in the JWTAuthorizationTest. A role called "boss" is inserted into the token. On the receiving side, the JwtAuthenticationFilter is configured to use the "role" claim in the token to extract roles for the authenticated principal and to populate the security context with them. As part of the test-case, CXF's SimpleAuthorizingInterceptor is used to require that a client must have a role of "boss" to invoke on the web service method in question.

4) Encrypting JWT Tokens

It is very easy to encrypt JWT Tokens (as well as both sign and encrypt) them in CXF. The JwtAuthenticationClientFilter needs to be configured to also encrypt the token, and the same configuration is used as for JWE in the previous article. Similarly, on the receiving side the JwtAuthenticationFilter must have the property "jweRequired" set to "true" to decrypt incoming encrypted tokens. See the JWTEncryptedTest test for some examples. 

5) Token validation

On receiving a JAX-RS request containing a JWT token, the
JwtAuthenticationFilter will first parse the token, and then verify the signature (if present) and decrypt the token (if encrypted). It then performs some quality of service validation on the token claims, which I'll detail here. This validation can be easily modified by overriding the protected "validateToken" method in JwtAuthenticationFilter.
  • The "exp" (Expiration Time) claim is validated if present. If the expiry value is before the current date/time, then the token is rejected. 
  • The "nbf" (Not Before) claim is validated if present. If the not before value is after the current date/time, then the token is rejected. 
  • The "iat" (Issued At) claim is validated if present. To validate the "iat" claim, a "ttl" property must be set on the JwtAuthenticationFilter.
  • Either an "iat" or "exp" claim must be present in the token, as otherwise we have no way of enforcing an expiry on a token.
  • A clockskew value can also be configured on the JwtAuthenticationFilter via the "clockOffset" property.
  • The "aud" (Audience) claim is validated. This claim must contain at least one audience value which matches the endpoint address of the recipient.
Categories: Colm O hEigeartaigh

Javascript Object Signing and Encryption (JOSE) support in Apache CXF - part II

Colm O hEigeartaigh - Wed, 12/02/2015 - 18:49
This is the second in a series of blog posts on the support for the Javascript Object Signing and Encryption (JOSE) specifications in Apache CXF. The first article covered how to sign content using the JSON Web Signature (JWS) specification. In this post we will look at how to encrypt content using the JSON Web Encryption (JWE) specification.

1) Test Cases:

As before, let's start by looking at some practical unit tests on github:
  • cxf-jaxrs-jose: This project contains a number of tests that show how to use the JSON Security functionality in Apache CXF to sign and encrypt JSON payloads to/from a JAX-RS service.
For now let's look at the tests contained in JWETest. These tests mostly follow the same basic format. The web service configuration defines a number of endpoints that map to the same web service implementation (a simple DoubleItService, which allows a user to POST a number and receive the doubled amount, where both the request and response are encoded via JSON). The client test code uses the CXF WebClient API to encrypt the message payload by adding a specific provider. The message in turn is decrypted by a provider on the receiving side. You can run the test via the command line "mvn test -Dtest=JWETest", and the message requests and responses will appear in the console.

2) Compact vs. JSON Serialization

Just like the JWS specification, there are two different ways of serializing JWE structures. Compact serialization is a URL-safe representation that is convenient to use when you only have a single encrypting entity. JSON serialization respresents the JWE structures as JSON objects. As of the time of publishing this post, CXF only has interceptors for the compact approach. However I'm told the JSON serialization case will be supported very soon :-)

The providers to use for the compact case on both the client + receiving sides are:
  • Compact: JweWriterInterceptor (out) + JweContainerRequestFilter (in)
3) Security Configuration

As well as adding the desired providers, it is also necessary to specify the security configuration to set the appropriate algorithms, keys, etc. to use. The CXF wiki has an extensive list of all of the different security configuration properties. For encryption, we need to first load the encrypting key (either a JKS keystore or else a JSON Web Key (JWK) is supported).

As well as defining the encryption key, we also need to configure the algorithms to encrypt the content as well as to encrypt the key. The list of acceptable encryption algorithms for JWE is defined by the JSON Web Algorithms (JWA) spec. For content encryption, the supported algorithms are all based on AES (CBC/GCM mode) with different key sizes. For key encryption, various schemes based on RSA, AES KeyWrap/GCM, Elliptic Curve Diffie-Hellman, PBES2 are supported, as well as a symmetric encryption option.

For example, the tests use the following configuration to load a public key from a Java KeyStore, and to use the RSA-OAEP key encryption algorithm, as well as a 128-bit AES content encryption algorithm in CBC mode, using HMAC-SHA256 to generate the authentication code:
The service side configuration is largely the same, apart from the fact that we need to specify the "rs.security.key.password" configuration tag to load the private key. The encryption algorithms must also be specified to impose a constraint on the desired algorithms.

4) Encrypting XML payload

Similar to the signature case, it is possible to use JWE to encrypt an XML message, and not just a JSON message. An example is included in JWETest ("testEncryptingXMLPayload").  The configuration is exactly the same as for the JSON case. 

5) Including the encrypting key

It is possible to include the encrypting certificate/key in the JWE header by setting one of the following properties:
  • rs.security.encryption.include.public.key - Include the JWK public key for encryption in the "jwk" header.
  • rs.security.encryption.include.cert - Include the X.509 certificate for encryption in the "x5c" header.
  • rs.security.encryption.include.key.id - Include the JWK key id for encryption in the "kid" header.
  • rs.security.encryption.include.cert.sha1 - Include the X.509 certificate SHA-1 digest for encryption in the "x5t" header.
It could be useful to include the encrypting certificate/key if the recipient has multiple decryption keys and doesn't know which one to use to decrypt the request.

6) Signing + encrypting a message

It is possible to both sign and encrypt a message by combining the JWS + JWE interceptors. For example, simply adding the JweWriterInterceptor and JwsWriterInterceptor providers on the client side will both sign and encrypt the request. An example is included in the github project above (JWEJWSTest). 
Categories: Colm O hEigeartaigh

Javascript Object Signing and Encryption (JOSE) support in Apache CXF - part I

Colm O hEigeartaigh - Mon, 11/30/2015 - 18:39
The Javascript Object Signing and Encryption (JOSE) specifications cover how to sign and encrypt data using JSON. Apache CXF has excellent support for all of the JOSE specifications (see the documentation here), thanks largely to the work done by my colleague Sergey Beryozkin. This is the first in a series of blog posts describing how to use and implement JOSE for your web services using Apache CXF. In this post, we will cover how to sign content using the JSON Web Signature (JWS) specification.

1) Test Cases:

Let's start by looking at some practical unit tests on github:
  • cxf-jaxrs-jose: This project contains a number of tests that show how to use the JSON Security functionality in Apache CXF to sign and encrypt JSON payloads to/from a JAX-RS service.
For now let's look at the JWSSignatureTest. These tests mostly follow the same basic format. The web service configuration defines a number of endpoints that map to the same web service implementation (a simple DoubleItService, which allows a user to POST a number and receive the doubled amount, where both the request and response are encoded via JSON). The client test code uses the CXF WebClient API to sign the message payload by adding a specific provider. The message in turn is validated by a provider on the receiving side. You can run the test via the command line "mvn test -Dtest=JWSSignatureTest", and the message requests and responses will appear in the console.

For example, here is the output of the "testSignatureCompact" request. The Payload consists of the concatenated (+ separated by a '.') BASE-64 URL encoded JWS header (e.g. containing the signature algorithm, amongst other values), the BASE-64 URL encoded message payload, and the BASE-64 URL encoded signature value.


2) Compact vs. JSON Serialization

The JWS specification defines two different ways of serializing the signatures. Compact serialization is a URL-safe representation that is convenient to use when you only have a single signing entity. JSON serialization resprents the JWS structures as JSON objects, and allows multiple signatures to be included in the request as a result. The JWSSignatureTest includes both examples ("testSignatureListProperties" and "testSignatureCompact"). It's very easy to experiment with both approaches, as you only have to use different providers on both the client + receiving sides:
  • JSON Serialization: JwsJsonWriterInterceptor (out) + JwsJsonContainerRequestFilter (in)
  • Compact: JwsWriterInterceptor (out) + JwsContainerRequestFilter (in)
3) Security Configuration

As well as adding the desired providers, it is also necessary to specify the security configuration to set the appropriate algorithms, keys, etc. to use. The CXF wiki has an extensive list of all of the different security configuration properties. For signature, we need to first load the signing key (either a JKS keystore or else a JSON Web Key (JWK) is supported).

As well as defining a signing key, we also need to configure the signing algorithm. The list of acceptable signing algorithms for JWS is defined by the JSON Web Algorithms (JWA) spec. For signature, this boils down to a public key signature scheme based on either RSA or EC-DSA, or a symmetric scheme using HMAC.

For example, the tests use the following configuration to load a private key from a Java KeyStore, and to use the signature scheme of RSASSA-PKCS1-v1_5 using SHA-256:
The service side configuration is largely the same, apart from the fact that we don't need to specify the "rs.security.key.password" configuration tag, as we don't need to load the private key. The signature algorithm must be specified to impose a constraint on the acceptable signature algorithm.

4) Signing XML payload

The JWS payload (the content to be signed) can be any binary content and not just a JSON Object. This means that we can use JWS to sign an XML message. This is a really cool feature of the specification in my opinion, as it essentially removes the need to use XML Signature to sign XML payload. An example of this is included in the JWSSignatureTest. The configuration is exactly the same as for the JSON case.

5) Including the signing key

It is possible to include the signing certificate/key in the JWS header by setting one of the following properties:
  • rs.security.signature.include.public.key -  Include the JWK public key for signature in the "jwk" header.
  • rs.security.signature.include.cert - Include the X.509 certificate for signature in the "x5c" header.
  • rs.security.signature.include.key.id - Include the JWK key id for signature in the "kid" header.
  • rs.security.signature.include.cert.sha1- Include the X.509 certificate SHA-1 digest for signature in the "x5t" header.
One advantage of including the entire certificate is that the service doesn't need to store the client certificate locally, but only the issuing certificate.
Categories: Colm O hEigeartaigh

Enterprise ready request logging with CXF 3.1.0 and elastic search

Christian Schneider - Mon, 11/30/2015 - 15:24

Blog post edited by Christian Schneider

You may already know the old CXF LoggingFeature (org.apache.cxf.feature.LoggingFeature). You added it to a JAXWS endpoint to enable logging for a CXF endpoint at compile time.

While this already helped a lot it was not really enterprise ready. The logging could not be controlled much at runtime and contained too few details. This all changes with the new CXF logging support and the up coming Karaf Decanter.

Logging feature in CXF 3.1.0

In CXF 3.1 this code was moved into a separate module and gathered some new features.

  • Auto logging for existing CXF endpoints
  • Uses slf4j MDC to log meta data separately
  • Adds meta data for Rest calls
  • Adds MD5 message id and exchange id for correlation
  • Simple interface for writing your own appenders
  • Karaf decanter support to log into elastic search
Manual UsageCXF LoggingFeature <jaxws:endpoint ...> <jaxws:features> <bean class="org.apache.cxf.ext.logging.LoggingFeature"/> </jaxws:features> </jaxws:endpoint> Auto logging for existing CXF endpoints in Apache Karaf

Simply install and enable the new logging feature:

Logging feature in karaf feature:repo-add cxf 3.1.0 feature:install cxf-features-logging config:property-set -p org.apache.cxf.features.logging enabled true

Then install CXF endpoints like always. For example install the PersonService from the Karaf Tutorial Part 4 - CXF Services in OSGi. The client and endpoint in the example are not equipped with the LoggingFeature. Still the new logging feature will enhance the clients and endpoints and log all SOAP and Rest calls using slf4j. So the logging data will be processed by pax logging and by default end up in your karaf log.

A log entry looks like this:

Sample Log entry 2015-06-08 16:35:54,068 | INFO | qtp1189348109-73 | REQ_IN | 90 - org.apache.cxf.cxf-rt-features-logging - 3.1.0 | <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:addPerson xmlns:ns2="http://model.personservice.cxf.karaf.tutorial.lr.net/" xmlns:ns3="http://person.jms2rest.camel.karaf.tutorial.lr.net"><arg0><id>3</id><name>Test2</name><url></url></arg0></ns2:addPerson></soap:Body></soap:Envelope>

This does not look very informative. You only see that it is an incoming request (REQ_IN) and the SOAP message in the log message. The logging feature provides a lot more information though. You just need to configure the pax logging config to show it.

Slf4j MDC values for meta data

This is the raw logging information you get for a SOAP call:

FieldValue@timestamp2015-06-08T14:43:27,097ZMDC.addresshttp://localhost:8181/cxf/personServiceMDC.bundle.id90MDC.bundle.nameorg.apache.cxf.cxf-rt-features-loggingMDC.bundle.version3.1.0MDC.content-typetext/xml; charset=UTF-8MDC.encodingUTF-8MDC.exchangeId56b037e3-d254-4fe5-8723-f442835fa128MDC.headers{content-type=text/xml; charset=UTF-8, connection=keep-alive, Host=localhost:8181, Content-Length=251, SOAPAction="", User-Agent=Apache CXF 3.1.0, Accept=*/*, Pragma=no-cache, Cache-Control=no-cache}MDC.httpMethodPOSTMDC.messageIda46eebd2-60af-4975-ba42-8b8205ac884cMDC.portNamePersonServiceImplPortMDC.portTypeNamePersonServiceMDC.serviceNamePersonServiceImplServiceMDC.typeREQ_INlevelINFOloc.classorg.apache.cxf.ext.logging.slf4j.Slf4jEventSenderloc.fileSlf4jEventSender.javaloc.line55loc.methodsendloggerClassorg.ops4j.pax.logging.slf4j.Slf4jLoggerloggerNameorg.apache.cxf.services.PersonService.REQ_INmessage<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:getAll xmlns:ns2="http://model.personservice.cxf.karaf.tutorial.lr.net/"; xmlns:ns3="http://person.jms2rest.camel.karaf.tutorial.lr.net"/></soap:Body></soap:Envelope>;threadNameqtp80604361-78timeStamp1433774607097

Some things to note:

  • The logger name is <service namespace>.<ServiceName>.<type> karaf by default only cuts it to just the type.
  • A lot of the details are in the MDC values

You need to change your pax logging config to make these visible.

You can use the logger name to fine tune which services you want to log this way. For example set the debug level to WARN for noisy services to avoid that they are logged or log some services to another file.

Message id and exhange id

The messageId allows to uniquely identify messages even if you collect them from several servers. It is also transported over the wire so you can correlate a request sent on one machine with the request received on another machine.

The exchangeId will be the same for an incoming request and the response sent out or on the other side for an outgoing request and the response for it. This allows to correlate request and responses and so follow the conversations.

Simple interface to write your own appenders

Write your own LogSender and set it on the LoggingFeature to do custom logging. You have access to all meta data from the class LogEvent.

So for example you could write your logs to one file per message or to JMS.

Karaf decanter support to write into elastic search

Many people use elastic search for their logging. Fortunately you do not have to write a special LogSender for this purpose. The standard CXF logging feature will already work.

It works like this:

  • CXF sends the messages as slf4j events which are processed by pax logging
  • Karaf Decanter LogCollector attaches to pax logging and sends all log events into the karaf message bus (EventAdmin topics)
  • Karaf Decanter ElasticSearchAppender sends the log events to a configurable elastic search instance

As Decanter also provides features for a local elastic search and kibana instance you are ready to go in just minutes.

Installing Decanter for CXF Logging feature:repo-add mvn:org.apache.karaf.decanter/apache-karaf-decanter/3.0.0-SNAPSHOT/xml/features feature:install decanter-collector-log decanter-appender-elasticsearch elasticsearch kibana


After that open a browser at http://localhost:8181/kibana. When decanter is released kibana will be fully set up. At the moment you have to add the logstash dashboard and change the index name to [karaf-]YYYY.MM.DD.

Then you should see your cxf messages like this:

Kibana easily allows to filter for specific services and correlate requests and responses.

This is just a preview of decanter. I will do a more detailed post when the first release is out.

 

View Online
Categories: Christian Schneider

WADL and Swagger United in Apache CXF

Sergey Beryozkin - Fri, 11/20/2015 - 18:33
Who could've thought that Swagger and WADL can be real friends ?
Both Swagger and WADL are about describing REST APIs and while the former has a definite momentum, the latter has proved to be very capable and helpful to JAX-RS users.

The important thing is that we have users who submit WADL documents  to the runtime or build time code generators which is all working fine. We also have Swagger users who use cool Swagger features and being happy with a nice UI being generated. And WADL users, while being happy with WADL (which IMHO is indeed a very capable language for describing schema rich XML but with some extensions - even JSON - services) would like to use Swagger to introspect the code generated by WADL processors and have a nice API UI.

So my colleague Andrei and  Francesco, Apache Syncope maestro, have driven the work about enhancing a WADL generator to set WADL documentation fragments as Java Docs in the generated sources and then having CXF Swagger features being very smart about enhancing Swagger JSON payloads with these Java Docs, with Francesco doing some magic there. I should also mention Andriy Redko doing some work earlier on directly with Swagger for it to better support JAX-RS annotations and initiating the CXF Swagger project and Aki Yoshida doing a lot of Swagger2 work next.

So here you go, WADL and Swagger United in Apache CXF.

IMHO this project has been a perfect example of the power of the Open Source collaboration with the contributors from different teams working effectively on this project.


Categories: Sergey Beryozkin

HTrace your Apache CXF Service flows

Sergey Beryozkin - Fri, 11/20/2015 - 18:10
Andriy Redko keeps pushing CXF to the next level with adding new features nearly every few weeks :-).

One of his latest projects has been to do with wiring Apache HTrace into CXF such that CXF users can HTrace calls starting from CXF clients going to CXF servers and then to such HTrace aware containers as HBase  and using the collectors like Zipkin.

I'm looking forward to Andriy talking in detail about it on his blog and at the conferences, but in meantime you can check the documentation. Note that it works not only for JAX-RS but for JAX-WS too: if we can have a new feature working with both frontends then you know it will be done. The demo is here.

Give it a try and stay on top of the web services game :-)
Enjoy !



 
Categories: Sergey Beryozkin

JAX-RS 2.1 specification work has started

Sergey Beryozkin - Fri, 11/20/2015 - 17:51
JAX-RS 2.1 specification work has finally started after a rather quiet year and this is a good news for JAX-RS users at large and CXF JAX-RS users in particular.
JAX-RS 2.1 is entirely Java 8 based and a number of new enhancements are on the way. I was concerned earlier on that having a Java 8 will slow down the adoption but I think now the spec leads were right, Java 8 is so rich and JAX-RS needs to be open to accepting the latest Java features - ultimately this is what will excite the users.

The main new features list is: support for Server-Sent Events (something CXF users will enjoy experimenting with while also keeping in mind CXF has some great WebSocket support done by Aki), enhanced NIO support and introducing a reactive mode into Client API.

I've already mentioned before that JAX-RS 2.0 AsyncResponse API is IMHO very impressive as it makes a fairly complex task of dealing with suspended invocations becoming rather trivial to deal with. Marek and Santiago are doing it again with the new 2.1 proposals. Of course there will be some minor disagreements here and there but overall I'm very positive about this new JAX-RS project.


We now have a CXF Java 8 master branch to support the future JAX-RS 2.1 features but having a Java 8 trunk is great for all of the CXF community.

What is really good is that there appears to be no obvious end to the new requirements coming into the JAX-RS space. The HTTP services space is wide open, with the new ideas generated around the security, faster processing, etc, and it all will be eventually available as future JAX-RS features. I'm confident JAX-RS 3.0 will be coming in due time too.


Categories: Sergey Beryozkin

New security advisory for Apache CXF

Colm O hEigeartaigh - Mon, 11/16/2015 - 13:28
A new security advisory has been released for Apache CXF, which is fixed in the 3.1.3, 3.0.7 and 2.7.18 releases.
  • CVE-2015-5253: Apache CXF SAML SSO processing is vulnerable to a wrapping attack
Apache CXF supports the SAML SSO protocol with JAX-RS web service endpoints. It is possible for a malicious user to construct a SAML Response (the response from the SAML SSO IdP to the endpoint) via a so-called "wrapping attack", to allow that user to log in instead of the authenticated user associated with the signed SAML Assertion.

Please see the Apache CXF security advisories page for more information.
Categories: Colm O hEigeartaigh

Testing Kerberos with Web Services using Apache Kerby

Colm O hEigeartaigh - Wed, 11/11/2015 - 13:13
The previous blog post described how to use Apache Directory to easily create a KDC via Java annotations for kerberos integration testing. In this post, we will look at an alternative way of setting up a KDC for integration testing using Apache Kerby.

Apache Kerby is a new subproject of Apache Directory that aims to provide a complete Kerberos solution in Java. Version 1.0.0-RC1 has recently been released and is available for testing. Apache Kerby consists of both a KDC as well as a client API, that is completely independent of the GSS API that comes with Java. A key selling point of Apache Kerby is that it is very easy and fast to setup and deploy a KDC. It is possible to set up a KDC completely in code, without having to edit any configuration files or configure any system properties.

Let's see how this is done by looking at a project I created on github:
  • cxf-kerberos-kerby: This project contains a number of tests that show how to use Kerberos with Apache CXF, where the KDC used in the tests is based on Apache Kerby.
The KDC is launched in the test-code, and is pretty much as straightfoward as the following code snippet:

The first block of code configures the host, realm, transports and ports, while the second creates the client, service and TGT principals that are used in the tests. No configuration files required! As well as showing how to use Apache CXF to authenticate using both Kerberos and Spnego for a JAX-WS service, the AuthenticationTest also includes unit tests for getting a service ticket from the Kerby KDC using the Java GSS API as well as the Kerby client API. Using the Kerby client API is as simple as this:


Have fun playing around with Apache Kerby and please join and contribute to the project if you are interested!
Categories: Colm O hEigeartaigh

Testing Kerberos with Web Services using Apache Directory

Colm O hEigeartaigh - Mon, 10/26/2015 - 12:59
Apache CXF supports Kerberos for web services both via the Kerberos Token Profile of WS-Security, where the kerberos ticket is conveyed as a BinarySecurityToken in the security header of the client request, and over HTTP via the Negotiate authentication scheme. If you are developing kerberos-enabled web services using a framework like Apache CXF, a natural question to ask is how to set up a Kerberos KDC to test your web services prior to deployment. This is the first of two blog posts that shows two different ways to easily set up a KDC using open source projects for kerberos integration testing.

At ApacheCon EU 2014 in Budapest, I attended a great talk by Emmanuel Lécharny entitled "Testing LDAP Implementations". The talk covered how the Apache Directory project can be used to easily deploy Kerberos and LDAP servers in your test-code via annotations. This was music to my ears, as I had written a bunch of tests in Apache CXF for both LDAP and kerberos that were not run as part of the normal build, as they required a local KDC to run successfully. After this talk I got involved in the Apache Directory project, and converted the tests in Apache CXF to use Apache Directory instead, so they could be run as part of the normal build cycle. I also made some small improvements which I'll describe as part of this post.

I've created a project in github that shows how to use Apache Directory to set up a KDC, and how to use Apache CXF to authenticate to a web service using Kerberos, for both JAX-RS and JAX-WS:
  • cxf-kerberos: This project contains a number of tests that show how to use Kerberos with Apache CXF.
Both test-cases use an annotation to load a kerberos.ldif file, containing the information required to set up Kerberos principals in the KDC for testing:


 Another annotation sets up the Directory Service:

Finally, an annotation adds a KDC server:

The "KRB" protocol was added as part of DIRSERVER-2031 in the 2.0.0-M20 release. Previously, you could specify either "TCP" or "UDP" for the protocol attribute when testing Kerberos. However, this meant that they could not share the same port. The "KRB" protocol generates both TCP and UDP transports on the port provided, or otherwise on a random port. Previously, the random port generation was not working, as it always defaulted to 1024. Random port generation is an essential feature for testing as part of a build cycle, as hard-coded ports tend to cause problems on continuous integration platforms. Using a random port also means that the krb5.conf file used by the CXF clients must be read in, and the random port substituted into the file before writing it out again, as otherwise the clients would have no way of knowing the port the KDC was running on.
Categories: Colm O hEigeartaigh

A certificate revocation security vulnerability in Java

Colm O hEigeartaigh - Fri, 10/23/2015 - 12:04
A few days ago, Oracle released a Critical Patch Update containing fixes for various security vulnerabilities. In particular, the update contained fixes for 25 security vulnerabilities in Java itself. One of them, CVE-2015-4868, was discovered by me and duly disclosed to Oracle earlier this year. This issue has now been fixed in this Critical Patch Update (and included in Java 1.8.0_65), and so I am free to describe it.

1) Background

I first noticed this issue in the context of signature validation of SOAP web service requests. A signed SOAP request involves using XML Signature to sign some part of the request, where the resulting Signature structure is inserted into the security header of the request. The Signature contains a KeyInfo Element, which references the (public) key to use to validate the request. The recipient must resolve the appropriate public key, establish trust in it, and use it to validate the signature.

A common use-case is when the certificate used to validate the signature is included directly in the request, by BASE-64 encoding it in the security header. Optionally, the full certificate chain can be included instead. The recipient must take the certificates and establish a trust chain using a CA certificate stored in a local truststore, which is then validated.

However, what if the signing certificate has been revoked by the issuing CA? In this case, we can specify a Certificate Revocation List, and include it as part of the validation of the trust chain.

2) The vulnerability

Now to the vulnerability. Under the more usual use-case of just including the signing certificate in the security header, and establishing a trust-chain using a local truststore and CRL file, everything was working fine. Namely, if the signing certificate was trusted, but revoked, then the CertPath validation failed. However, if the issuing certificate of the signing certificate was also included in the security header, then CRL validation was not failing! This vulnerability exists in a range of JDK 8 versions prior to 1.8.0_65. It does not exist prior to JDK 8.

To see how this works using the Java CertPathValidator API, I created a simple maven-based unit test in github:
  • java.crls - A testcase that show how to include a CRL when validating the certificate path of a certificate.
The test has a JUnit failure assertion that asserts that the CertPathValidator validation should fail (as the signing certificate has been revoked). However, this failure assertion is not met when run locally with Java 1.8.0_51. With a Java version post-1.8.0_65 the failure assertion is met, and the test passes.
Categories: Colm O hEigeartaigh

Pages

Subscribe to Talend Community Coders aggregator