initial draft
This commit is contained in:
@@ -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
|
||||
--->
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
@@ -0,0 +1,2 @@
|
||||
D:\lucee\jre\bin\keytool.exe -list -keystore D:/lucee/tomcat/lucee-server/context/security/cacerts -storepass changeit
|
||||
pause
|
||||
@@ -0,0 +1,2 @@
|
||||
D:\lucee\jre\bin\keytool.exe -list -v -keystore D:/lucee/tomcat/lucee-server/context/security/cacerts -storepass changeit
|
||||
pause
|
||||
@@ -0,0 +1,2 @@
|
||||
"%JAVA_HOME%\bin\keytool.exe" -list -v -keystore C:\lucee\tomcat\lucee-server\context\security\cacerts -storepass changeit
|
||||
pause
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
@@ -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
|
||||
@@ -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/" />
|
||||
@@ -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
@@ -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 }R�j�0���,yw�ch�� 9�RYnDm�x��ϯ
|
||||
�G�7o��n`�i�}�0 ��������OI�/m��8�2|�i�C��0�D�yg9�2z�B�"o��^���NO4�1Mp�����?��w�����.̫�0Bn���+������i�3�w���>I���E�#����*n��pP�4�%0+�����&CL� �4R�V�f2��������zG+�3�)h��J�U���p������4���ǒ�h��Ce��1���$ ǹ T�mLe𦅿�3�@7%$;:�Y�b=��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 пересоздались
|
||||
подложил в верхнюю либу файлы от Райло, перезапустил Люси - и вот, все взлетело. Теперь надо
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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"/>
|
||||
@@ -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
@@ -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
@@ -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
@@ -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>
|
||||
Reference in New Issue
Block a user