PAC4J against AD FS 2.0 using SAML

2,894 views
Skip to first unread message

Jaroslav Kačer

unread,
Aug 26, 2014, 11:49:00 AM8/26/14
to pac4j...@googlegroups.com
Hello everyone!

I've been successfully using PAC4J for SAML integration for some time. I have tested it against a couple of Shibbolet IdP servers and also the Feide IdP server, which is written in PHP, as far as I know. However, when I tried to run it against Microsoft AD FS 2.0, I experienced problems preventing successful authentication. I wonder if someone has succeeded integrating PAC4J and ADFS.

1. Entity ID cannot contain a question mark
It seems that ADFS ignores everything after a question mark in an entity ID. As PAC4J uses question marks in URLs and IDs by default (e.g. http://localhost:8080/cas/login?client_name=Saml2Client), this is a problem. ADFS then complains in the log:
A token request was received for a relying party identified by the key 'https://server:8443/cas/login', but the request could not be fulfilled because the key does not identify any known relying party trust. Key: https://server:8443/cas/login. When I added another ID without everything after the question mark (https://server:8443/cas/login) to the corresponding ADFS trust in the ADFS management console, the problem disappeared. I think the problem could be also eliminated by editing the SAML metadata first before importing them to ADFS.

2. Signature algorithms that do not match
By default ADFS always wants to use RSA-SHA256 as the signature algorithm, although RSA-SHA1 is specified in the SAML message: <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>.
Moreover, it logs an error message that says exactly the opposite: SAML request is not signed with expected signature algorithm. SAML request is signed with signature algorithm http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 . Expected signature algorithm is http://www.w3.org/2000/09/xmldsig#rsa-sha1. This must also be edited in the ADFS management console.

After resolving these two problems, ADFS no longer logs any errors; however, the authentication still fails even before asking the user for credentials (using a login form).

It sends back a SAML response that contains this status code:
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder" />
</samlp:Status>

PAC4J then throws an exception from Saml2ResponseValidator.validateSamlResponse().

Does anybody have an idea what can be wrong, either on PAC4J or ADFS side? As I've said, there are no more errors in the Windows system log.
I would be grateful for any hint.

Thank you!

Jarda Kacer

Michaël REMOND

unread,
Aug 27, 2014, 3:49:22 AM8/27/14
to Jaroslav Kačer, pac4j...@googlegroups.com
Hello Jaroslav,

You made a lot of tests and investigations and I want to thank you for that.

The issue with the entityID being equals to the pac4j callback url (with the query string) has finally happened. When we designed the SAML module, we wanted to keep the configuration as simple as possible and that's why we have the entityID equals to the callback url.

But Microsoft will force us to adapt pac4j. What I will do is update the saml module to provide a custom SP entityID. This will allow to generate the correct metadata but also generate a correct authentication request. The last item is important and it is probably the reason why you receive an error message from ADFS.

I let you know when the 1.6.0-SNAPSHOT will be updated.

By the way, do you know some free ADFS on the cloud in case I need to make some tests?

Regards,
Michaël


--
You received this message because you are subscribed to the Google Groups "pac4j-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jaroslav Kačer

unread,
Aug 27, 2014, 5:10:58 AM8/27/14
to pac4j...@googlegroups.com, jaro...@kacer.biz
Hello Michael and thank you for your prompt reply!

If the issue is in the Entity ID, I will modify my metadata (I'll remove ?client_name=....) and import them again into ADFS.
As it seems ADFS strips ?xxxx from the SAML request, this should work and the metadata should be looked up fine.
I will keep posting my results here.

In the meantime, I have enabled debug logging for ADFS but it is not much useful in this case. No errors in the debug log (just info level) and the messages do not indicate any error. Just the last message says the "Responder" status code is being send back to the client:
Description: Response: Id='_dc36e88f-d5c2-4eab-9147-dad4a7e1de13', InResponseTo='_5f2f4de8d1928a8269e9088f6e0fe446', Status='urn:oasis:names:tc:SAML:2.0:status:Responder', Destination='https://czpr-jkacer01.insideidc.com:8443/cas/login?client_name=IdcTestAdfsSaml2Client': error response created

And I'm really looking forward to see version 1.6 :-)

Concerning public ADFS, unfortunately I don't know any :-(
I am testing against our company's internal ADFS, which is not even reachable from the Internet.

Thank you very much once again & Have a nice day!

Jarda

Dne středa, 27. srpna 2014 9:49:22 UTC+2 Michaël REMOND napsal(a):

Michaël REMOND

unread,
Aug 27, 2014, 9:59:43 AM8/27/14
to Jaroslav Kačer, pac4j...@googlegroups.com
Jaroslav,

The module 1.6.0-SNAPSHOT has been updated but the build is currently broken because of refactoring on the tests. You may however try it if you build pac4j from the sources on your own by disabling the test phase. I think it will solve your issue because fixing the metadata before importing them in ADFS is not enough as the Authentication Request must have the correct entity ID too.

Please use the following code to specify your own entity ID:

// custom SP entity ID
client.setSpEntityId("http://localhost:8080/callback");

Given your context, you can put for example "https://czpr-jkacer01.insideidc.com:8443/cas/login"

Regards,
Michael
  

Jaroslav Kačer

unread,
Aug 27, 2014, 11:11:04 AM8/27/14
to pac4j...@googlegroups.com, jaro...@kacer.biz
Hi Michael!

Thank you for such a quick fix! I'll grab the new code tomorrow and try it out. I will keep you informed about any progress.

In the meantime, I tried to do something similar manually, i.e. to "replay" the POST request from the client to ADFS using a REST client in Firefox, while modifying the <Issuer> element in SAML. It did not work out, however, I think it was due to a badly constructed POST request.

Thank you & Have a nice day!

Jarda


Dne středa, 27. srpna 2014 15:59:43 UTC+2 Michaël REMOND napsal(a):

Jaroslav Kačer

unread,
Aug 28, 2014, 9:15:04 AM8/28/14
to pac4j...@googlegroups.com, jaro...@kacer.biz
Hi again, Michael!

I can confirm the fix you made helps!

I set up an explicit Entity ID and it was sent in the request:
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://czpr-jkacer01.insideidc.com:8443/cas/login_IdcTestAdfsSaml2Client</saml2:Issuer>

ADFS then authenticated the user and returned back a SAML response.
I got another error then saying "Illegal key size" but that's another story and I think I will be able to get over it somehow. I think it is not directly related to PAC4J.

Just one thing: I had to slightly modify the PAC4J plugin in CAS due to some other changes made in 1.6.x.
Namely class ClientAction, line 135, because Protocol has been replaced by Mechanism:

if (client.getMechanism() != Mechanism.SAML_PROTOCOL) {
    throw new TechnicalException("Only SAML clients are supported. Your client is: " + client);
}

Thank you very much for your help once again!

Best Regards,
   Jarda Kacer


Dne středa, 27. srpna 2014 15:59:43 UTC+2 Michaël REMOND napsal(a):
Jaroslav,

Jaroslav Kačer

unread,
Aug 28, 2014, 11:45:14 AM8/28/14
to pac4j...@googlegroups.com
One more important thing for those who plan to use PAC4J against ADFS:
Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files must be installed in the JDK/JRE running the service provider. It seems ADFS uses a strong encryption algorithm which cannot be handled by default. When this happens, you see messages like this in the logs:

2014-08-28 14:46:33,930 ERROR [org.opensaml.xml.encryption.Decrypter] - <Error decrypting the encrypted data element>
org.apache.xml.security.encryption.XMLEncryptionException: Illegal key size
Original Exception was java.security.InvalidKeyException: Illegal key size
(stacktrace...)

2014-08-28 14:46:33,933 ERROR [org.opensaml.xml.encryption.Decrypter] - 
<Failed to decrypt EncryptedData using either EncryptedData KeyInfoCredentialResolver or EncryptedKeyResolver + EncryptedKey KeyInfoCredentialResolver>
2014-08-28 14:46:33,933 ERROR [org.opensaml.saml2.encryption.Decrypter] - <SAML Decrypter encountered an error decrypting element content>
org.opensaml.xml.encryption.DecryptionException: Failed to decrypt EncryptedData
(stacktrace...)

Installing the new policy files solves the issue.

I think this is the cause of the problem:
<EncryptedAssertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
<e:EncryptedKey xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
</e:EncryptionMethod>
...

Best Regards,
 Jarda

Michaël REMOND

unread,
Aug 29, 2014, 3:57:42 AM8/29/14
to Jaroslav Kačer, pac4j...@googlegroups.com
Great ! I'm glad to hear you succeed in integrating pac4j with ADFS. Maybe you could make a pull request to update the README in pac4j.

Thanks very much for your interest,

Michaël


--

Jaroslav Kačer

unread,
Aug 29, 2014, 5:39:09 AM8/29/14
to pac4j...@googlegroups.com, jaro...@kacer.biz
Hi Michael!

Dne pátek, 29. srpna 2014 9:57:42 UTC+2 Michaël REMOND napsal(a):
Great ! I'm glad to hear you succeed in integrating pac4j with ADFS. Maybe you could make a pull request to update the README in pac4j.

Sure, when I finish the whole task and resolve all problems, I will update the README file.

Just FYI, here are a couple of things I have had to solve so far:

1. It seems there duplicate versions of XMLSec in PAC4J-SAML. Version 1.3.0 is referenced directly, version 1.4.4 indirectly via OpenSAML and XML Tooling. So I simply excluded 1.3.0 from the PAC4J CAS plugin. Maven was not able to detect it because they changed the group name from "xml-security" to "org.apache.santuario".

2. I encountered an issue with different authentication life sizes on ADFS and in the PAC4J client. By default, ADFS has this set to 8 hours, while PAC4J to 1 hour only. So I was getting back assertions containing authentications that were still valid on ADFS but evaluated as invalid in PAC4J.

Example:

<**** SAML Response / IssueInstant>
<Now: 1409242359281, IssueInstantMS: 1409242346678, Interval: 0, Skew: 120, IssueInstant: 2014-08-28T16:12:26.678Z>
<Before end OK: true>
<After start OK: true>

<*** Assertion / IssueInstant>
<Now: 1409242359345, IssueInstantMS: 1409242346678, Interval: 0, Skew: 120, IssueInstant: 2014-08-28T16:12:26.678Z>
<Before end OK: true>
<After start OK: true>

<**** Authentication statement / Authentication instant>
<Now: 1409242359346, IssueInstantMS: 1409229981270, Interval: 3600, Skew: 120, IssueInstant: 2014-08-28T12:46:21.270Z>
<Before end OK: true>
<After start OK: false>

The last one is not OK. That's an authentication created about 3.5 hours before the SAML assertion is sent back by ADFS. On ADFS side, it's still valid. On CAS side, it's already invalid.

I solved this by setting Maximum Authentication Lifetime on the client to 8 hours:
<property name="maximumAuthenticationLifetime" value="28800"/>

Alternatively, this can be also set on ADFS using the management console or PowerShell scripts.

3. Something interesting but not related to PAC4J: ADFS requires certificates of all trusts to be unique. You cannot register more trusts (i.e. SPs) using the same certificate in their metadata. TestShib or Feide, for example, allow it. This is somewhat unpleasant for development and testing when I have more environments (SPs) and I don't want to care about generating a new certificate for each. But maybe a valid point for production usage.

More issues on the way, stay tuned...

Best Regards,
   Jarda

Jaroslav Kačer

unread,
Aug 29, 2014, 11:41:40 AM8/29/14
to pac4j...@googlegroups.com
Hello everyone!

As I promised, here is another issue concerning ADFS. A tough one :-(

My PAC4J installation cannot verify the SAML response coming from ADFS for a curious reason. It cannot "establish trust of a KeyInfo-derived credential". More details follow...

Normally, what I get back as SAML response (i.e. from Shibboleth IdP), is the following:

<saml2:EncryptedAssertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="_7a52d4e67b6ae2288f4df12e233223ae" Type="http://www.w3.org/2001/04/xmlenc#Element">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<xenc:EncryptedKey Id="_01551d715912b8d3e5b4ece4ac2629f2" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
</xenc:EncryptionMethod>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIID.......(BASE-64 data)</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
<xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:CipherValue>.......</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedKey>
</ds:KeyInfo>
<xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:CipherValue>.....</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</saml2:EncryptedAssertion>

But ADFS returns a slightly different structure (changes are highlighted):

<EncryptedAssertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
<e:EncryptedKey xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
</e:EncryptionMethod>
<KeyInfo>
<ds:X509Data xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509IssuerSerial>
<ds:X509IssuerName>CN=pac4j-demo, OU=Unknown, O=Unknown, L=Unknown, S=Unknown, C=Unknown</ds:X509IssuerName>
<ds:X509SerialNumber>1395330932</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data>
</KeyInfo>
<e:CipherData>
<e:CipherValue>......</e:CipherValue>
</e:CipherData>
</e:EncryptedKey>
</KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>.....</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</EncryptedAssertion>

Simply, the BASE-64 data of the certificate have been replaced with a "descriptor" of the certificate. Maybe the SP is assumed to lookup the right certificate based on this data, I'm not sure. The X509IssuerName data look OK, I use the certificate from the PAC4J demo project.

Anyway, PAC4J is not able to process the assertion. I debugged the whole validation process and found this:

We try to validate the assertion:
org.pac4j.saml.sso.Saml2ResponseValidator.validateAssertion(Saml2ResponseValidator.java:248)
--> org.pac4j.saml.sso.Saml2ResponseValidator.validateAssertionSignature(Saml2ResponseValidator.java:419)
--> org.pac4j.saml.sso.Saml2ResponseValidator.validateSignature(Saml2ResponseValidator.java:455)

Here we call trustEngine.validate(signature, criteriaSet); (trustEngine is ExplicitKeySignatureTrustEngine from OpenSAML XML Tooling), then validate(Signature, TrustBasisType) which returns false because:
- At line 99 the signature is verified OK
- At line 102 we call evaluateTrust() which returns false.

evaluateTrust() uses ExplicitKeyTrustEvaluator to find whether a certain untrusted credential is among trusted credentials. I have just 1 trusted credential. They compare public keys of the untrusted and trusted credential. In my case, they don't match because their moduluses differ. So the whole trust evaluation returns false. For the 1st SAML Reply with an explicit certificate data, the trust evaluates to true.

I have no idea what the exact cause could be. Should the trust engine be populated explicitly with the certificate? And if yes, how?

Are there any ideas how to make this work? Has enybody encoutered  such SAML responses?

Thank you in advance for any hint or help!

Best Regards,
  Jarda

Jaroslav Kačer

unread,
Sep 1, 2014, 9:11:20 AM9/1/14
to pac4j...@googlegroups.com
Hello everyone!

I think I found a possible solution to the above problem with ADFS responses. It's based on this idea:
- SignatureTrustEngineProvider creates an instance of ExplicitKeySignatureTrustEngine inside build().
- The 2nd parameter to the constructor is OpenSAML's default KeyInfoCredentialResolver.
- The resolver has, by default, 3 KeyInfoProviders that are configured in DefaultSecurityConfigurationBootsrap.populateKeyInfoCredentialResolverParams(): RSAKeyValueProvider, DSAKeyValueProvider and InlineX509DataProvider.
- The last one is responsible for creating credentials from <KeyInfo>/<X509Data>.
- However, it seems (from the JavaDoc) that it needs <X509Certificate>, plus optionally it can process <X509IssuerSerial> in order to select a certificate if there are more of them. I.e., a <X509Certificate> element must be present, which is not true in my case.
- If I create a new KeyInfoProvider and register it within OpenSAML, it should supply a credential based on a certificate loaded from a file or a classpath resource.

Does this approach seem reasonable to you?
Or can you see any possible problems?

Thank you very much for your comments!
I'm going to try to implement it...

Best Regards,
   Jarda

Jaroslav Kačer

unread,
Sep 2, 2014, 2:55:37 AM9/2/14
to pac4j...@googlegroups.com
Hello again, everyone!

Please ignore the last reported problem. My bad -- we reinstalled ADFS and I forgot to update IdP metadata on the client side. That's why the credentials could not match inside OpenSAML. It took me a whole day of debugging and examining code, ufff :-(

I apologize to anyone who invested his time into examining it.

Therefore, I confirm the default OpenSAML configuration set up by PAC4J is usable even for this kind of KeyInfo without certificate data:
<ds:X509Data xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509IssuerSerial>
<ds:X509IssuerName>CN=pac4j-demo, OU=Unknown, O=Unknown, L=Unknown, S=Unknown, C=Unknown</ds:X509IssuerName>
<ds:X509SerialNumber>1395330932</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data>

The InlineX509DataProvider is able to process such key infos and resolve the certificate successfully.

I am sorry once again!
And moving forward with PAC4J and ADFS...

Best Regards,
  Jarda

Michaël REMOND

unread,
Sep 2, 2014, 3:46:49 AM9/2/14
to Jaroslav Kačer, pac4j...@googlegroups.com
No problem, I'm glad to hear you succeeded because these certificates stuff are not easy to solve.

Since we want to ship the 1.6 release of pac4j soon, please tell us if the current trunk can function with ADFS or if we need to backport some of your modifications.

Regards,
Michaël


Jaroslav Kačer

unread,
Sep 2, 2014, 8:23:12 AM9/2/14
to pac4j...@googlegroups.com, jaro...@kacer.biz
Hi Michael!

Finally I got a CAS TGT ticket created when authenticating via ADFS :-)

But some modifications inside PAC4J were needed, because it seems ADFS does not return any of these data in accertion Subject: NameID, BaseID, EncryptedID. I looked into the SAML specification and indeed they are not mandatory if there is at least one SubjectConfirmation. There is one SubjectConfirmation in my case but it does not contain any of those IDs either (also allowed, I believe).

I have rewritten Saml2ResponseValidator, Saml2Client and ExtendedSAMLMessageContext a little bit to allow processing of such replies:
  • I try to pick those IDs directly from the Subject.
  • If not found, I try to pick them from any usable SubjectConfirmation.
  • BaseID is also accepted (although it is an abstract type, this can be almost anything derived), altough it is not later used for the credentials
  • If no ID is found in validateSubject(), I don't throw an exception, just log a warning.
  • I throw an exception later in validateSamlSSOResponse() if there is no ID and no SubjectConfirmation. If there is at least one SubjectConfirmation (altough without any ID), I leave it pass.
  • If later the NameID is null, I create a dummy one with name "Unknown_SAML_User" and use it.
I believe it does not violate the SAML specification. If you think it does, please tell me. I studied the whole section 2.4.

I noticed that ADFS returns information in attributes while Shibboleth does not by default. The set of attributes to be returned can be configured in the ADFS management console. Maybe this could be used to extract the ID to be put into SAML credentials but at the moment I don't need this (I think), so I did not modify anything there.

Would you be interested in a pull request on GitHub?

Best Regards,
   Jarda


Dne úterý, 2. září 2014 9:46:49 UTC+2 Michaël REMOND napsal(a):

Benoit S

unread,
Nov 25, 2014, 3:29:15 AM11/25/14
to pac4j...@googlegroups.com, jaro...@kacer.biz
Hi Jaroslav,

First, I would like to thank you and Michaël for this thread, it helped me a lot in my integration of pac4j against ADFS. I also followed the rules described here: https://github.com/leleuj/pac4j/blob/master/README-ADFS.txt

It sounds like I'am now facing the last issue you are talking about. The full error message is: Subject NameID, BaseID and EncryptedID cannot be both null at the same time if there are no Subject Confirmations.

Would it be possible you to share the patch you applied to get it work?

Thanks.

Benoit.

Jaroslav Kačer

unread,
Nov 25, 2014, 3:42:29 AM11/25/14
to pac4j...@googlegroups.com, jaro...@kacer.biz
Hi Benoit!

What version of PAC4J are you currently using? If it is 1.6.0, those changes should already be there.

And, please do not forget to edit a Claim Rule in the ADFS console, associated with your Relying Party Trust. You select a trust and then in the menu on the right side there is an option "Edit Claim Rule" (or something similar). The important thing about it is that the rule must export an attribute with key "Name ID" (there is a space in the middle). This key will be used as the subject's ID. This is the right column of the mapping table in the edit dialog. In the left column (source attribute), you can select whatever you want - something uniquely identifying the user. For example, I use the email address.

In theory, you could omit this, if you set up ADFS to generate at least one Subject Confirmation with a Base ID or Encrypted ID. Unfortunately I don't know how to do it. But the above setup with Name ID always worked for me.

Hope this helps :-)

If you still have problems, please write back to this thread.

Best Regards,
   Jarda



Dne úterý, 25. listopadu 2014 9:29:15 UTC+1 Benoit S napsal(a):

Benoit S

unread,
Nov 26, 2014, 3:41:25 AM11/26/14
to pac4j...@googlegroups.com, jaro...@kacer.biz
Hi Jaroslav,

Thanks to your help, we could get our application to work with an ADFS SAML Identity Provider.

Thank you and all the pac4j contributors, you did a great job!

Benoit

Jaroslav Kačer

unread,
Nov 26, 2014, 3:45:08 AM11/26/14
to pac4j...@googlegroups.com, jaro...@kacer.biz
Nice to hear that, you're welcome :-)

Jarda

Dne středa, 26. listopadu 2014 9:41:25 UTC+1 Benoit S napsal(a):
Hi Jaroslav,

Anton Piatek

unread,
May 4, 2017, 4:37:55 AM5/4/17
to pac4j-users
Hi, I've just come across your post while I was testing a pac4j app using saml against AD FS. Thanks for pointing out some of the issues, I have a question though if anyone has further details


On Tuesday, August 26, 2014 at 4:49:00 PM UTC+1, Jaroslav Kačer wrote:
Hello everyone!

I've been successfully using PAC4J for SAML integration for some time. I have tested it against a couple of Shibbolet IdP servers and also the Feide IdP server, which is written in PHP, as far as I know. However, when I tried to run it against Microsoft AD FS 2.0, I experienced problems preventing successful authentication. I wonder if someone has succeeded integrating PAC4J and ADFS.

1. Entity ID cannot contain a question mark
It seems that ADFS ignores everything after a question mark in an entity ID. As PAC4J uses question marks in URLs and IDs by default (e.g. http://localhost:8080/cas/login?client_name=Saml2Client), this is a problem. ADFS then complains in the log:
A token request was received for a relying party identified by the key 'https://server:8443/cas/login', but the request could not be fulfilled because the key does not identify any known relying party trust. Key: https://server:8443/cas/login. When I added another ID without everything after the question mark (https://server:8443/cas/login) to the corresponding ADFS trust in the ADFS management console, the problem disappeared. I think the problem could be also eliminated by editing the SAML metadata first before importing them to ADFS.
 
My app is multitenant, so I'm thinking I will need something equivalent to /callback?client_name=saml1 in order to separate which client to use to validate the response? Has anyone got this working with multiple clients (even multiple saml clients)? Is the client_name parameter required, or is it enough that each IdP will have their own urls and signatures so pac4j can tell which client to use to validate them? The big part is that as my app is multitenant, each saml client has its own mapping from the saml token back to the right user lookup code, which has to be correct and secure.
If I do need an explicit client mapping, I'm assuming I could just set the callback url to  /callback/client_name/saml1 or similar, but how do I hook that into the callback logic so that it selects the correct client to use given that url?

Many thanks, 
Anton

Jérôme LELEU

unread,
May 4, 2017, 5:06:02 AM5/4/17
to Anton Piatek, pac4j-users
Hi,


See my reply:

I had never thought about having such customized callback URL, but as the clients are gathered in the Clients component which is also used to retrieve them, I have the feeling that subclassing the Clients component should allow you to do exactly what you want.

The following methods: protected void updateCallbackUrlOfIndirectClient(final IndirectClient indirectClient) and public Client findClient(final WebContext context) could be overridden for your needs.

We could certainly even go further on this by creating some interface and implementations or some delegated component to handle the addition and retrieval of the client name.

Thanks.
Best regards,
Jérôme


--
You received this message because you are subscribed to the Google Groups "pac4j-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users+unsubscribe@googlegroups.com.

Anton Piatek

unread,
May 4, 2017, 5:27:38 AM5/4/17
to pac4j-users, anton....@gmail.com
Thanks, that sounds useful. 
Presumably this is something that will be needed with multiple clients - the callback handler can't use the contents of the saml assertion to determine the correct client by its IdP url or signature on its own (I'll admit that even as I write this idea, it sounds awfully complicated thing to get correct compared to using a named parameter)

Jérôme LELEU

unread,
May 4, 2017, 5:33:06 AM5/4/17
to Anton Piatek, pac4j-users
From a pac4j perspective, I don't think you can really use the SAML assertion to determine the right client (as it happens later in the login process). It's better rely on the query parameter or path...

--

Anton Piatek

unread,
May 4, 2017, 9:47:22 AM5/4/17
to pac4j-users, anton....@gmail.com
Thanks, 
It turned out to be relatively simple to do as you suggest and override the callback url and the callback resolver code by subclassing Clients. 
In case anyone else is trying to achieve this, don't forget to consider the saml ServiceProviderEntityId too, as I had to have it match my callback url for AD FS to play nicely
To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users...@googlegroups.com.

Jaroslav Kačer

unread,
May 4, 2017, 11:40:39 AM5/4/17
to pac4j-users
Hi Anton!

Yes, we use PAC4J in this mode. We have about 10 different clients, all of them are SAML clients.
We use the "client_name" parameter every time - our application constructs the URL (including a client name) and then forwards the browser to it.

Please do not forget to use "client_name" in the SAML metadata too, for the Assertion Consumer Service. As a consequence of this, you need different metadata for each client.

(Maybe I'm replying too late and you have already solved your problem, but just in case you or someone else needs it...)

Best Regards,
    Jarda

Dne čtvrtek 4. května 2017 10:37:55 UTC+2 Anton Piatek napsal(a):
Hi, I've just come across your post while I was testing a pac4j app using saml against AD FS. Thanks for pointing out some of the issues, I have a question though if anyone has further details
Reply all
Reply to author
Forward
0 new messages