----- Original Message -----
From: "John Dennis" <jdennis(a)redhat.com>
To: "Pedro Igor Silva" <psilva(a)redhat.com>
Cc: "keycloak-dev" <keycloak-dev(a)lists.jboss.org>, "Nathan
Kinder" <nkinder(a)redhat.com>, "Adam Young"
<ayoung(a)redhat.com>, "Bill Burke" <bburke(a)redhat.com>
Sent: Friday, April 15, 2016 6:51:43 PM
Subject: Re: [keycloak-dev] Keycloak's SAML AuthnResponse uses wrong binding
On 04/15/2016 02:07 PM, Pedro Igor Silva wrote:
> Like we discussed on IRC, KC relies on the ProtocolBinding attribute
> of an AuthnRequest to decide which response binding to use. We don't
> support AssertionConsumerServiceURL neither
> AssertionConsumerServiceIndex. Accordingly with the specs, all those
> attributes are optional and mutually exclusive.
I don't believe that's true, they are not all mutually exclusive. Here
is my reading of the SAML Core Spec in Section "3.4.1 Element
<AuthnRequest>"
The AssertionConsumerServiceIndex, AssertionConsumerServiceURL and
ProtocolBinding attributes are all optional. The
AssertionConsumerServiceIndex is mutually exclusive with the
AssertionConsumerServiceURL attribute. The ProtocolBinding attribute
may only be composed with the AssertionConsumerServiceURL
attribute. Therefore the ProtocolBinding attribute is also mutually
exclusive with the AssertionConsumerServiceIndex attribute.
Here are the 5 possible legal combinations:
1) None of AssertionConsumerServiceIndex, AssertionConsumerServiceURL
nor ProtocolBinding are supplied.
2) AssertionConsumerServiceIndex is supplied
3) AssertionConsumerServiceURL is supplied
4) AssertionConsumerServiceURL and ProtocolBinding are supplied.
5) ProtocolBinding is supplied.
Right. I've sent another e-mail right after this one fixing what I said.
What I tried to say is that ACSI and ProtocolBinding are mutually exclusive. And usually,
ProtocolBinding is used with ACSURL.
In the Web SSO case the SAML Profiles Spec in Section
4.1.2 "Profile Overview" in "Step 5. Identity Provider issues
<Response>
to Service Provider" the spec is very clear you're supposed to respond
with an AuthnResponse using either POST or Artifact, but *never*
Redirect. Here is the specification text:
"In step 5, the identity provider issues a <Response> message to be
delivered by the user agent to the service provider. Either the HTTP
POST, or HTTP Artifact binding can be used to transfer the message to
the service provider through the user agent. The message may indicate
an error, or will include (at least) an authentication assertion. The
HTTP Redirect binding MUST NOT be used, as the response will typically
exceed the URL length permitted by most user agents."
> In case ProtocolBinding is not provided, KC chooses on based on how
> the AutnRequest was sent. Eg.Ç If sent using POST than use POST to
> respond.
See above, this is not correct.
This behavior is there for a long time. Since PicketLink SAML ...
I'm pretty sure there was some requirement for that. Probably some odd requirement
from our customers.
And that is why we always recommend POST (and also because the assertion is not exposed)
and the usage of that "Force Post Binding". Which is enabled by default ...
You can only respond using either HTTP-Post or Artifact. So which of the
two do you choose? You need to follow the rules outlined above for the
presence of the attributes in the AuthnRequest. Here is how I think you
need to handle the 5 cases enumerated above.
1) Since nothing was specified use a default (HTTP-Post). The spec seems
to be silent on what the default should be but HTTP-Post seems like the
best choice.
See above. We do that. And, AFAIK, we don't support Artifact.
2) Verify the AssertionConsumerServiceIndex is valid and specifies a
binding of either HTTP-Post or Artifact, if not it's an error. If the
ProtocolBinding attribute is also specified it's an error.
Do you really need ACSI ?
3) If only the AssertionConsumerServiceURL is specified you have to
figure out if you're going to use HTTP-Post or Artifact. The spec is
silent on how you determine this but a reasonable and friendly thing to
do is scan the AssertionConsumerService endpoints the SP supplied in
it's metadata in order [1] and select the first one which matches either
HTTP-Post or Artifact. If none of them match use the default
(HTTP-Post). You must verify the AssertionConsumerServiceURL is present
in the SP metadata.
Considering that we don't support Artifact. We would always choose POST.
Do you need Artifact ?
4) Verify the ProtocolBinding is one of HTTP-Post or Artifact, if not
it's an error. Use the ProtocolBinding attribute for the binding and the
AssertionConsumerServiceURL as the destination (after validating the URL
is specified in the SP metadata!)
That is fine. But again, no Artifact.
The ACSURL is always checked against the valid URLs you specified in your client
configuration.
5) Verify the ProtocolBinding is one of HTTP-Post or Artifact, if not
it's an error. The spec appears to be silent on how to determine the
AssertionConsumerService URL. Probably the best action is something
similar to case 3, scan the ACS endpoints in order [1] and use the first
match.
We already choose the ACSURL based on the client configuration.
[1] See Section 2.2.3 "Complex Type IndexedEndpointType" in the SAML
Metadata spec. concerning the isDefault flag and index values. Start
with the default ACS as determined by the rules in Section 2.3.3 and
then iterate over the remainder of the ACS's. I would suggest iterating
in index order as opposed to metadata order.
Do you need that ?
I think the point is, can you live with ProtocolBinding and ACSURL ? Or do you really need
full spec support (ACSI, etc) at this regard ?
Beside that, please note that if you don't provide a ACSURL, KC will choose one for
you accordingly with your client configuration.
--
John