Closed tngan closed 7 years ago
Just a heads up that I verified it works with SimpleSamlPHP. I'm hoping to test Shibboleth next week.
I have trouble integrating with Okta when Okta acts as SP - It needs AuthnStatement and some other issues am yet to understand since am new to SAML. From Okta error log: The recipient specified in the SubjectConfirmation did not match our service provider entity id. Found "{0}", expected "{1}"
Our code sends right entityId and still it fails. I tried with ACS URL too and it still failed. Any helps would be appreciated.
@yesvivek I think Okta should be an identity provider instead of service provider, then your application acts as a service provider. The SubjectConfirmation (P.18-19 in doc) should be something look like,
<saml:SubjectConfirmationData
NotOnOrAfter="2024-01-18T06:21:48Z"
Recipient="http://sp.example.com/demo1/index.php?acs"
InResponseTo="_4fee3b046395c4e751011e97f8900b5273d56685"/>
</saml:SubjectConfirmation>
and in your use case, the recipient is same as your entity identifier (P.79 in doc) which is configured in Okta (http://developer.okta.com/standards/SAML/setting_up_a_saml_application_in_okta) and specified in your Issuer and NameID tag.
@tngan I understand Okta is popularly used as IdP entity but here am attempting to use express-saml2 as Identity Provider and making clould entities like Okta to talk to it and get authenticated - Okta supports this.
There is confusion in Recipient attribute, either be ACS URL or SP-EntityID - express-saml2 uses entityID for Recipient.
PostBinding.js:99 SubjectRecipient: spEntityID,
But the standard says it needs to be ACS URL.
Either way, Okta rejects both the Assertions which is surprising. Any help here would be appreciated.
That's interesting. I will open a new issue for this thread. Meanwhile, you can override the default method and use your own template.
However, the mismatch message shows From Okta error log: The recipient specified in the SubjectConfirmation did not match our service provider entity id. Found "{0}", expected "{1}"
Can you check the recipient in the response is same as the entity id configured in your Okta panel ? It would be good if you can also provide sample saml request from Okta or the response from express-saml2, not sure if you are doing idp-initiated or sp-initiated.
@tngan , I have gotten past that Recipient issue by setting it as ACS URL. I need to explore the template option of express-saml2. Befre that, am facing cert errors reported by Okta - It says
The digital signature in the SAML response did not validate with the Identity Providers certificate
I have used following command to generate cert and keys.
openssl req -newkey rsa:2048 -new -x509 -days 3650 -keyout key.pem -out cert.pem
and provided the privateKeyFile
as key.pem and signingCertFile
as cert.pem and privateKeyFilePass
with actual password. Not sure where the problem is here.
I think you may have to set the correct signature algorithms when you configure the application in Okta. By our default entity setting, the signature algorithm is RSA-SHA1 (but we will change the default setting to RSA-SHA256 in version 2).
@tngan the above screenshot is used for configuring express-saml2 as SP and Okta as IdP, but am using express-saml2 as IdP and Okta as SP - please refer this link https://support.okta.com/help/Documentation/Knowledge_Article/40561903-Configuring-Inbound-SAML. There is no option at Okta to specify any algorithm when it acts as SP and am assuming Okta doesnt restrict to specific algorithm. This could become easy if Okta says what the error is exactly.
Oh sorry, you are right, I just wonder SP should have similar configuration to handle the response from IdP. When you setup an inbound SAML, the documentation mentions that you have to add an Idp, can you configure something like that in Okta ?
We can give only basic data about IdP to Okta. Attaching the screenshot from Okta Inbound Saml page,
@tngan I can share you my nodejs code and steps to create okta-dev account so that you could do your magic to sort this?
@yesvivek Remember to hide all sensitive information before you post here.
@tngan, giving you steps to create life-long free Okta-developer account. Have attached the NodeJS code am using - little altered for publishing. express_saml2_idp.txt
1) Visit https://www.okta.com/developer/signup
to create Okta dev account
2) After creating & verifying acccount, login and goto Admin console.
3) Open Security -> Authentication -> Inbound SAML.
4) Add Endpoint to provide your IdP settings. I have used above openssl command to create certs and keys. Please refer specific comment for more details.
5) Once saved, download Metadata to refer it in express-saml2.
6) For SAML error logs, Reports -> System Log. In log section, click on > symbol of each entry to expand. Expand Event > Outcome > Reason to get more particular error info.
7) Download and modify the attached express-saml2 as per your Okta settings.
8) Run the saml2 server.
9) Access https://your-dev.oktapreview.com and you will be redirected to express-saml2 for authentication which sends hard-coded username.
10) Have added the modified LoginResponseTemplate from SamlLib.js at the end of the attachment.
Thanks for your help.
@yesvivek I will try to make an inbound saml example within this week.
@yesvivek An update for the example of inbound saml. Instead of adding endpoint, I've added the Identity Provider (Security -> Identity Provider) and matched the algorithm selected in express-saml2. However, I got the error user.authentication.auth_via_IDP
, I have made a support request to Okta developer team to figure out what problem it is.
It is an assertion error and I do think the signature verification is passed, normally assertion check should be after the signature verification, the error may be caused by the wrong attribute name mapping. I will keep you posted here.
@yesvivek Keep things updated. I have scheduled a call with the dev team next week. I will also create an example of using Okta as IdP and try to work out the solution of inbound saml again.
There is a fork repo of express-saml2, they implement a way to insert attribute statement and you may want to check it out. I hope it can be integrated in this module later on. I am open to any pull request. (#56)
https://github.com/nimbleton/ij-express-saml2/commit/4befc559ef06eea17cdbe8ef292adea06d25e66a
Example for Okta as Identity Provider is created in sp1 of branch 2.0.0-alpha. When localhost:4002 is accessed, press Login via Okta
button then enter the credential for Okta account. Afterthat, you are supposed to login sp1. The step-by-step Okta configuration will be included in documentation very soon.
Email: exprsaml2@gmail.com Password: oktaEsaml2
You can also login the sp1 directly via:
Email: exprsaml2@gmail.com Password: admin123
@yesvivek The inbound example is still in progress. :(
Some updates on the inbound saml.
Okta requires at least four attributes for authentication, firstName, lastName, login and the email, that's one of the reasons why I got 400 last time.
Thanks for your follow ups, Ngan.. I have made it to work with node-samlp without any of these attributes. Just sending email-ID as NameID was enough there.
On Mon, Mar 20, 2017 at 11:11 PM, Tony Ngan notifications@github.com wrote:
Some updates on the inbound saml.
Okta requires at least four attributes for authentication, firstName, lastName, login and the email, that's one of the reasons why I got 400 last time.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/tngan/express-saml2/issues/12#issuecomment-287839461, or mute the thread https://github.com/notifications/unsubscribe-auth/ADel-vrkwLEfcfHPGgwbefMjKhER7Sr9ks5rnrpQgaJpZM4GUrnS .
@yesvivek Thanks for your update. Would you like to post the sample saml response sent by the idp there ?
@tngan have sent 1-1 mail to your personal mailID.
@sebakerckhof The discussion of inbound saml of okta is here, and we can add attributes when our IdP handles the SAML response right now #56 (the commits are already in the alpha branch).
The example is shown in two test cases and I haven't added it into documentation. (tests)
also in the example code here.
Okay, I had some time today to set up an okta account.
If I try to log in using express-saml2 idp I end up with a 400 bad request
error at the assertion consumer url from the Okta SP. Is that the same thing you guys are seeing?
The problem now is that it seems I have locked myself out of my account, since if I want to log in (to see the system error log reports in okta), I have to log in using express-saml2, which gives the error...
@sebakerckhof Would you like to send your email to exprsaml2@gmail.com ? I would like to open an admin account for you in okta first.
Yes, I experienced 400 bad request even though I added firstname, lastname, login name and email to the assertions in SAML response. I followed this tutorial to set up inbound SAML.
As discussed in #62, here is the configuration for setting gitlab saml.
docker run --name gitlab-postgresql -d \
--env 'DB_NAME=gitlabhq_production' \
--env 'DB_USER=gitlab' --env 'DB_PASS=password' \
--env 'DB_EXTENSION=pg_trgm' \
--volume /esaml2/postgresql:/var/lib/postgresql \
sameersbn/postgresql:9.6-2
docker run --name gitlab-redis -d \
--volume /esaml2/redis:/var/lib/redis \
sameersbn/redis:latest
docker run --name gitlab -d \
--link gitlab-postgresql:postgresql --link gitlab-redis:redisio \
--publish 10022:22 --publish 10080:80 \
--env 'GITLAB_PORT=10080' --env 'GITLAB_SSH_PORT=10022' \
--env 'GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alpha-numeric-string' \
--env 'GITLAB_SECRETS_SECRET_KEY_BASE=long-and-random-alpha-numeric-string' \
--env 'GITLAB_SECRETS_OTP_KEY_BASE=long-and-random-alpha-numeric-string' \
--env 'OAUTH_SAML_ASSERTION_CONSUMER_SERVICE_URL=http://localhost:10080/users/auth/saml/callback' \
--env 'OAUTH_SAML_IDP_CERT_FINGERPRINT=77:36:12:0B:32:9A:6D:61:29:E1:0D:13:C0:FF:63:1A:B9:22:FC:3C' \
--env 'OAUTH_SAML_IDP_SSO_TARGET_URL=http://localhost:3001/sso/SingleSignOnService/gitlab' \
--env 'OAUTH_SAML_ISSUER=https://gitlab' \
--env 'OAUTH_SAML_NAME_IDENTIFIER_FORMAT=urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress' \
--volume /esaml2/gitlab:/home/git/data \
sameersbn/gitlab:9.1.2
openssl x509 -in ./key/idp/cert.cer -sha1 -noout -fingerprint
http://localhost:10080/users/auth/saml/metadata
remember to modify the acs endpoint to http://localhost:10080/users/auth/saml/callback
After setting up the gitlab, we need to set up the IDP with express-saml2. Beside, the identity provider is an experimental feature in this module.
Since there are some required attributes are required and specified in the Gitlab metadata, so we need to add attributes to the response, so we need to customize response template when we construct the Identity provider.
email
, name
, first_name
and last_name
(I don't find first_name
and last_name
, but I think email
and name
is enough, default is admin@example.com
and Administrator
in docker-gitlab)
And we need to change our metadata by setting WantAuthnRequestsSigned
to false since the request from SP is not signed.
In version 1 of express-saml2, you have to input the loginResponseTemplate
for the attribute part when you construct the identity provider as follow.
var idp1 = require('express-saml2').IdentityProvider({
privateKeyFile: './misc/privkey.pem',
isAssertionEncrypted: false,
privateKeyFilePass: 'q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW',
loginResponseTemplate: '<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="{ID}" Version="2.0" IssueInstant="{IssueInstant}" Destination="{Destination}"><saml:Issuer>{Issuer}</saml:Issuer><samlp:Status><samlp:StatusCode Value="{StatusCode}"/></samlp:Status><saml:Assertion ID="{AssertionID}" Version="2.0" IssueInstant="{IssueInstant}" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"><saml:Issuer>{Issuer}</saml:Issuer><saml:Subject><saml:NameID Format="{NameIDFormat}">{NameID}</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="{SubjectConfirmationDataNotOnOrAfter}" Recipient="{SubjectRecipient}"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="{ConditionsNotBefore}" NotOnOrAfter="{ConditionsNotOnOrAfter}"><saml:AudienceRestriction><saml:Audience>{Audience}</saml:Audience></saml:AudienceRestriction></saml:Conditions><AuthnStatement AuthnInstant="{IssueInstant}"> <AuthnContext><AuthnContextClassRef>AuthnContextClassRef</AuthnContextClassRef></AuthnContext></AuthnStatement><saml:AttributeStatement><saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>{attrUserEmail}</saml:AttributeValue></saml:Attribute><saml:Attribute Name="name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>{attrUserName}</saml:AttributeValue></saml:Attribute><saml:Attribute Name="first_name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>{attrUserFirst}</saml:AttributeValue></saml:Attribute><saml:Attribute Name="last_name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>{attrUserLast}</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>'
}, './misc/metadata_idp1.xml');
The full example for SP-initiated SSO for gitlab will be uploaded later on. The last barrier is the error message Can't verify CSRF token authenticity
.
The metadata from Gitlab specified that it doesn't want the assertion to be signed, so the message related to invalid number of signed elements seems not possible. A ticket will be issued to the Gitlab repo.
There is no problem in the context of ruby-saml since validate_signed_elements
should be fired when only WantAssertionSigned
is true and the logic of toggling is not in this method, then I wonder it's the problem in Omniauth part of Gitlab's implementation. Now the method to validate signed element is always executed no matter WantAssertionSigned
is set to true or false.
The issue is filed here. https://github.com/onelogin/ruby-saml/issues/395
I somehow misunderstood the definition of the WantAssertionSigned
. And right now the IDP in express-saml2 is only signing the assertion instead of giving an option to sign the entire message.
Sounds like we are making progress. Thanks!
@manu-silicon I have successfully made it, the example will be pushed very soon.
@manu-silicon
You can find the example in examples/idp-gitlab
, following the above setup and run npm start
, couple things are modified in the current build.
ds
is added into signature, key info and certificate sectionRemember to activate the SAML connector in your account tab (Profile -> Settings -> Account).
Thanks. I'll check it and report shortly.
I checked and although it doesn't complain anymore after login through my IdP I'm still not logged in on the gitlab side. I'll double check my settings tomorrow.
Finally made it work. Thanks @tngan. Will you update the npm package soon? Quick question about the certificates: should I be using self-signed certificates?
For poc and testing, you can use self-signed certificate, but I don't recommend you use self-signed one in production, and some identity providers even don't allow self-signed certificate.
This thread will be continued, and moved to the example or passify-ce later on.
Apart from our own IdP implementation, examples will be included to show how to work with other 3rd party Identity Providers. You can see the list of IdP as follow:
Inbounded SAML (Examples using express-saml2's IdP)