initial draft

This commit is contained in:
msyu
2025-06-02 16:16:51 +03:00
commit 529334d03b
272 changed files with 22684 additions and 0 deletions
+89
View File
@@ -0,0 +1,89 @@
<!---saml configuration--->
<!---development, stage, and production configurations are managed locally
(under saml/),
because global configuration is uniform --->
<!---common configuration parameters--->
<cfset request.SAML.KEYSTORE_PASS="changeit" />
<cfset request.SAML.KEY_PASS="#request.SAML.KEYSTORE_PASS#" />
<cfset request.SAML.IDP_URL="https://sso.nubes.ru/adfs/ls" />
<!--- environment-specific configuration parameters--->
<!--- development environment, the default one --->
<!---we do not create to have all parameters listed in one place--->
<cfset request.SAML.KEYSTORE_FILE_NAME="C:/lucee/tomcat/lucee-server/context/security/cacerts" />
<!---<cfset request.SAML.CERTIFICATE_ALIAS="VDI_SMISHCHUK10_SAML" />--->
<cfset request.SAML.CERTIFICATE_ALIAS="LUCEE_SAML" /><!--- experiment--->
<cfset request.SAML.baseUrl="https://dat-n-smishch1/svc/saml/" /><!---*** appname--->
<cftry>
<!---production environment--->prod...
<cfinclude template="conf/prod.cfm"/> prod
<cfcatch type="ANY">
<cftry>
<!---stage environment--->stage...
<cfinclude template="conf/stage.cfm"/>stage
<cfcatch type="ANY">dev
<!--- development environment --->
<!--- we could initialise dev params here, but just use defaults --->
</cfcatch>
</cftry>
</cfcatch>
</cftry>
<cfdump var=#request.SAML#/>
<!---
files are copied as follows at deploy: dev->stage->prod
config files have priority: prod>stage (>dev which is the default)
- production environment has conf/prod.cfm file (and can contain conf/stage.cfm, but it doesn't matter)
- stage environment has conf/stage.cfm file
- development environment contains no one of them
But we put into conf/ directory templates-placeholders
named stage_sample.cfm and prod_sample.cfm and
So for dev environment contents of saml/conf directory looks like this:
saml/conf/
prod_sample.cfm
stage_sample.cfm
for stage:
saml/conf/
prod_sample.cfm (optional)
stage.cfm
stage_sample.cfm (optional)
for prod:
saml/conf/
prod.cfm
prod_sample.cfm (optional)
stage.cfm (optional)
stage_sample.cfm (optional)
--->
<!---**** Это рассуждение устарело, выше (кажется, удовлетворительное) решение проблемы--->
<!---
Как хранить конфигурационные данные приложения
В конфиг-файле
Просто, но при деплое dev-test-prod придется подменять конфиг, и где вести эти три конфигурации
Сделать 3 конфиг-файла и выбирать программно нужный
Довольно стандартное решение, но нужны надежные признаки dev,test,prod, а что делать, если какие-то еще хосты или конфигурации надо поддержать
- в том же файле можно перечислить, кто будет dev,test,prod, хоть по маске, хоть как. Только вот на сервере нельзя будет обращаться к локалхосту. Или вообще забанить локалхост
Держать конфигурацию в основной базе
При копировании базы с продуктива восстановлением из бэкапа девелоперская конфигурация затрется; надо осторожно кэшировать данные в Application
Держать конфигурацию в отдельной базе
Плодить БД не хочется. Подошел бы текстовый файл вне веб рута?
Держать конфигурацию в шаренной базе
Одна точка отказа для нескольких приложений
В конфиге выбирать. Очень глубоко зарыто. Можно поднять, собрать конфиги в кучу.
--->
<!---cannot load class through its string name, because no definition for the class with the specified name [org.apache.xml.security.Init] could be found caused by (java.lang.ClassNotFoundException:org.apache.xml.security.Init not found by lucee.core [64];java.lang.ClassNotFoundException:org.apache.xml.security.Init;)
put xmlsec-2.1.1.jar to D:\lucee\tomcat\lib, restart Lucee
No! Could not initialize class org.apache.xml.security.Init
--->
View File
View File
+2
View File
@@ -0,0 +1,2 @@
D:\lucee\jre\bin\keytool.exe -delete -v -alias OFFICE02_SAML -keystore D:\lucee\tomcat\lucee-server\context\security\cacerts -storepass changeit
pause
+2
View File
@@ -0,0 +1,2 @@
D:\lucee\jre\bin\keytool.exe -delete -v -alias LUCEE_SAML -keystore D:\lucee\jre\lib\security\cacerts -storepass changeit
pause
+2
View File
@@ -0,0 +1,2 @@
D:\railo\jre\bin\keytool.exe -delete -v -alias OFFICE02_SAML -keystore D:\railo\jre\lib\security\cacerts -storepass changeit
pause
+23
View File
@@ -0,0 +1,23 @@
REM maybe should run as admin
cd /D "%~dp0"
SET keytool=D:\lucee\jre\bin\keytool.exe
SET keystore=D:\lucee\tomcat\lucee-server\context\security\cacerts
REM SET dname=CN=office02.ad.nubes.ru SAML key pair, OU=office02.ad.nubes.ru, O=NUBES, L=Moscow, C=RU
SET alias=OFFICE02_SAML
SET passwd=changeit
%keytool% -importkeystore ^
-deststorepass %passwd% -destkeypass %passwd% -destkeystore %keystore% ^
-srckeystore office02.ad.nubes.ru.pfx -srcstoretype PKCS12 -srcstorepass ZbUswE9T ^
-srcalias "te-webserver2k-6c5a79ec-75b1-403e-8a44-31f694e74ea3" -destalias OFFICE02_SAML
pause
%keytool% -list ^
-keypass %passwd% ^
-storepass %passwd% ^
-keystore %keystore% ^
-alias %alias% ^
-v
pause
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
D:\lucee\jre\bin\keytool.exe -list -keystore D:/lucee/tomcat/lucee-server/context/security/cacerts -storepass changeit
pause
+2
View File
@@ -0,0 +1,2 @@
D:\lucee\jre\bin\keytool.exe -list -v -keystore D:/lucee/tomcat/lucee-server/context/security/cacerts -storepass changeit
pause
+2
View File
@@ -0,0 +1,2 @@
"%JAVA_HOME%\bin\keytool.exe" -list -v -keystore C:\lucee\tomcat\lucee-server\context\security\cacerts -storepass changeit
pause
+62
View File
@@ -0,0 +1,62 @@
REM maybe should run as admin
cd /D "%~dp0"
SET keytool="%JAVA_HOME%\bin\keytool.exe"
SET keystore=D:/lucee/tomcat/lucee-server/context/security/cacerts
SET dname=CN=dat-n-smishch1 SSL key pair, OU=dat-n-smishch1, O=NUBES, L=Moscow, C=RU
SET alias=LUCEE_SAML
SET passwd=changeit
REM it is important for Lucee to see cert
REM SET keytool=D:\railo\jdk\bin\keytool.exe
REM SET keystore=D:\railo\lib\railo-server\context\security\cacerts
REM SET dname=CN=office02 SAML key pair, OU=offiec02, O=NUBES, L=Moscow, C=RU
REM SET alias=OFFICE02_SAML
REM generate cert + key
%keytool% -v -genkeypair ^
-dname "%dname%" ^
-alias %alias% ^
-keyalg RSA ^
-keysize 2048 ^
-validity 3653 ^
-keypass %passwd% ^
-storepass %passwd% ^
-keystore %keystore%
pause
%keytool% -list ^
-alias %alias% ^
-keypass %passwd% ^
-storepass %passwd% ^
-keystore %keystore% ^
-v
pause
%cd%
REM export cert + key to p12 keystore
%keytool% -importkeystore ^
-alias %alias% ^
-srckeystore %keystore% ^
-destkeystore keystore.p12 ^
-deststoretype PKCS12 ^
-srckeypass %passwd% ^
-srcstorepass %passwd% ^
-deststorepass %passwd% ^
-destkeypass %passwd%
pause
:export
REM U should convert .p12 keystore to .pem format for sending your cert and key to adfs administrator, 'openssl pkcs12 -in keystore.p12 -out saml.pem'
%keytool% -exportcert ^
-alias %alias% ^
-keypass %passwd% ^
-keystore %keystore% ^
-storepass %passwd% ^
-rfc ^
-file LUCEE_SAML.pem
pause
+62
View File
@@ -0,0 +1,62 @@
REM maybe should run as admin
cd /D "%~dp0"
SET keytool="%JAVA_HOME%\bin\keytool.exe"
SET keystore=C:/lucee/tomcat/lucee-server/context/security/cacerts
SET dname=CN=dat-n-smishch1 SAML key pair, OU=dat-n-smishch1, O=NUBES, L=Moscow, C=RU
SET alias=LUCEE_SAML
SET passwd=changeit
REM it is important for Lucee to see cert
REM SET keytool=D:\railo\jdk\bin\keytool.exe
REM SET keystore=D:\railo\lib\railo-server\context\security\cacerts
REM SET dname=CN=office02 SAML key pair, OU=offiec02, O=NUBES, L=Moscow, C=RU
REM SET alias=OFFICE02_SAML
goto export
REM generate cert + key
%keytool% -v -genkeypair ^
-dname "%dname%" ^
-alias %alias% ^
-keyalg RSA ^
-keysize 2048 ^
-validity 3653 ^
-keypass %passwd% ^
-storepass %passwd% ^
-keystore %keystore%
pause
%keytool% -list ^
-alias %alias% ^
-keypass %passwd% ^
-storepass %passwd% ^
-keystore %keystore% ^
-v
pause
%cd%
REM export cert + key to p12 keystore
%keytool% -importkeystore ^
-alias %alias% ^
-srckeystore %keystore% ^
-destkeystore keystore.p12 ^
-deststoretype PKCS12 ^
-srckeypass %passwd% ^
-srcstorepass %passwd% ^
-deststorepass %passwd% ^
-destkeypass %passwd%
pause
:export
REM U should convert .p12 keystore to .pem format for sending your cert and key to adfs administrator, 'openssl pkcs12 -in keystore.p12 -out saml.pem'
%keytool% -exportcert ^
-alias %alias% ^
-keypass %passwd% ^
-keystore %keystore% ^
-storepass %passwd% ^
-rfc ^
-file LUCEE_SAML.pem
pause
+47
View File
@@ -0,0 +1,47 @@
REM maybe should run as admin
CD /d .
SET keytool="%JAVA_HOME%\bin\keytool.exe"
SET keystore=C:/lucee/tomcat/lucee-server/context/security/cacerts
SET dname=CN=dat-n-smishch1 SAML key pair, OU=dat-n-smishch1, O=NUBES, L=Moscow, C=RU
SET alias=LUCEE_SAML
SET passwd=changeit
REM SET keytool=D:\railo\jdk\bin\keytool.exe
REM SET keystore=D:\railo\lib\railo-server\context\security\cacerts
REM SET dname=CN=office02 SAML key pair, OU=offiec02, O=NUBES, L=Moscow, C=RU
REM SET alias=OFFICE02_SAML
REM generate cert + key
%keytool% -v -genkeypair ^
-dname "%dname%" ^
-alias %alias% ^
-keyalg RSA ^
-keysize 2048 ^
-validity 3653 ^
-keypass %passwd% ^
-storepass %passwd% ^
-keystore %keystore%
pause
%keytool% -v -list ^
-alias %alias% ^
-keypass %passwd% ^
-storepass %passwd% ^
-keystore %keystore%
pause
REM export cert + key to p12 keystore
%keytool% -importkeystore ^
-alias %alias% ^
-srckeystore %keystore% ^
-destkeystore keystore.p12 ^
-deststoretype PKCS12 ^
-srckeypass %passwd% ^
-srcstorepass %passwd% ^
-deststorepass %passwd% ^
-destkeypass %passwd%
pause
REM U should convert .p12 keystore to .pem format for sending your cert and key to adfs administrator, 'openssl pkcs12 -in keystore.p12 -out saml.pem'
Binary file not shown.
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
D:\lucee\jre\bin\keytool.exe -importkeystore ^
-deststorepass changeit -destkeypass changeit -destkeystore temp.keystore ^
-srckeystore office02.ad.nubes.ru.pfx -srcstoretype PKCS12 -srcstorepass ZbUswE9T
pause
D:\lucee\jre\bin\keytool.exe -list -keystore temp.keystore -storepass changeit -v
pause
+8
View File
@@ -0,0 +1,8 @@
<!---template for saml configuration:
parameters, specific for production environment--->
<!---in production, this file should be named prod.cfm--->
<cfset request.SAML.KEYSTORE_FILE_NAME="D:/lucee/tomcat/lucee-server/context/security/cacerts" />
<cfset request.SAML.CERTIFICATE_ALIAS="OFFICE02_SAML" />
<cfset request.SAML.baseUrl="https://office02.ad.nubes.ru/svc/saml/" />
+8
View File
@@ -0,0 +1,8 @@
<!---template for saml configuration:
parameters, specific for production environment--->
<!---in production, this file should be named prod.cfm--->
<cfset request.SAML.KEYSTORE_FILE_NAME="D:/railo/lib/railo-server/context/security/cacerts" />
<cfset request.SAML.CERTIFICATE_ALIAS="OFFICE02_SAML" />
<cfset request.SAML.baseUrl="https://office02.ad.nubes.ru/svc/saml/" /><!---config placeholder for stage environment--->
+239
View File
@@ -0,0 +1,239 @@
18:32 11.05.2018
Метаданные:
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="https:__vdi-smishchuk.dtln.local_mms_saml_metadata.cfm" entityID="https://vdi-smishchuk.dtln.local/mms/saml/metadata.cfm" validUntil="2018-05-13T15:31:08Z" cacheDuration="PT604800S">
<md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>
MIIDszCCApugAwIBAgIEZ+Y5QzANBgkqhkiG9w0BAQsFADCBiTELMAkGA1UEBhMCUlUxDzANBgNVBAcTBk1vc2NvdzEVMBMGA1UEChMMRGF0YWxpbmUgTExDMSEwHwYDVQQLExh2ZGktc21pc2hjaHVrLmR0bG4ubG9jYWwxLzAtBgNVBAMTJnZkaS1zbWlzaGNodWsuZHRsbi5sb2NhbCBTQU1MIGtleSBwYWlyMB4XDTE4MDUxMTEwMzc1NloXDTI4MDUxMTEwMzc1NlowgYkxCzAJBgNVBAYTAlJVMQ8wDQYDVQQHEwZNb3Njb3cxFTATBgNVBAoTDERhdGFsaW5lIExMQzEhMB8GA1UECxMYdmRpLXNtaXNoY2h1ay5kdGxuLmxvY2FsMS8wLQYDVQQDEyZ2ZGktc21pc2hjaHVrLmR0bG4ubG9jYWwgU0FNTCBrZXkgcGFpcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIi2IftGa1xi6KmhojTi/gSbRFfZpFyQw1V9YhMo4PgzsJz5tKKPlK/TPJX+P8Gu2OOYlkH2zjjYM9rCmNrdnViVqnlKk0E6cUBeQoKZxGN9GmjHvCONsScLxGMpho+YdNbFAga/OiK3myJeNSGc+tKkyQGUTrXQAK4ZvR0bUy/SkfFjjRA9RJLdBZlA6l1DSht1c6HMV3/tRdWxfwszQ+MK45eFHs6NmSjb6VESFXE6fIsa+JKLSOyjPVaNJeYp2fHSEvA6/mxQYl4AxzGilV7acaFgP8JWdBGuOM+ruyuAH3eAXqVvV/9HiYNPflL5VxKT0/rG50+qpKxTACwgX/kCAwEAAaMhMB8wHQYDVR0OBBYEFLF3U+R9xuCkVjkBpLZO+evGgjS+MA0GCSqGSIb3DQEBCwUAA4IBAQAnTSgsmf1JdT3TVZcCODMkj0UgvhNt9tFTCcBsdYnuMmATZ1ktGaGc3iDd5qynopC55u7VzkyH8S+RXqf5rw6OSTmEWgoNYoKXQXkE0U/LUI0Zurc/OciT6KqOprgqr0JEtV+htaJpAhL1iQ0q+Yi6dmlwRD1c8LOFy5dEwwho4acrDjI6WUNN/eedO9/SJWqpC5ZbzreeUUfcO3vJcRHNY++o8TmK6trJU/DR18G8pBzVPRpjJw9YvzOlw106gk1Vyp0J5OIHB0jpFCHzGYBwBB2XgAso6VgTIiJ2Gd08jSuq+UjvClB9mgA2+vG8jiHFaf8DKSqWjOfxie96S9Ff
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>
MIIDszCCApugAwIBAgIEZ+Y5QzANBgkqhkiG9w0BAQsFADCBiTELMAkGA1UEBhMCUlUxDzANBgNVBAcTBk1vc2NvdzEVMBMGA1UEChMMRGF0YWxpbmUgTExDMSEwHwYDVQQLExh2ZGktc21pc2hjaHVrLmR0bG4ubG9jYWwxLzAtBgNVBAMTJnZkaS1zbWlzaGNodWsuZHRsbi5sb2NhbCBTQU1MIGtleSBwYWlyMB4XDTE4MDUxMTEwMzc1NloXDTI4MDUxMTEwMzc1NlowgYkxCzAJBgNVBAYTAlJVMQ8wDQYDVQQHEwZNb3Njb3cxFTATBgNVBAoTDERhdGFsaW5lIExMQzEhMB8GA1UECxMYdmRpLXNtaXNoY2h1ay5kdGxuLmxvY2FsMS8wLQYDVQQDEyZ2ZGktc21pc2hjaHVrLmR0bG4ubG9jYWwgU0FNTCBrZXkgcGFpcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIi2IftGa1xi6KmhojTi/gSbRFfZpFyQw1V9YhMo4PgzsJz5tKKPlK/TPJX+P8Gu2OOYlkH2zjjYM9rCmNrdnViVqnlKk0E6cUBeQoKZxGN9GmjHvCONsScLxGMpho+YdNbFAga/OiK3myJeNSGc+tKkyQGUTrXQAK4ZvR0bUy/SkfFjjRA9RJLdBZlA6l1DSht1c6HMV3/tRdWxfwszQ+MK45eFHs6NmSjb6VESFXE6fIsa+JKLSOyjPVaNJeYp2fHSEvA6/mxQYl4AxzGilV7acaFgP8JWdBGuOM+ruyuAH3eAXqVvV/9HiYNPflL5VxKT0/rG50+qpKxTACwgX/kCAwEAAaMhMB8wHQYDVR0OBBYEFLF3U+R9xuCkVjkBpLZO+evGgjS+MA0GCSqGSIb3DQEBCwUAA4IBAQAnTSgsmf1JdT3TVZcCODMkj0UgvhNt9tFTCcBsdYnuMmATZ1ktGaGc3iDd5qynopC55u7VzkyH8S+RXqf5rw6OSTmEWgoNYoKXQXkE0U/LUI0Zurc/OciT6KqOprgqr0JEtV+htaJpAhL1iQ0q+Yi6dmlwRD1c8LOFy5dEwwho4acrDjI6WUNN/eedO9/SJWqpC5ZbzreeUUfcO3vJcRHNY++o8TmK6trJU/DR18G8pBzVPRpjJw9YvzOlw106gk1Vyp0J5OIHB0jpFCHzGYBwBB2XgAso6VgTIiJ2Gd08jSuq+UjvClB9mgA2+vG8jiHFaf8DKSqWjOfxie96S9Ff
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://vdi-smishchuk.dtln.local/mms/saml/logout.cfm"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://vdi-smishchuk.dtln.local/mms/saml/logout.cfm"/>
<md:NameIDFormat>
urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
</md:NameIDFormat>
<md:NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:transient
</md:NameIDFormat>
<md:NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
</md:NameIDFormat>
<md:NameIDFormat>
urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
</md:NameIDFormat>
<md:NameIDFormat>
urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
</md:NameIDFormat>
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://vdi-smishchuk.dtln.local/mms/saml/sso.cfm" index="0" isDefault="true"/>
<md:AssertionConsumerService xmlns:hoksso="urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser" Binding="urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser" Location="https://vdi-smishchuk.dtln.local/mms/saml/hoksso.cfm" hoksso:ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" index="1"/>
</md:SPSSODescriptor>
</md:EntityDescriptor>
Респонс:
<samlp:Response ID="_906304e3-997d-45bc-8796-d25af0abc424" Version="2.0" IssueInstant="2018-05-11T15:28:37.941Z" Destination="https://vdi-smishchuk.dtln.local/mms/saml/sso.cfm" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" InResponseTo="id2A4900FD-BAB2-4182-95027AF283B0311A" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">http://adfs.dtln.local/adfs/services/trust</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="#_906304e3-997d-45bc-8796-d25af0abc424">
<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/2001/04/xmlenc#sha256" />
<ds:DigestValue>pMECHm07laxWFPMkrmXUlWmNa8NJcoVtq6pNxqLOOHk=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>eDuI0bjq0iii5nm0lj8hUrAOm+4Vnkm5a6PlK1crdFYz5bf6TpQlqnCUbXVDByDvBwdJRvaGYg2MDhRcgOcjADRS4vLdzZN3lDBfVEZ8YGwkiK0lrVjsh8EdkEUl+3mHWbGgLhCNRg0auJEXwlvp7goBqeTtJ9/jcNg9T6RWspUZ6b8De07B02KNi54NpdeFRlZ3JUSRODepgDwO6eLnCw/tGGFpOwKL4CrbT2E+UTDygIylAYyoh1YdkIZQm+My3tWDI7LQh2uwaFU9lZk+t/KqoIQwngnoCnOlmPijXLFZ8vSsdcd62PTy8DTIGsziiochZ+Fb3bOsf6mLF5b0BQ==</ds:SignatureValue>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIIC2jCCAcKgAwIBAgIQRkugSLS1sq1JtGCxzdsvDTANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDEx5BREZTIFNpZ25pbmcgLSBhZGZzLmR0bG4ubG9jYWwwHhcNMTgwNDIyMDk1MzIzWhcNMTkwNDIyMDk1MzIzWjApMScwJQYDVQQDEx5BREZTIFNpZ25pbmcgLSBhZGZzLmR0bG4ubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtVjQVaHUIurxJQVZYze5ERKvVrGoTc+5qZZ7a72IAgw2WVU/KxLGQXn2Yxk1f2Gs4nsG/4iwLeLyIZUPLWqCylURGzQLqv0jy+G0HxXE0kDkMO97s8n7K0vzd58cY6nQofq8kN/IujXzV++KpDRD1hpX3znBegCVgb6RCuozeG8u5eT3LctYQWv/8y5VZuY8pKsGWT3X/LM8f//XBVgYfzMvCrx+7muHC09MHPfrcZ6zacXZaTyT7urVVqQ5uTjiFaQDirRSVeBfGsRpqAMuTTHSDoVVGyNHtqMeIAHbOYyBnOQRaFNY9yHnkJVIN2FMgZ8oCs6LwYxbWUkyNvA53AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIQm2zh/73Dba69c+07vbhIDbnBuM1QBjcrTFC4m5NbPvLD/yh8mW6pipYsj5b9SZReJxjlCrvAwqNReafN44BUARD0GzUv2x5sRuAoFpx8MbUzYEdf2HJe+OOPwfeNZ8fUa6v986kslYHFXfEfS1/rB54EFNcTU0LOwG/FR6kfV0PvpzAg4KEl3BDv9rQVOGMu6cPvHFm66HpTnfwKXRe1qMiQlaeeATjeiDzdTBFBhZoLvUPymM22iSKRT4u3YQIIEXT3OiuXuJM9h66CYNvCTkQF0vRSnEpCjNZfsNjknimNIX2dz6IeXpzYQCPV4PdNM94jTInZ+JWwFzFWANjo=</ds:X509Certificate>
</ds:X509Data>
</KeyInfo>
</ds:Signature>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder" />
</samlp:Status>
</samlp:Response>
Потому что обращался к себе по локалхосту или короткому имени, а надо по полному имени vdi-smishchuk.dtln.local (делать, что ли, редирект? или пробивать имя своего хоста в настройках)
13:22 14.05.2018
С полным именем работает, но Ассершен не возвращает
Логаут полный не отработал, простой отработал, но ассершен все равно не.
Ругается на отсутствие подписи, хотя в метаданных декларирует, что подпись будет AuthnRequestsSigned="true"
Теперь алгоритм подписи не тот. У меня SHA1, а он ожидает SHA256
ADFS metadata: https://adfs.dtln.local/FederationMetadata/2007-06/FederationMetadata.xml
там есть упоминание sha256, но только про себя, про SP не говорит
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
Не в первый раз возникает:
file or directory }Rj0,ywch 9RYnDmxϯ
G7on`i}0 OI/m82|iC0Dyg92zB"o^NO41Mp?w0Bn+i3w>IE#*npP4%0+&CL 4 RVf2zG+3)hJUp4ǒhCe1$ ǹ TmLe𦅿3@7%$;:Yb=r~L#3|l4;:1[? not exist
Очевидно, райло думает, что я даю ему имя файла
Говорят - потому что не может распарсить. Его можно понять
Теперь новая измена при логине
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder" />
</samlp:Status>
*** наверно, неплохо проверять статус?
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
в незашифрованной части документа
На Logout приходит то SAML_request, то SAML_Request, то SAML_Response
Оказывается, она присылает то постом, то гетом. Вероятно, от этого зависит и кодирование!
Эта прекрасная тулза https://rnd.feide.no/simplesaml/module.php/saml2debug/debug.php прекрасно декодирует (ссылка с https://www.experts-exchange.com/questions/28521347/Decipher-SAML-Response-From-ADFS-Server-using-ColdFusion.html)
Попробовал без успеха: https://gist.github.com/guillaumemolter/3e210855881ec5f09294
18:19 14.05.2018
Думаю, что надо на Редирект давать Ассершен логаута
17:14 15.05.2018
SAML:2.0:status:Responder
Теперь не могу законнектиться. Такое чувство, что зря поменял на SHA256
https://social.technet.microsoft.com/Forums/en-US/4acc04b7-aac7-43e9-ba50-9570503045f9/msis0038-saml-message-has-wrong-signature?forum=windowsazureaditpro
Попробовал SHA1 то же самое ADFS:MSIS0038: SAML Message has wrong signature
10:24 16.05.2018
Если не подписывать запрос (обратное было отражено в метаданных AuthnRequestsSigned="true") то вроде все работает
Вот, теперь не могу отлогиниться
Трассирую хромом
Оказывается, при простом логауте получаю такую телегу
SAMLRequest:
<?xml version="1.0" encoding="UTF-8"?>
<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" Destination="https://vdi-smishchuk.dtln.local/mms/saml/logout.cfm" ID="_a9c2be02-8823-4d6d-b73f-5f06906af60d" IssueInstant="2018-05-16T09:15:51.899Z" NotOnOrAfter="2018-05-16T09:20:51.899Z" Version="2.0">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">http://adfs.dtln.local/adfs/services/trust</Issuer>
<NameID xmlns="urn:oasis:names:tc:SAML:2.0:assertion">smishchuk</NameID>
<samlp:SessionIndex>_0a607a2f-c124-4b0f-9245-c476a24a9344</samlp:SessionIndex>
<samlp:SessionIndex>_e79a1300-00c3-4426-a64f-879c43de5a94</samlp:SessionIndex>
<samlp:SessionIndex>_7f1dc8d5-9b0c-4f8b-b59c-1a1905609cd3</samlp:SessionIndex>
</samlp:LogoutRequest>
Потом сбросилось.
Похоже, при каждом логине ИдП дает новый индекс сессии, даже не справшивая пароля
13:40 06.06.2018
System.NotSupportedException: MSIS0023: SAML signature type 'http://www.w3.org/2000/09/xmldsig#rsa-sha256' is not supported by the HTTP Redirect binding serializer at this time.
Сделать постом?
12:15 07.06.2018
был неправильный урл криптоалгоритма правильно: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
Почти хорошо, только возвращает в первый раз
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder" />
Если повторить запрос - редиректит куда надо и присылает группы
Попробуем трассировать https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/
11:04 08.06.2018
ошибка в метаданных
исправил
11:07 08.06.2018
Saml
https://vdi-smishchuk.dtln.local/mms/saml/metadata.cfm
Microsoft.IdentityModel.Protocols.XmlSignature.SignatureVerificationFailedException: MSIS0038: SAML Message has wrong signature. Issuer: 'https://vdi-smishchuk.dtln.local/mms/saml/metadata.cfm'.
Нашел еще 1 параметр в урле, которого у меня нет RelayState: https://infong-dev.dtln.local/sso/login
10:43 09.06.2018
&client-request-id=18ee542a-04ee-4fb7-ba19-0080000000f9
Вижу разночтение
https://adfs.dtln.local/adfs/ls/?SAMLRequest=nVNdb9MwFH3upP0Hy%2B%2F5ateus9ZOWUpFpQFRm%2FHAm3FcauGP4Ot03b%2FHcShECCpEXqL4nnvuuec49w8nJdGRWxBGL3AWpxhxzUwt9JcFfq7W0Rw%2FLK%2BvUPfcA1Vy3JC8dQe95d9aDu76aoQ8hQbSFxe4tZoYCgKIpooDcYzs8ndPZBynpLHGGWYk%2Fq3tchcF4NZ5gRh1fZvVAos6zWZFPh5n0Twv7qKb2U0RPb6Z3k1ui9ntJFuvZ%2Bt5D%2F94Xs5ThbmlNUdRc%2FveD1rgXYmc3yNUNgAt32hwVDuPT7N5lM6idF5lUzKekkn6KcBWHi80dYH14FwDJElovYe4dlLH0jAqw3ciITmPDHs%2FCt07e2ndzz0IyNuqKqPyw64KHPnZhcJoaBW3O26PgvHn7dMvFcdaRKAEHNih%2FTqUoxQkndUJgInZXmE0Qt6eLtmO3Ec8GvX5kuCC%2FZ94lv8uQ3FHa%2Bpop%2BU%2BGQ4eSGlIl9FmVRop2CtaG6uo%2B7uYLM7CiaijfYCSVkPDmdgLXmOUS2leCsup87E723KcLNFw2I8rzetwwb3Njp8cKoxqqBXQhc1PlDncd53tGoIL6c3Y8v3yol%2BMsA7nj0v%2FejG27u4HZ35yZamXbKw7e%2FJH9iA6uaS6g6CfkOEP6yvfAQAAAAAAAAAAAAA%3D&SigAlg=http%3A%2F%2Fwww%2Ew3%2Eorg%2F2001%2F04%2Fxmldsig%2Dmore%23rsa%2Dsha256&RelayState=https%3A%2F%2Fvdi%2Dsmishchuk%2Edtln%2Elocal%2Fmms%2Fsaml%2Fsso%2Ecfm&Signature=OKVrDbguCzLO0qzFmzNnGpWymCcu97nMyiYe7r1rhQVRgofNYOA3d0bPpjwMGn%2Bcz1WefeX7s%2BvZABXwunwJEC99Tqy9iYhqDpiNYze8rwFbYGnRJUOJVBCtCX2NUYthOlOzVlb%2B1B31NvW70jhBonr3i7syD5Lg4aJpHqaTfAh7ayPdABTlI%2FKjZd2BsHxKH%2F3gh7zQ%2B3VS2tJ2NEUGDwNeJwauG7mxDL4WNZvBIb%2FBQ4UvllfZ3A5rQNwh5c%2BB7qu16%2FAy3j27LpC12xrOPITJuFueoZEa%2BjAs5QjU2Pj%2BndhlT0MH5Az2dqKPI6if%2FTTFYBZleycgRzIwMOkD8g%3D%3D
https://adfs.dtln.local/adfs/ls/?SAMLRequest=nVNdb9MwFH3upP0Hy%2B%2F5ateus9ZOWUpFpQFRm%2FHAm3FcauGP4Ot03b%2FHcShECCpEXqL4nnvuuec49w8nJdGRWxBGL3AWpxhxzUwt9JcFfq7W0Rw%2FLK%2BvUPfcA1Vy3JC8dQe95d9aDu76aoQ8hQbSFxe4tZoYCgKIpooDcYzs8ndPZBynpLHGGWYk%2Fq3tchcF4NZ5gRh1fZvVAos6zWZFPh5n0Twv7qKb2U0RPb6Z3k1ui9ntJFuvZ%2Bt5D%2F94Xs5ThbmlNUdRc%2FveD1rgXYmc3yNUNgAt32hwVDuPT7N5lM6idF5lUzKekkn6KcBWHi80dYH14FwDJElovYe4dlLH0jAqw3ciITmPDHs%2FCt07e2ndzz0IyNuqKqPyw64KHPnZhcJoaBW3O26PgvHn7dMvFcdaRKAEHNih%2FTqUoxQkndUJgInZXmE0Qt6eLtmO3Ec8GvX5kuCC%2FZ94lv8uQ3FHa%2Bpop%2BU%2BGQ4eSGlIl9FmVRop2CtaG6uo%2B7uYLM7CiaijfYCSVkPDmdgLXmOUS2leCsup87E723KcLNFw2I8rzetwwb3Njp8cKoxqqBXQhc1PlDncd53tGoIL6c3Y8v3yol%2BMsA7nj0v%2FejG27u4HZ35yZamXbKw7e%2FJH9iA6uaS6g6CfkOEP6yvfAQAAAAAAAAAAAAA%3D&SigAlg=http:%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&RelayState=https:%2F%2Fvdi-smishchuk.dtln.local%2Fmms%2Fsaml%2Fsso.cfm&Signature=OKVrDbguCzLO0qzFmzNnGpWymCcu97nMyiYe7r1rhQVRgofNYOA3d0bPpjwMGn%2Bcz1WefeX7s%2BvZABXwunwJEC99Tqy9iYhqDpiNYze8rwFbYGnRJUOJVBCtCX2NUYthOlOzVlb%2B1B31NvW70jhBonr3i7syD5Lg4aJpHqaTfAh7ayPdABTlI%2FKjZd2BsHxKH%2F3gh7zQ%2B3VS2tJ2NEUGDwNeJwauG7mxDL4WNZvBIb%2FBQ4UvllfZ3A5rQNwh5c%2BB7qu16%2FAy3j27LpC12xrOPITJuFueoZEa%2BjAs5QjU2Pj%2BndhlT0MH5Az2dqKPI6if%2FTTFYBZleycgRzIwMOkD8g%3D%3D&client-request-id=bdb01962-e04c-4505-6006-0080000000c6
А как в работающем варианте
https://adfs.dtln.local/adfs/ls/?SAMLRequest=fVNNj9owEL3vr4hyD0mgQNaCSBT6gUQhgrSHXipjT1hLjp16HJb997WzbGGlNrlYnnnvzbzxZIa0lg1ZtPZJ7eF3C2gfguBSS4WkS83D1iiiKQokitaAxDJyWHzbkOEgIY3RVjMtw3ekfg5FBGOFVp60Xs3D3fbTZvdlvf2VJSw78nSYTbLx5DgdfoAxJFM%2BrhJ49AlGj%2BPpaJR64g8w6DTmoZP09yAojD4LDmbrKs7DQxFYZ6argdjCWqGlyjp8kmZRMomSrEymZJSR9PGnR60cWihqO9EnaxskcUx5hQNupRpIzajs7rHE2BOKq%2FePQnGhTv2mj68gJF%2FLsoiK3aH0Eou3USy1wrYGcwBzFgy%2B7ze3HoSqtDpFHM73nSDqWOrTCXiYd%2FZnfvKk82ryXu4svofeyA3xo1uvCi0Fe%2Bni%2FvusTU3t%2F%2B2lg7SLCB5VHZS0ChtgohKuub8yCyn189IAte51rGkhDOJ3xa%2FrB7xbRjcRCxcbLHXdUCPQvwpcKLNXuzfL9%2FCldNu1hyrvXUBGmMe5cOGOZ224f0tgrnZpqGteG3sd0j%2FFX7uOe9rOH97S939W%2Fgc%3D&RelayState=https%3A%2F%2Finfong-dev.dtln.local%2Fsso%2Flogin&Signature=AMgdc0Doiznf7v5240ZHq6pqw5ms1C%2FFb2cxRv%2Ft%2F85HgzhsShy3F4H15%2BvT0kbscrLF%2B6EEVqHY0tVI%2BYZH1IOfryHU4b7e9DdsKRKUusJ9b3GK%2BiQeyt5lIB3VPZyWQ6bndMJ353R4AhBkYF4%2B0Ilk3fHYsOhATPl8yGNtMn9PrBQ9N5Dh320fcrPO19v3Qv%2B8Hbu1Z2kw2qRyI4E9rPuTnn1n3q0ybBHl1OtW23EMlnW7Grp5Gfvf3EcLd68FdAT6SPlaBIeFVZmtQ92eugYxXEgMFD241d8P1iVDyeJI3SBUX%2FcuyaBVQ%2BT1Y4G6dLIh7MfUDh2V55xAHijZBg%3D%3D&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256
https://adfs.dtln.local/adfs/ls/?SAMLRequest=fVNNj9owEL3vr4hyD0mgQNaCSBT6gUQhgrSHXipjT1hLjp16HJb997WzbGGlNrlYnnnvzbzxZIa0lg1ZtPZJ7eF3C2gfguBSS4WkS83D1iiiKQokitaAxDJyWHzbkOEgIY3RVjMtw3ekfg5FBGOFVp60Xs3D3fbTZvdlvf2VJSw78nSYTbLx5DgdfoAxJFM%2BrhJ49AlGj%2BPpaJR64g8w6DTmoZP09yAojD4LDmbrKs7DQxFYZ6argdjCWqGlyjp8kmZRMomSrEymZJSR9PGnR60cWihqO9EnaxskcUx5hQNupRpIzajs7rHE2BOKq%2FePQnGhTv2mj68gJF%2FLsoiK3aH0Eou3USy1wrYGcwBzFgy%2B7ze3HoSqtDpFHM73nSDqWOrTCXiYd%2FZnfvKk82ryXu4svofeyA3xo1uvCi0Fe%2Bni%2FvusTU3t%2F%2B2lg7SLCB5VHZS0ChtgohKuub8yCyn189IAte51rGkhDOJ3xa%2FrB7xbRjcRCxcbLHXdUCPQvwpcKLNXuzfL9%2FCldNu1hyrvXUBGmMe5cOGOZ224f0tgrnZpqGteG3sd0j%2FFX7uOe9rOH97S939W%2Fgc%3D&RelayState=https%3A%2F%2Finfong-dev.dtln.local%2Fsso%2Flogin&Signature=AMgdc0Doiznf7v5240ZHq6pqw5ms1C%2FFb2cxRv%2Ft%2F85HgzhsShy3F4H15%2BvT0kbscrLF%2B6EEVqHY0tVI%2BYZH1IOfryHU4b7e9DdsKRKUusJ9b3GK%2BiQeyt5lIB3VPZyWQ6bndMJ353R4AhBkYF4%2B0Ilk3fHYsOhATPl8yGNtMn9PrBQ9N5Dh320fcrPO19v3Qv%2B8Hbu1Z2kw2qRyI4E9rPuTnn1n3q0ybBHl1OtW23EMlnW7Grp5Gfvf3EcLd68FdAT6SPlaBIeFVZmtQ92eugYxXEgMFD241d8P1iVDyeJI3SBUX%2FcuyaBVQ%2BT1Y4G6dLIh7MfUDh2V55xAHijZBg%3D%3D&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&client-request-id=18ee542a-04ee-4fb7-ba19-0080000000f9
Теперь мы видим удивительную вещь, у меня дефис кодируется UrlEncodedFormat, а у них нет. После раундтрипа мои параметры имеют уже другие значения, %2D преобразовался обратно в минус. То ли это стандарт, то ли сервер это делает, то ли клиент.
А когда у меня SHA1, то в урле нету дефисов, и этот баг не проявляется
Полагаю, то же самое будет, когда я буду пользоваться сразу постом
Sic! https://www.bennadel.com/blog/2656-url-encoding-amazon-s3-resource-keys-for-pre-signed-urls-in-coldfusion.htm
reserved=;/?:@&=+$,
http://localhost/mms/saml/sso.cfm?mark=-_.!~*'()
http://localhost/mms/saml/sso.cfm?mark=%2D%5F%2E%21%7E%2A%27%28%29&mark=-_.!~*'()
14:56 09.06.2018
fixed...
А зачем мы используем HTTP POST binding? Чем редирект нас не радует?
А вот чем: HTTP 413, он ответ отправляет редиректом и он не помещается в урлу
Хочется понять, как пост попадает на мой сервер SP
Теперь не могу отлогиниться
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Requester"/>
13:08 13.06.2018
NotOnOrAfter не означает истечения сессии
adfs sessionNotOnOrAfter not supported?
https://aws.amazon.com/ru/blogs/security/enable-your-federated-users-to-work-in-the-aws-management-console-for-up-to-12-hours/
https://www.owasp.org/index.php/SAML_Security_Cheat_Sheet
13:20 19.06.2018
проверка подписи оказалась сложнее, чем я думал http://blog.tagworldwide.com/?p=19
https://stackoverflow.com/questions/26265727/unable-to-validate-saml-assertion-with-coldfusion
The Reference for URI #_abc42efe-bcaa-43dc-b1c3-3ac2d3c99d5e has no XMLSignatureInput
получилось
assertionArray = XMLSearch(SAMLResponseXml, "/*[name()='samlp:Response']/*[name()='EncryptedAssertion']/*[name()='Assertion']");
assertionElement = assertionArray[1];
assertionElement.setIdAttribute("ID",true); //sic!
16:22 27.03.2019
Добавил xmlsec-2.1.1.jar в railo/lib
Error
illegal key size
//see https://backstage.forgerock.com/knowledge/kb/article/a17171105
see https://myshittycode.com/2016/02/18/java-saml-illegal-key-size/
put local_policy.jar, US_export_policy.jar to railo\jdk\jre\lib\security, reboot railo
OK works
на Railo
10:08 02.04.2019 проблемы на Lucee Could not initialize class org.apache.xml.security.Init
Возможно, библиотека xmlsec конфликтует?
Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.apache.xml.security.Init
Переименовать файл D:\lucee\tomcat\lib\xmlsec-2.1.1.jar при этом не дает
//Init = CreateObject("Java", "org.apache.xml.security.Init").Init().init();
ref = createObject("java", "org.apache.xml.security.Init");
// initialize if needed
if (!ref.isInitialized()) {
// find static method named "init" with no parameters
method = ref.getClass().getDeclaredMethod("init", []);
// invoke it via reflection
method.invoke(ref, javacast("null", ""));
}
- сложный способ инициализации оказался ничем не лучше простого
Если изменить имя класса
cannot load class through its string name, because no definition for the class with the specified name [org.apache.xml.security.Init1] could be found caused by (java.lang.ClassNotFoundException:org.apache.xml.security.Init1 not found by lucee.core [64];java.lang.ClassNotFoundException:org.apache.xml.security.Init1;)
https://stackoverflow.com/questions/30887240/exception-noclassdeffounderror-org-apache-xml-security-init ссылаются на логирование. И у меня при первом вызове ругань на slf4j
java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
В D:\lucee\tomcat\lucee-server\bundles имеются slf4j.api-1.7.12.jar, slf4j.nop-1.7.12.jar,
но в райло slf4j-nop.jar slf4j-api-1.7.22.jar slf4j-api.jar
причем slf4j-api-1.7.22.jar новее (2016 год)
Попробовать обновиться? Current version: 5.2.9.31
5.3.1.102
не помогло
для опыта вовсе дизейблил
Кстати. Log4J not loaded (может, потому что slf4j дизейблил, никто и не грузит)
Ни фига, jar пересоздались
подложил в верхнюю либу файлы от Райло, перезапустил Люси - и вот, все взлетело. Теперь надо
+57
View File
@@ -0,0 +1,57 @@
<!---v0.2 13:19 12.01.2021--->
<cfinclude template="app_saml_config.cfm"/>
<cfinclude template="saml.cfm"/>
<cfparam name="target_page" default=""/>
<cfset ksFile = CreateObject("Java", "java.io.File").init(request.SAML.KEYSTORE_FILE_NAME) />
<cfset ksInputStream = CreateObject("Java", "java.io.FileInputStream").init(ksFile) />
<cfset keystore = CreateObject("Java", "java.security.KeyStore").getInstance("JKS") />
<cfset keystore.load(ksInputStream, request.SAML.KEYSTORE_PASS.toCharArray()) />
<!---<cfset certificate = keystore.getCertificate(request.SAML.CERTIFICATE_ALIAS) />--->
<cfset privateKey = keystore.getKey(request.SAML.CERTIFICATE_ALIAS, request.SAML.KEY_PASS.toCharArray()) />
<cfif isnull(privateKey)>
<cfthrow type="custom" message="Private Key Not Found" detail="Cannot obtain key #request.SAML.CERTIFICATE_ALIAS# from keystore"/>
</cfif>
<!---<cfdump var=#keystore.getKey(request.SAML.CERTIFICATE_ALIAS, request.SAML.KEY_PASS.toCharArray())#/>--->
<!---<cfset signingCertString = binaryEncode(certificate.getEncoded(),"base64") />
<cfset encryptionCertString = signingCertString />--->
<cfset currentUTC = DateConvert("local2UTC", Now()) />
<cfoutput>
<cfsavecontent variable="authnRequestXml"><?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
ID="id#CreateUUID()#"
Version="2.0"
ProviderName="MMS"
IssueInstant="#DateFormat(currentUTC,"yyyy-mm-dd")#T#TimeFormat(currentUTC,"HH:MM:ss")#Z"
Destination="#request.SAML.IDP_URL#"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
AssertionConsumerServiceURL="#request.SAML.baseUrl#sso.cfm">
<saml2:Issuer>#request.SAML.baseUrl#metadata.cfm</saml2:Issuer>
</saml2p:AuthnRequest>
</cfsavecontent>
</cfoutput>
<cfscript>
login64 = binaryEncode(deflate(authnRequestXml),"base64");
loginUrlEnc = urlEncodeRfc2396(login64);
loginSigAlgUrl = urlEncodeRfc2396('http://www.w3.org/2001/04/xmldsig-more##rsa-sha256');
relayState = urlEncodeRfc2396(target_page);
if (len(target_page)) { //empty RelayState would not be accepted
relayStateX = "&RelayState=#urlEncodeRfc2396(target_page)#";
} else {
relayStateX = "";
}
loginRequest2Sign = "SAMLRequest=#loginUrlEnc##relayStateX#&SigAlg=#loginSigAlgUrl#"; //parameter order matters
signature = sign(loginRequest2Sign, privateKey, 'SHA256withRSA');
signature64 = binaryEncode(signature,"base64");
signatureForUrl = urlEncodeRfc2396(signature64);
loginRequest = "#loginRequest2Sign#&Signature=#signatureForUrl#";
</cfscript>
<cflocation url="#request.SAML.IDP_URL#?#loginRequest#" addtoken="No"/>
+120
View File
@@ -0,0 +1,120 @@
<cfinclude template="app_saml_config.cfm"/>
<cfinclude template="saml.cfm"/>
<!---В отличие от логона, здесь тот же шаблон обрабатывает редирект от IDP. Возможно, правильнее делать было через sso.cfm--->
<!---Последовательность: шаблон принимает редирект от logout.cfm (к этому моменту usr_id в сессии уже сброшен), формирует подписанный запрос на разлогинивание и отправляет его браузеру с редиректом на IDP.
Заодно с ним идет RelayState, в который мы кладем относительный URL на страницу, которая инициировала логаут.
При успешном логауте IDP возвращает браузеру редирект на вот эту же страницу с подписанным ответом (мы его не читаем и подпись не проверяем) и RelayState.
Мы делаем редирект на относительный URL из RelayState --->
<!---*** Дублирование кода--->
<cfset ksFile = CreateObject("Java", "java.io.File").init(request.SAML.KEYSTORE_FILE_NAME) />
<cfset ksInputStream = CreateObject("Java", "java.io.FileInputStream").init(ksFile) />
<cfset keystore = CreateObject("Java" , "java.security.KeyStore").getInstance("JKS") />
<cfset keystore.load(ksInputStream, request.SAML.KEYSTORE_PASS.toCharArray()) />
<cfset certificate = keystore.getCertificate(request.SAML.CERTIFICATE_ALIAS) />
<cfset privateKey = keystore.getKey(request.SAML.CERTIFICATE_ALIAS, request.SAML.KEY_PASS.toCharArray()) />
<!---<cfset signingCertString = binaryEncode(certificate.getEncoded(),"base64") />
<cfset encryptionCertString = signingCertString/>--->
<cfset currentUTC = DateConvert("local2UTC", Now()) />
<cfparam name="SAMLResponse" default=""/>
<cfparam name="SAMLRequest" default=""/>
<cfparam name="target_page" default="ttrtrtrt"/> <!---пустое значение вызывает проблемы!--->
<cflock scope="session" type="exclusive" timeout="3">
<cfparam name="session.SAML_NameID" default=""/>
<cfparam name="session.SAML_SessionIndex" default=""/>
<cfset SAML_NameID=session.SAML_NameID/>
<cfset SAML_SessionIndex=session.SAML_SessionIndex/>
</cflock>
<cfif len(SAMLResponse)><!---Обработка ответа (редиректа) от IDP--->
<!---Мы не проверяем аутентичность ответа от IDP, полагаясь на то, что знаем, кому отправляем запрос на разлогинивание--->
<cfparam name="RelayState" default=""/>
<cflock scope="session" type="exclusive" timeout="3">
<cfset structdelete(session, "usr")>
<cfset structdelete(session, "SAML_NameID")>
<cfset structdelete(session, "SAML_SessionIndex")>
<cfset structdelete(session, "SAML_IdPCredentialsExpirationTime")>
<cfset structdelete(session, "usr_id")>
</cflock>
<cfset strUrl="../index.cfm"/>
<cfif len(RelayState) GT 0>
<cfif left(RelayState,1) EQ "/">
<cfset strUrl="#RelayState#"/>
<cfelse>
<cfset strUrl="../#RelayState#"/>
</cfif>
</cfif>
<!--- <cfset strUrl="req.cfm"/> --->
<cfelseif len(SAMLRequest)><!---Не знаю, когда используется этот режим--->
<cfset SAMLRequestStr = XMLParse(inflate(SAMLRequest))/>
<cfset SAMLRequestXml = XMLParse(SAMLRequestStr)/>
<cfset requestID=XMLSearch(SAMLRequestXml, "string(/*[name()='samlp:LogoutRequest']/@ID)")/>
<cfoutput><cfsavecontent variable="logoutResponseXml"><?xml version="1.0" encoding="UTF-8"?>
<samlp:LogoutResponse xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="id#CreateUUID()#" Version="2.0" IssueInstant="#DateFormat(currentUTC,"yyyy-mm-dd")#T#TimeFormat(currentUTC,"HH:MM:ss")#Z" Destination="https://sso.nubes.ru/adfs/ls/" InResponseTo="#requestID[1]#">
<saml:Issuer>#request.SAML.baseUrl#metadata.cfm</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
</samlp:LogoutResponse>
</cfsavecontent></cfoutput>
<cfscript>
logout64 = (deflate2base64(logoutResponseXml));
logoutUrl = urlEncodeRfc2396(logout64);
logoutSigAlgUrl= urlEncodeRfc2396('http://www.w3.org/2001/04/xmldsig-more##rsa-sha256');
if (len(target_page)) { //empty RelayState would not be accepted
relayStateX = "&RelayState=#urlEncodeRfc2396(target_page)#";
} else {
relayStateX = "";
}
logoutRequest2Sign="SAMLRequest=#logoutUrl##relayStateX#&SigAlg=#logoutSigAlgUrl#"; //order matters
signedBytesUrl = urlEncodeRfc2396(sign2base64(logoutRequest2Sign, privateKey, 'SHA256withRSA'));
logoutRequest="#logoutRequest2Sign#&Signature=#signedBytesUrl#";
</cfscript>
<cflock scope="session" type="exclusive" timeout="3">
<cfset structClear(session)/>
<cfset structClear(cookie)/>
</cflock>
<cfset strUrl="#request.SAML.IDP_URL#?#logoutRequest#"/>
<cfelse><!---Формируем и отправляем IDP (редиректом) запрос на разлогинивание--->
<cfoutput>
<cfsavecontent variable="logoutRequestXml"><?xml version="1.0" encoding="UTF-8"?>
<samlp:LogoutRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="id#CreateUUID()#" Version="2.0"
IssueInstant="#DateFormat(currentUTC,"yyyy-mm-dd")#T#TimeFormat(currentUTC,"HH:MM:ss")#Z"
Destination="#request.SAML.IDP_URL#">
<saml:Issuer>#request.SAML.baseUrl#metadata.cfm</saml:Issuer>
<saml:NameID>#SAML_NameID#</saml:NameID>
<samlp:SessionIndex>#SAML_SessionIndex#</samlp:SessionIndex>
</samlp:LogoutRequest>
</cfsavecontent>
</cfoutput>
<cfscript>
logout64 = (deflate2base64(logoutRequestXml));
logoutUrl = urlEncodeRfc2396(logout64);
logoutSigAlgUrl= urlEncodeRfc2396('http://www.w3.org/2001/04/xmldsig-more##rsa-sha256');
if (len(target_page)) { //empty RelayState would not be accepted
relayStateX = "&RelayState=#urlEncodeRfc2396(target_page)#";
} else {
relayStateX = "";
}
logoutRequest2Sign="SAMLRequest=#logoutUrl##relayStateX#&SigAlg=#logoutSigAlgUrl#"; //order matters
signedBytesUrl = urlEncodeRfc2396(sign2base64(logoutRequest2Sign,privateKey,'SHA256withRSA'));
logoutRequest="#logoutRequest2Sign#&Signature=#signedBytesUrl#";
</cfscript>
<cfset strUrl="#request.SAML.IDP_URL#?#logoutRequest#"/>
</cfif>
<cflocation url="#strUrl#" addtoken="no"/>
+51
View File
@@ -0,0 +1,51 @@
<cfsilent>
<!---when generating metadata, use HTTPS! --->
<!--- set in applicaion.cfc --->
<cfinclude template="app_saml_config.cfm"/>
<cfset ksFile = CreateObject("Java", "java.io.File").init(request.SAML.KEYSTORE_FILE_NAME) />
<cfset ksInputStream = CreateObject("Java", "java.io.FileInputStream").init(ksFile) />
<cfset keystore = CreateObject("Java" , "java.security.KeyStore").getInstance("JKS") />
<cfset keystore.load(ksInputStream, request.SAML.KEYSTORE_PASS.toCharArray()) />
<cfset certificate = keystore.getCertificate(request.SAML.CERTIFICATE_ALIAS) />
<!---<cfset privatekey = keystore.getkey(request.saml.certificate_alias, request.saml.key_pass.tochararray()) />--->
<cfset signingCertString = binaryEncode(certificate.getEncoded(),"base64") />
<cfset encryptionCertString = signingCertString/>
<cfset currentPageUrl = "#request.SAML.baseUrl##GetFileFromPath(CGI.script_name)#"/>
<cfset IdFromCurrentPageUrl = replace(replace(currentPageUrl, "/", "_", "ALL"), ":", "_", "ALL")/>
<cfset validUntilUTC = DateConvert("local2UTC", DateAdd( "d", 2, Now() ))/> <!--- 2 days literal --->
<!--- ------------------------------------------------------------------------------------ --->
<!--- ------------------------------------------------------------------------------------ --->
<!--- ------------------------------------------------------------------------------------ --->
</cfsilent><cfcontent type="text/xml"/><?xml version="1.0" encoding="UTF-8"?><cfoutput>
<md:EntityDescriptor ID="#IdFromCurrentPageUrl#" entityID="#currentPageUrl#" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" validUntil="#DateFormat(validUntilUTC,"yyyy-mm-dd")#T#TimeFormat(validUntilUTC,"HH:MM:ss")#Z" cacheDuration="PT604800S">
<md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig##">
<ds:X509Data>
<ds:X509Certificate>#signingCertString#</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig##">
<ds:X509Data>
<ds:X509Certificate>#encryptionCertString#</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<!--- <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="#baseUrl#logout.cfm"/>--->
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="#request.SAML.baseUrl#logout.cfm"/>
<!--- <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>--->
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
<!--- <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</md:NameIDFormat>--->
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="#request.SAML.baseUrl#sso.cfm" index="0" isDefault="true"/>
<!--- <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser" Location="#baseUrl#hoksso.cfm" hoksso:ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" index="1" xmlns:hoksso="urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser"/>--->
</md:SPSSODescriptor>
</md:EntityDescriptor></cfoutput>
+131
View File
@@ -0,0 +1,131 @@
<!---for debug--->
<cfinclude template="app_saml_config.cfm"/>
<cfinclude template="saml.cfm"/>
<cfset ksFile = CreateObject("Java", "java.io.File").init(request.SAML.KEYSTORE_FILE_NAME) />
<cfset ksInputStream = CreateObject("Java", "java.io.FileInputStream").init(ksFile) />
<cfset keystore = CreateObject("Java" , "java.security.KeyStore").getInstance("JKS") />
<cfset keystore.load(ksInputStream, request.SAML.KEYSTORE_PASS.toCharArray()) />
<cfset certificate = keystore.getCertificate(request.SAML.CERTIFICATE_ALIAS) />
<cfset privateKey = keystore.getKey(request.SAML.CERTIFICATE_ALIAS, request.SAML.KEY_PASS.toCharArray()) />
<cfset signingCertString = binaryEncode(certificate.getEncoded(),"base64") />
<cfset encryptionCertString = signingCertString/>
<cfset currentPageUrl = "#baseUrl##GetFileFromPath(CGI.script_name)#"/>
<cfset currentUTC = DateConvert("local2UTC", Now()) />
<!--- ------------------------------------------------- --->
<!--- ------------------------------------------------- --->
<!--- ------------------------------------------------- --->
<cfoutput><cfsavecontent variable="authnRequestXml"><?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
ID="id#CreateUUID()#"
Version="2.0"
ProviderName="MMS Dev"
IssueInstant="#DateFormat(currentUTC,"yyyy-mm-dd")#T#TimeFormat(currentUTC,"HH:MM:ss")#Z"
Destination="https://sso.nubes.ru/adfs/ls/"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
AssertionConsumerServiceURL="#baseUrl#sso.cfm">
<saml2:Issuer>#baseUrl#metadata.cfm</saml2:Issuer>
</saml2p:AuthnRequest>
</cfsavecontent></cfoutput>
<cflock scope="session" type="exclusive" timeout="3">
<cfparam name="session.SAML_NameID" default=""/>
<cfparam name="session.SAML_SessionIndex" default=""/>
<cfset SAML_NameID=session.SAML_NameID/>
<cfset SAML_SessionIndex=session.SAML_SessionIndex/>
</cflock>
<cfoutput><cfsavecontent variable="logoutRequestXml"><?xml version="1.0" encoding="UTF-8"?>
<samlp:LogoutRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="id#CreateUUID()#" Version="2.0"
IssueInstant="#DateFormat(currentUTC,"yyyy-mm-dd")#T#TimeFormat(currentUTC,"HH:MM:ss")#Z"
Destination="https://sso.nubes.ru/adfs/ls/">
<saml:Issuer>#baseUrl#metadata.cfm</saml:Issuer>
<saml:NameID>#SAML_NameID#</saml:NameID>
<samlp:SessionIndex>#SAML_SessionIndex#</samlp:SessionIndex>
</samlp:LogoutRequest>
</cfsavecontent></cfoutput>
<cfscript>
login64 = binaryEncode(deflate(authnRequestXml),"base64");
loginUrlEnc = urlEncodeRfc2396(login64);
loginSigAlgUrl= urlEncodeRfc2396('http://www.w3.org/2001/04/xmldsig-more##rsa-sha256');
loginRequest2Sign="SAMLRequest=#loginUrlEnc#&SigAlg=#loginSigAlgUrl#";
signedLoginUrlEnc = urlEncodeRfc2396(sign2base64(loginRequest2Sign,privateKey,'SHA256withRSA'));
loginRequest="#loginRequest2Sign#&Signature=#signedLoginUrlEnc#";
</cfscript>
<cfscript>
logout64 = binaryEncode(deflate(logoutRequestXml),"base64");
logoutUrl = urlEncodeRfc2396(logout64);
logoutSigAlgUrl= urlEncodeRfc2396('http://www.w3.org/2001/04/xmldsig-more##rsa-sha256');
logoutRequest2Sign="SAMLRequest=#logoutUrl#&SigAlg=#logoutSigAlgUrl#";
signedLogoutUrl = urlEncodeRfc2396(sign2base64(logoutRequest2Sign,privateKey,'SHA256withRSA'));
logoutRequest="#logoutRequest2Sign#&Signature=#signedLogoutUrl#";
</cfscript>
<cfdump var="#session#"/>
<cfoutput>
При обращении к этой странице используйте корректное имя хоста, которое зарегистрировано в ADFS!
<br/>
<cfif len(SAML_SessionIndex)><b>Logged in #SAML_SessionIndex#</b><cfelse><b style="color:red">Not logged in</b></cfif>
Текущий URL #currentPageUrl#
<br/>
SAML2 LOGIN:
<A HREF="https://sso.nubes.ru/adfs/ls/?#loginRequest#">Click Here to login</A>
#loginRequest#
<br/>
SAML2 LOGOUT:
<A HREF="https://sso.nubes.ru/adfs/ls/?#logoutRequest#">Click Here to logout</A>
<br/>
ADFS URL:
<A HREF="https://sso.nubes.ru/adfs/ls/">adfs url</A>
</cfoutput>
<br/>
<A HREF="https://sso.nubes.ru/FederationMetadata/2007-06/FederationMetadata.xml">ADFS (IdP) metadata</a>
<br/>
<A HREF="#baseUrl#metadata.xml">Own metadata</a>
<br/>
authnRequestXml:<br/>
-----------------<br/>
<cfoutput>
<pre>#xmlformat(authnRequestXml)#</pre>
</cfoutput>
-----------------<br/>
<br/>
logoutRequestXml:<br/>
-----------------<br/>
<cfoutput>
<pre>#xmlformat(logoutRequestXml)#</pre>
</cfoutput>
-----------------<br/>
<br/>
<br/>
form:<cfdump var=#form#/>
url:<cfdump var=#url#/>
session:<cfdump var=#session#/>
cookie:<cfdump var=#cookie#/>
+146
View File
@@ -0,0 +1,146 @@
<!---
https://gist.github.com/guillaumemolter/3e210855881ec5f09294
Reading, decoding and inflating a SAML XML respone with Coldfusion
This script is heavily inspired by the following posts:
- Ciarán Archer : https://flydillonfly.wordpress.com/2011/06/28/using-coldfusion-to-unzip-a-gzip-base64-string/
- Ryan Loda : http://www.coderanch.com/t/545270/java/java/Decode-SAML-Request
- Ben Nadel : http://www.bennadel.com/blog/1343-converting-a-base64-value-back-into-a-string-using-coldfusion.htm
--->
<cffunction
name="inflate"
access="public"
output="false"
returntype="string">
<cfargument name="s" type="string" required="true" />
<!--- We convert the string to binary and a ByteArrayInputStream to be able to read the stream --->
<cfset byteIn = createObject("java", "java.io.ByteArrayInputStream").init(ToBinary(s)) />
<cfset byteClass = CreateObject("Java", "java.lang.Byte").TYPE />
<cfset byteArray = CreateObject("Java", "java.lang.reflect.Array").NewInstance(byteClass, 1024) />
<!--- We init the output object where we are going to inflate our response --->
<cfset byteOut = CreateObject("Java", "java.io.ByteArrayOutputStream").init() />
<!--- We init the zip inflater --->
<cfset inflater = CreateObject("Java", "java.util.zip.Inflater").init(true) />
<!--- We are specifying to the ibnflater what to read --->
<cfset inflaterStream = CreateObject("Java", "java.util.zip.InflaterInputStream").init(byteIn, inflater) />
<!--- We loop through our byte array, inflate the buffer and store it inside of our output buffer --->
<cfset Count = inflaterStream.read(byteArray) />
<cfloop condition="Count neq -1">
<cfset byteOut.write(byteArray, 0, Count) />
<cfset Count = inflaterStream.read(byteArray) />
</cfloop>
<!--- We end/close our inflater --->
<cfset inflater.end() />
<cfset inflaterStream.close() />
<!--- Finally we convert back our bytes stream to a nice string :-) --->
<cfreturn ToString(byteOut.tobyteArray()) />
</cffunction>
<cffunction
name="deflate"
access="public"
output="false"
returntype="string">
<cfargument name="s" type="string" />
<cfscript>
var emptyByteArray = createObject("java", "java.io.ByteArrayOutputStream").init().toByteArray();
var byteClass = emptyByteArray.getClass().getComponentType();
var output = createObject("java","java.lang.reflect.Array").newInstance(byteClass, 500);
var deflater = createObject("java", "java.util.zip.Deflater");
deflater.init(9,true);
deflater.setInput(ARGUMENTS.s.getBytes("UTF-8"));
deflater.finish();
var compressedDataLength = deflater.deflate(output);
return output;
</cfscript>
</cffunction>
<cffunction
name="deflate2base64"
access="public"
output="false"
returntype="string">
<cfargument name="s" type="string" />
<cfscript>
var emptyByteArray = createObject("java", "java.io.ByteArrayOutputStream").init().toByteArray();
var byteClass = emptyByteArray.getClass().getComponentType();
var output = createObject("java","java.lang.reflect.Array").newInstance(byteClass, 500);
var deflater = createObject("java", "java.util.zip.Deflater");
deflater.init(9,true);
deflater.setInput(ARGUMENTS.s.getBytes("UTF-8"));
deflater.finish();
compressedDataLength = deflater.deflate(output);
return toBase64(output, 'UTF-8');
</cfscript>
</cffunction>
<cffunction
name="sign"
access="public"
output="false"
returntype="string">
<cfargument name="s" type="string" />
<cfargument name="pk" type="ANY" />
<cfargument name="algorithm" type="string" default="SHA256withRSA"/>
<cfscript>
var signer = createObject("java", "java.security.Signature").getInstance(ARGUMENTS.algorithm);;
var signer.initSign(ARGUMENTS.pk);
var signer.update(ARGUMENTS.s.getBytes("us-ASCII"));
return signer.sign();
</cfscript>
</cffunction>
<cffunction
name="sign2base64"
access="public"
output="false"
returntype="string">
<cfargument name="s" type="string" />
<cfargument name="pk" type="ANY" />
<cfargument name="algorithm" type="string" default="SHA256withRSA"/>
<cfscript>
var signer = createObject("java", "java.security.Signature").getInstance(ARGUMENTS.algorithm);;
var signer.initSign(ARGUMENTS.pk);
var signer.update(ARGUMENTS.s.getBytes("us-ASCII"));
return binaryEncode(signer.sign(), "base64");
</cfscript>
</cffunction>
<cffunction
name="urlEncodeRfc2396"
output="false"
returntype="string">
<cfargument name="s" type="string" />
<!--- replace back mark (unreserved) characters, otherwise when POSTing to the same URL,
browser changes escaped mark characters to originall characters, and the signature becomes invalid,
because the string signed already is not exactly the same --->
<cfreturn replaceList(urlEncodedFormat(s),"%2D,%5F,%2E,%21,%7E,%2A,%27,%28,%29", "-,_,.,!,~,*,',(,)")/>
</cffunction>
+150
View File
@@ -0,0 +1,150 @@
<cfinclude template="app_saml_config.cfm"/>
<!---<cfinclude template="saml.cfm"/>--->
<cfset ksFile = CreateObject("Java", "java.io.File").init(request.SAML.KEYSTORE_FILE_NAME) />
<cfset ksInputStream = CreateObject("Java", "java.io.FileInputStream").init(ksFile) />
<cfset keystore = CreateObject("Java" , "java.security.KeyStore").getInstance("JKS") />
<cfset keystore.load(ksInputStream, request.SAML.KEYSTORE_PASS.toCharArray()) />
<cfset certificate = keystore.getCertificate(request.SAML.CERTIFICATE_ALIAS) />
<cfset privateKey = keystore.getKey(request.SAML.CERTIFICATE_ALIAS, request.SAML.KEY_PASS.toCharArray()) />
<cfset signingCertString = binaryEncode(certificate.getEncoded(),"base64") />
<cfset encryptionCertString = signingCertString/>
<cfparam name="SAMLResponse"/>
<cfparam name="RelayState" default=""/>
<cfset SAMLResponseStr = ToString(ToBinary(SAMLResponse))/>
<cfset SAMLResponseXml = XMLParse(SAMLResponseStr)/><!---*** catch exception--->
<cfset SAMLStatus = XMLSearch(SAMLResponseXml, "//*[name()='samlp:StatusCode']")[1].XmlAttributes.Value/><!---*** catch exception--->
<cfset err=""/>
<cfscript>
/*
On Lucee
Error "Could not initialize class org.apache.xml.security.Init" is possibly caused by incompatible slf4j(api?)
Solution: put slf4j-api-1.7.22.jar to D:\lucee\tomcat\lib
*/
Init = CreateObject("Java", "org.apache.xml.security.Init").Init().init();
/*
// more complex way to initialize xmlsec
ref = createObject("java", "org.apache.xml.security.Init");
// writeDump(ref);
// initialize if needed
if (!ref.isInitialized()) {
// find static method named "init" with no parameters
method = ref.getClass().getDeclaredMethod("init", []);
// invoke it via reflection
method.invoke(ref, javacast("null", ""));
}
*/
dataArray=XMLSearch(SAMLResponseXml, "//*[name()='EncryptedAssertion']");
try {
dataElement=dataArray[1];
DECRYPT_MODE=CreateObject( "Java", "org.apache.xml.security.encryption.XMLCipher").DECRYPT_MODE;
cipher=CreateObject( "Java", "org.apache.xml.security.encryption.XMLCipher").getInstance();
cipher.init(DECRYPT_MODE, javacast("null", ""));
cipher.setKEK(privateKey);
cipher.doFinal(dataElement.getOwnerDocument(), dataElement, true);
} catch (any e) {
err = "Ошибка авторизации. Статус запроса: " & SAMLStatus;
}
//<!---проверка подписи--->
if (NOT len(err)) {
assertionArray = XMLSearch(SAMLResponseXml, "/*[name()='samlp:Response']/*[name()='EncryptedAssertion']/*[name()='Assertion']");
try {
assertionElement = assertionArray[1];
assertionElement.setIdAttribute("ID",true); //sic!
//WriteDump(assertionElement);
Init = CreateObject("Java", "org.apache.xml.security.Init").Init().init();
SignatureConstants = CreateObject("Java", "org.apache.xml.security.utils.Constants");
SignatureSpecNS = SignatureConstants.SignatureSpecNS; //writeDump(SignatureSpecNS);
xmlSignatureClass = CreateObject("Java", "org.apache.xml.security.signature.XMLSignature");
signatureElement=SAMLResponseXml.getElementsByTagNameNS(SignatureSpecNS,"Signature").item(0);
xmlSignature = xmlSignatureClass.init(signatureElement,"");
keyInfo = xmlSignature.getKeyInfo();
X509CertificateResolverCN = "org.apache.xml.security.keys.keyresolver.implementations.X509CertificateResolver";
keyResolver = CreateObject("Java", X509CertificateResolverCN).init();
keyInfo.registerInternalKeyResolver(keyResolver);
x509cert = keyInfo.getX509Certificate();
isValid = xmlSignature.checkSignatureValue(x509cert);
} catch (any e) {
err = "Ошибка при проверке подписи. Статус запроса: " & SAMLStatus;
}
}
</cfscript>
<cfif NOT len(err)>
<cfif (isValid NEQ 0)>
<cfset NameID=XMLSearch(SAMLResponseXml, "string(/*[name()='samlp:Response']/*[name()='EncryptedAssertion']/*[name()='Assertion']/*[name()='Subject']/*[name()='NameID'])") />
<cfset SessionIndex=XMLSearch(SAMLResponseXml, "string(//*[name()='Assertion']/*[name()='AuthnStatement']/@SessionIndex)") />
<cftry>
<cfset NotOnOrAfter=XMLSearch(SAMLResponseXml, "string(//*[name()='Assertion']/*[name()='Conditions']/@NotOnOrAfter)") />
<cfset SAML_IdPCredentialsExpirationTime=ParseDateTime(NotOnOrAfter)/>
<cfcatch type="ANY">
<cfset SAML_IdPCredentialsExpirationTime=Now()/>
</cfcatch>
</cftry>
<cfquery name="qUsr" datasource="#request.DS#">
select usr_id, locked, shortname
from usr
where login=<cfqueryparam cfsqltype="cf_sql_varchar" value="#NameID#">
</cfquery>
<cfif (qUsr.RecordCount NEQ 1)>
<cfset err="Пользователь #NameID# не зарегистрирован в данной системе."/>
<cfdump var=#SAMLResponseXml#/>
<cfset QueryAddRow(qUsr, 1)/>
<cfset qUsr.usr_id=request.GUEST_USR_ID/>
</cfif>
<cfif SAML_IdPCredentialsExpirationTime LE Now()>
<cfset err="Данные аутентификации устарели (были действительны до #dateFormat(SAML_IdPCredentialsExpirationTime,'DD.MM.YYYY')# #timeFormat(SAML_IdPCredentialsExpirationTime,'HH:MM')#). Пожалуйста, авторизуйтесь заново."/>
</cfif>
<cfelse>
<cfset err="Подпись SAML-ответа недействительна."/>
</cfif>
</cfif>
<cfif len(err)>
<cfoutput><span class="err">#err#</span></cfoutput>
<cfelse>
<cflock scope="session" type="exclusive" timeout="3">
<cfparam name="session.targetScriptName" default=""/>
<cfparam name="session.targetQueryString" default=""/>
<cfset session.SAML_NameID=#NameID#/>
<cfset session.SAML_SessionIndex=#SessionIndex#/>
<cfset session.SAML_IdPCredentialsExpirationTime=#SAML_IdPCredentialsExpirationTime#/>
<cfset session.usr_id=qUsr.usr_id/>
<cfset request.usr_id=qUsr.usr_id>
</cflock>
<!--- redirect to requested url --->
<cfset strUrl="../index.cfm"/>
<!--- <cfset strUrl="req.cfm"/> --->
<cfif len(RelayState) GT 0>
<cfset strUrl="../#RelayState#"/>
<cfelseif len(session.targetScriptName) GT 0>
<cfif NOT lCase(session.targetScriptName) EQ "login.cfm">
<cfset strUrl=#session.targetScriptName#>
<cfif len(session.targetQueryString) GT 0>
<cfif Find("?", "#strUrl#", 1) GT 0>
<cfset strUrl="../#strUrl#&#urlEncodedFormat(session.targetQueryString)#"/>
<cfelse>
<cfset strUrl="../#strUrl#?#urlEncodedFormat(session.targetQueryString)#"/>
</cfif>
</cfif>
<cfset session.targetScriptName="">
<cfset session.targetQueryString="">
</cfif>
</cfif>
<!--- <cfoutput>
<br><a href="#strUrl#">Аутентификация успешна. Продолжить работу как #qUsr.shortname#</a>
<br><pre>#saml.prettyPrintXml(SAMLResponseXml)#</pre>
</cfoutput> --->
<cflocation url="#strUrl#" addtoken="no"/>
</cfif>