PicketLink with SAML and POST - does a redirect instead of a POST in the end
qtm Feb 4, 2016 4:33 AMHi,
I'm using picketlink and WildFly 9.0.2 for SAML with POST SSO. All goes as expected until the end where I'm getting a GET redirect instead of a POST.
Short version:
Quick call stack :
SP does a POST to IDP
The login form is displayed, I fill the correct user and password. It goes to the IDP.
IDP does a POST to SP, but receives a 302 HTTP status code - found
Then a redirect is done to SP using GET.
I don't understand the last part, why does the SP return 302, instead of 200, because the resource exist.
Detailed version:
For IDP I have followed the quickstarts for POST and SSL. I have a war deployed on a local wildfly instance.
the picketlink.xml for IDP:
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> <PicketLinkIDP xmlns="urn:picketlink:identity-federation:config:2.1" AttributeManager="org.picketlink.identity.federation.bindings.wildfly.idp.UndertowAttributeManager" SSLClientAuthentication="true" RoleGenerator="org.picketlink.identity.federation.bindings.wildfly.idp.UndertowRoleGenerator" StrictPostBinding="true" > <IdentityURL>${idp.url::https://localhost:8643/idp}</IdentityURL> <Trust> <Domains>localhost,jboss.com,jboss.org,amazonaws.com</Domains> </Trust> [SSL config] </PicketLinkIDP> <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1"> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2IssuerTrustHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" /> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" /> </Handlers> <PicketLinkSTS xmlns="urn:picketlink:identity-federation:config:2.1" TokenTimeout="5000" ClockSkew="0"> <TokenProviders> <TokenProvider ProviderClass="org.picketlink.identity.federation.core.saml.v1.providers.SAML11AssertionTokenProvider" TokenType="urn:oasis:names:tc:SAML:1.0:assertion" TokenElement="Assertion" TokenElementNS="urn:oasis:names:tc:SAML:1.0:assertion" /> <TokenProvider ProviderClass="org.picketlink.identity.federation.core.saml.v2.providers.SAML20AssertionTokenProvider" TokenType="urn:oasis:names:tc:SAML:2.0:assertion" TokenElement="Assertion" TokenElementNS="urn:oasis:names:tc:SAML:2.0:assertion" /> </TokenProviders> </PicketLinkSTS> </PicketLink>
For SP I have another local wildfly instance. The SP is a REST endpoint (http://localhost:8080/api/myendpoint/). It responds to POST.
The SP picketlink.xml file:
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1"> <PicketLinkSP xmlns="urn:picketlink:identity-federation:config:2.1" ServerEnvironment="tomcat" BindingType="POST" IDPUsesPostBinding="true"> <IdentityURL>${idp.url::https://localhost:8643/idp}</IdentityURL> <ServiceURL>${sp.url::http://localhost:8080/api/myendpoint/}</ServiceURL> <Trust> <Domains>localhost,jboss.com,jboss.org,amazonaws.com</Domains> </Trust> [SSL config] </PicketLinkSP> <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1"> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2IssuerTrustHandler"/> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler"/> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler"> <Option Key=" ASSERTION_SESSION_ATTRIBUTE_NAME " Value="SAMLAssertion"/> </Handler> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler"/> <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AttributeHandler"> </Handler> </Handlers> </PicketLink>
Call sequence captured with SAMLTracer:
POST https://localhost:8643/idp HTTP/1.1
Referer: http://localhost:8080/api/myendpoint
HTTP/?.? 307 Temporary Redirect
Location: https://localhost:8643/idp/
POST https://localhost:8643/idp/ HTTP/1.1
Referer: http://localhost:8080/api/myendpoint
HTTP/?.? 200 OK
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns="urn:oasis:names:tc:SAML:2.0:assertion" AssertionConsumerServiceURL="http://localhost:8080/api/myendpoint" Destination="https://localhost:8643/idp" ForceAuthn="false" ID="ID_62a08705-dd1c-4144-8251-d5499424dcc8" IsPassive="false" IssueInstant="2016-02-03T14:40:56.238Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0" > <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://localhost:8080/api/myendpoint/</saml:Issuer> <samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" /> </samlp:AuthnRequest>
POST http://localhost:8080/api/myendpoint/ HTTP/1.1
HTTP/?.? 302 Found
Connection: keep-alive
Location: http://localhost:8080/api/myendpoint
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Destination="http://localhost:8080/api/myendpoint" ID="ID_d870d88c-aeb1-49ae-857b-a0de15f8c9cf" InResponseTo="ID_62a08705-dd1c-4144-8251-d5499424dcc8" IssueInstant="2016-02-03T14:41:02.636Z" Version="2.0" > <saml:Issuer>https://localhost:8643/idp</saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /> </samlp:Status> <saml:Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="ID_d6200ba5-166c-462e-aa18-057f9b3931ed" IssueInstant="2016-02-03T14:41:02.632Z" Version="2.0" > <saml:Issuer>https://localhost:8643/idp</saml:Issuer> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">tomcat</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="ID_62a08705-dd1c-4144-8251-d5499424dcc8" NotOnOrAfter="2016-02-03T14:41:07.632Z" Recipient="http://localhost:8080/api/myendpoint" /> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2016-02-03T14:41:02.632Z" NotOnOrAfter="2016-02-03T14:41:07.632Z" > <saml:AudienceRestriction> <saml:Audience>http://localhost:8080/api/myendpoint/</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2016-02-03T14:41:02.637Z" SessionIndex="ID_d6200ba5-166c-462e-aa18-057f9b3931ed" > <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> <saml:AttributeStatement> <saml:Attribute Name="Role"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string" >manager</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="Role"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string" >employee</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="Role"> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string" >sales</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion> </samlp:Response>
GET http://localhost:8080/api/myendpoint HTTP/1.1
Host: localhost:8080