'use strict'; var express = require( 'express' ); var bodyParser = require( 'body-parser' ); var passport = require( 'passport' ); var SamlStrategy = require( '../lib/passport-saml/index.js' ).Strategy; var request = require( 'request' ); var should = require( 'should' ); var zlib = require( 'zlib' ); var querystring = require( 'querystring' ); var parseString = require( 'xml2js' ).parseString; var SAML = require( '../lib/passport-saml/index.js' ).SAML; var fs = require( 'fs' ); var sinon = require('sinon'); // a certificate which is re-used by several tests var TEST_CERT = "MIIEFzCCAv+gAwIBAgIUFJsUjPM7AmWvNtEvULSHlTTMiLQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UEBhMCVVMxETAPBgNVBAoMCFN1YnNwYWNlMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgNDIzNDkwHhcNMTQwNTEzMTgwNjEyWhcNMTkwNTE0MTgwNjEyWjBYMQswCQYDVQQGEwJVUzERMA8GA1UECgwIU3Vic3BhY2UxFTATBgNVBAsMDE9uZUxvZ2luIElkUDEfMB0GA1UEAwwWT25lTG9naW4gQWNjb3VudCA0MjM0OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKrAzJdY9FzFLt5blArJfPzgi87EnFGlTfcV5T1TUDwLBlDkY/0ZGKnMOpf3D7ie2C4pPFOImOogcM5kpDDL7qxTXZ1ewXVyjBdMu29NG2C6NzWeQTUMUji01EcHkC8o+Pts8ANiNOYcjxEeyhEyzJKgEizblYzMMKzdrOET6QuqWo3C83K+5+5dsjDn1ooKGRwj3HvgsYcFrQl9NojgQFjoobwsiE/7A+OJhLpBcy/nSVgnoJaMfrO+JsnukZPztbntLvOl56+Vra0N8n5NAYhaSayPiv/ayhjVgjfXd1tjMVTOiDknUOwizZuJ1Y3QH94vUtBgp0WBpBSs/xMyTs8CAwEAAaOB2DCB1TAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRQO4WpM5fWwxib49WTuJkfYDbxODCBlQYDVR0jBIGNMIGKgBRQO4WpM5fWwxib49WTuJkfYDbxOKFcpFowWDELMAkGA1UEBhMCVVMxETAPBgNVBAoMCFN1YnNwYWNlMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxHzAdBgNVBAMMFk9uZUxvZ2luIEFjY291bnQgNDIzNDmCFBSbFIzzOwJlrzbRL1C0h5U0zIi0MA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQUFAAOCAQEACdDAAoaZFCEY5pmfwbKuKrXtO5iE8lWtiCPjCZEUuT6bXRNcqrdnuV/EAfX9WQoXjalPi0eM78zKmbvRGSTUHwWw49RHjFfeJUKvHNeNnFgTXDjEPNhMvh69kHm453lFRmB+kk6yjtXRZaQEwS8Uuo2Ot+krgNbl6oTBZJ0AHH1MtZECDloms1Km7zsK8wAi5i8TVIKkVr5b2VlhrLgFMvzZ5ViAxIMGB6w47yY4QGQB/5Q8ya9hBs9vkn+wubA+yr4j14JXZ7blVKDSTYva65Ea+PqHyrp+Wnmnbw2ObS7iWexiTy1jD3G0R2avDBFjM8Fj5DbfufsE1b0U10RTtg=="; describe( 'passport-saml /', function() { describe('captured saml responses /', function () { var fakeClock; var capturedChecks = [ { name: 'Okta -- valid config should succeed', samlResponse: { SAMLResponse: 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOlJlc3BvbnNlIHhtbG5zOnNhbWwycD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBEZXN0aW5hdGlvbj0iaHR0cDovL2xvY2FsaG9zdC9icm93c2VyU2FtbExvZ2luIiBJRD0iaWQzMzcxMDA5NzQ3ODg2OTIzMjIwMzA1Njc3ODMiIEluUmVzcG9uc2VUbz0iXzVjMzg1YWJiMTc3MzViN2FhOGQxIiBJc3N1ZUluc3RhbnQ9IjIwMTQtMDUtMjdUMjM6Mjc6MzUuNDI2WiIgVmVyc2lvbj0iMi4wIj48c2FtbDI6SXNzdWVyIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OmVudGl0eSI+aHR0cDovL3d3dy5va3RhLmNvbS9rdmpqNDZsc0RRRVFZVURCWklZVzwvc2FtbDI6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNyc2Etc2hhMSIvPjxkczpSZWZlcmVuY2UgVVJJPSIjaWQzMzcxMDA5NzQ3ODg2OTIzMjIwMzA1Njc3ODMiPjxkczpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNzaGExIi8+PGRzOkRpZ2VzdFZhbHVlPjRSNUNjYUVEQ3dPSCtudnVHSkY3TWRBelpIdz08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU+TzlycW1TUTJQd1NaZDFBeklRUDUySkY5VHBaSkJUNENpdnAxTUZZN3FzODdrU2RFQ3dNbWFWTDE2NFI4dUlCbzdscXUwOFRaTGZYeGF6ak5uRDhnV05BOWRuK2d5cFc1ZWo4S3EzK1J3cUxZUzM1M3pCeVpWcy9MSUxQZVJCK0tUS2RsbTVJSDcxdWhwbUp4a3k0T0gwNWdDSWExYnRFaXpKV1h3d1lleXpBPTwvZHM6U2lnbmF0dXJlVmFsdWU+PGRzOktleUluZm8+PGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU+TUlJQ29UQ0NBZ3FnQXdJQkFnSUdBVVk4elZQWU1BMEdDU3FHU0liM0RRRUJCUVVBTUlHVE1Rc3dDUVlEVlFRR0V3SlZVekVUTUJFRwpBMVVFQ0F3S1EyRnNhV1p2Y201cFlURVdNQlFHQTFVRUJ3d05VMkZ1SUVaeVlXNWphWE5qYnpFTk1Bc0dBMVVFQ2d3RVQydDBZVEVVCk1CSUdBMVVFQ3d3TFUxTlBVSEp2ZG1sa1pYSXhGREFTQmdOVkJBTU1DM04xWW5Od1lXTmxjM2N4TVJ3d0dnWUpLb1pJaHZjTkFRa0IKRmcxcGJtWnZRRzlyZEdFdVkyOXRNQjRYRFRFME1EVXlOekE0TWpreU4xb1hEVFEwTURVeU56QTRNekF5TjFvd2daTXhDekFKQmdOVgpCQVlUQWxWVE1STXdFUVlEVlFRSURBcERZV3hwWm05eWJtbGhNUll3RkFZRFZRUUhEQTFUWVc0Z1JuSmhibU5wYzJOdk1RMHdDd1lEClZRUUtEQVJQYTNSaE1SUXdFZ1lEVlFRTERBdFRVMDlRY205MmFXUmxjakVVTUJJR0ExVUVBd3dMYzNWaWMzQmhZMlZ6ZHpFeEhEQWEKQmdrcWhraUc5dzBCQ1FFV0RXbHVabTlBYjJ0MFlTNWpiMjB3Z1o4d0RRWUpLb1pJaHZjTkFRRUJCUUFEZ1kwQU1JR0pBb0dCQUtZWAovVWRWOUhMWGJOS3YweWM2WUpCdHpkV051R1RQSVhXVlBDYjBPc1J2UjU0bHErMFNMUFFHSlMzOWZsV0tpcXRVaUV1c3VpaDZHZExmCk52RkFWTEdQcUJUV1E0TGM3cjUrekQ1cW5INkxpVE0xS0NiYUYzdXUyUCtUK3V0c0dxRlVaYXdBOUZFVk5Ma0lDZTM2WDF5RTQwWCsKL2pNeWd5aWVRUE1lSkFCdkFnTUJBQUV3RFFZSktvWklodmNOQVFFRkJRQURnWUVBSFNXUEc0eTFiTnlKeVNnYkZxRGNTLzZNVU5JcgpTZmtRWUl4eklHUTM3cXk1cUFXMTVZa0JVaVc5VHNHSlJjcmd1c1ZyWklpYTE4ZVl6ODRabjdGeVVaTk1GbzI0TDdsNkJTMFdDaXRJClFTY0JDS0I0UVdBL2Ixc3pxczdFdHBPY1BQMDFUWU5xMnJhcytWcVIzYVdBWExYMm9LZkNsVi9TVXdzelJmNVU4NVk9PC9kczpYNTA5Q2VydGlmaWNhdGU+PC9kczpYNTA5RGF0YT48L2RzOktleUluZm8+PC9kczpTaWduYXR1cmU+PHNhbWwycDpTdGF0dXMgeG1sbnM6c2FtbDJwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiPjxzYW1sMnA6U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIi8+PC9zYW1sMnA6U3RhdHVzPjxzYW1sMjpBc3NlcnRpb24geG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIElEPSJpZDMzNzEwMDk3NDc4OTQ5MTAwNjY2NTIyNTEyIiBJc3N1ZUluc3RhbnQ9IjIwMTQtMDUtMjdUMjM6Mjc6MzUuNDI2WiIgVmVyc2lvbj0iMi4wIj48c2FtbDI6SXNzdWVyIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5IiB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiI+aHR0cDovL3d3dy5va3RhLmNvbS9rdmpqNDZsc0RRRVFZVURCWklZVzwvc2FtbDI6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNyc2Etc2hhMSIvPjxkczpSZWZlcmVuY2UgVVJJPSIjaWQzMzcxMDA5NzQ3ODk0OTEwMDY2NjUyMjUxMiI+PGRzOlRyYW5zZm9ybXM+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvZHM6VHJhbnNmb3Jtcz48ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3NoYTEiLz48ZHM6RGlnZXN0VmFsdWU+UFM4dE5taVVZUXpRQVFURjh3RDFRT3dMazA0PTwvZHM6RGlnZXN0VmFsdWU+PC9kczpSZWZlcmVuY2U+PC9kczpTaWduZWRJbmZvPjxkczpTaWduYXR1cmVWYWx1ZT5XM3JiUkNFUmE1ZEtUcy9MSERwY0pEeUhjSzFESjczd2xhT3J2MXZWNmZxQ3FTTUNpclZLRVlLKzR2OG5WaThZNlZwcVJHd0trWFV2cUY0b0hKWjYzOE5YYVRiRVRjU1VXWjVUNXowbzBNVXhBL3RnL01zVzYvRlVRMXBqUWJhVlhJT3Mvc1EwVzluUXpmZkVZLzgrSkVJMldLY0I2UkZlVzVtTlkvdm9oUWM9PC9kczpTaWduYXR1cmVWYWx1ZT48ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE+PGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlDb1RDQ0FncWdBd0lCQWdJR0FVWTh6VlBZTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUdUTVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHCkExVUVDQXdLUTJGc2FXWnZjbTVwWVRFV01CUUdBMVVFQnd3TlUyRnVJRVp5WVc1amFYTmpiekVOTUFzR0ExVUVDZ3dFVDJ0MFlURVUKTUJJR0ExVUVDd3dMVTFOUFVISnZkbWxrWlhJeEZEQVNCZ05WQkFNTUMzTjFZbk53WVdObGMzY3hNUnd3R2dZSktvWklodmNOQVFrQgpGZzFwYm1adlFHOXJkR0V1WTI5dE1CNFhEVEUwTURVeU56QTRNamt5TjFvWERUUTBNRFV5TnpBNE16QXlOMW93Z1pNeEN6QUpCZ05WCkJBWVRBbFZUTVJNd0VRWURWUVFJREFwRFlXeHBabTl5Ym1saE1SWXdGQVlEVlFRSERBMVRZVzRnUm5KaGJtTnBjMk52TVEwd0N3WUQKVlFRS0RBUlBhM1JoTVJRd0VnWURWUVFMREF0VFUwOVFjbTkyYVdSbGNqRVVNQklHQTFVRUF3d0xjM1ZpYzNCaFkyVnpkekV4SERBYQpCZ2txaGtpRzl3MEJDUUVXRFdsdVptOUFiMnQwWVM1amIyMHdnWjh3RFFZSktvWklodmNOQVFFQkJRQURnWTBBTUlHSkFvR0JBS1lYCi9VZFY5SExYYk5LdjB5YzZZSkJ0emRXTnVHVFBJWFdWUENiME9zUnZSNTRscSswU0xQUUdKUzM5ZmxXS2lxdFVpRXVzdWloNkdkTGYKTnZGQVZMR1BxQlRXUTRMYzdyNSt6RDVxbkg2TGlUTTFLQ2JhRjN1dTJQK1QrdXRzR3FGVVphd0E5RkVWTkxrSUNlMzZYMXlFNDBYKwovak15Z3lpZVFQTWVKQUJ2QWdNQkFBRXdEUVlKS29aSWh2Y05BUUVGQlFBRGdZRUFIU1dQRzR5MWJOeUp5U2diRnFEY1MvNk1VTklyClNma1FZSXh6SUdRMzdxeTVxQVcxNVlrQlVpVzlUc0dKUmNyZ3VzVnJaSWlhMThlWXo4NFpuN0Z5VVpOTUZvMjRMN2w2QlMwV0NpdEkKUVNjQkNLQjRRV0EvYjFzenFzN0V0cE9jUFAwMVRZTnEycmFzK1ZxUjNhV0FYTFgyb0tmQ2xWL1NVd3N6UmY1VTg1WT08L2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5mbz48L2RzOlNpZ25hdHVyZT48c2FtbDI6U3ViamVjdCB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiI+PHNhbWwyOk5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OmVtYWlsQWRkcmVzcyI+YmVuQHN1YnNwYWNlc3cuY29tPC9zYW1sMjpOYW1lSUQ+PHNhbWwyOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48c2FtbDI6U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgSW5SZXNwb25zZVRvPSJfNWMzODVhYmIxNzczNWI3YWE4ZDEiIE5vdE9uT3JBZnRlcj0iMjAxNC0wNS0yN1QyMzozMjozNS40MjZaIiBSZWNpcGllbnQ9Imh0dHA6Ly9sb2NhbGhvc3QvYnJvd3NlclNhbWxMb2dpbiIvPjwvc2FtbDI6U3ViamVjdENvbmZpcm1hdGlvbj48L3NhbWwyOlN1YmplY3Q+PHNhbWwyOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDE0LTA1LTI3VDIzOjIyOjM1LjQyNloiIE5vdE9uT3JBZnRlcj0iMjAxNC0wNS0yN1QyMzozMjozNS40MjZaIiB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiI+PHNhbWwyOkF1ZGllbmNlUmVzdHJpY3Rpb24+PHNhbWwyOkF1ZGllbmNlPmh0dHBzOi8vYWRtaW4uc3Vic3BhY2Vzdy5jb208L3NhbWwyOkF1ZGllbmNlPjwvc2FtbDI6QXVkaWVuY2VSZXN0cmljdGlvbj48L3NhbWwyOkNvbmRpdGlvbnM+PHNhbWwyOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxNC0wNS0yN1QyMzoyNzozNS40MjZaIiBTZXNzaW9uSW5kZXg9Il81YzM4NWFiYjE3NzM1YjdhYThkMSIgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPjxzYW1sMjpBdXRobkNvbnRleHQ+PHNhbWwyOkF1dGhuQ29udGV4dENsYXNzUmVmPnVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphYzpjbGFzc2VzOlg1MDk8L3NhbWwyOkF1dGhuQ29udGV4dENsYXNzUmVmPjwvc2FtbDI6QXV0aG5Db250ZXh0Pjwvc2FtbDI6QXV0aG5TdGF0ZW1lbnQ+PC9zYW1sMjpBc3NlcnRpb24+PC9zYW1sMnA6UmVzcG9uc2U+', RelayState: '', }, config: { entryPoint: 'https://subspacesw1.okta.com/app/subspacesw_subspacetest_1/kvjj46lsDQEQYUDBZIYW/sso/saml', cert: 'MIICoTCCAgqgAwIBAgIGAUY8zVPYMA0GCSqGSIb3DQEBBQUAMIGTMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxFDASBgNVBAMMC3N1YnNwYWNlc3cxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMB4XDTE0MDUyNzA4MjkyN1oXDTQ0MDUyNzA4MzAyN1owgZMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKDARPa3RhMRQwEgYDVQQLDAtTU09Qcm92aWRlcjEUMBIGA1UEAwwLc3Vic3BhY2VzdzExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKYX/UdV9HLXbNKv0yc6YJBtzdWNuGTPIXWVPCb0OsRvR54lq+0SLPQGJS39flWKiqtUiEusuih6GdLfNvFAVLGPqBTWQ4Lc7r5+zD5qnH6LiTM1KCbaF3uu2P+T+utsGqFUZawA9FEVNLkICe36X1yE40X+/jMygyieQPMeJABvAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAHSWPG4y1bNyJySgbFqDcS/6MUNIrSfkQYIxzIGQ37qy5qAW15YkBUiW9TsGJRcrgusVrZIia18eYz84Zn7FyUZNMFo24L7l6BS0WCitIQScBCKB4QWA/b1szqs7EtpOcPP01TYNq2ras+VqR3aWAXLX2oKfClV/SUwszRf5U85Y=' }, expectedStatusCode: 200, expectedNameIDStartsWith: 'ben', mockDate: '2014-05-27T23:29:35.426Z' }, { name: 'Okta -- valid encrypted response should succeed', samlResponse: { SAMLResponse: 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOlJlc3BvbnNlIHhtbG5zOnNhbWwycD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly82NGY0MDk0Zi5uZ3Jvay5pby9zc28vc2FtbC9jYWxsYmFjayIgSUQ9ImlkMTk1MjM4OTMzOTcwNDQ4MjIzOTQwNDk3IiBJblJlc3BvbnNlVG89Il9jNjA1MzdkYWQzNGZhNGVjYjYxMyIgSXNzdWVJbnN0YW50PSIyMDE2LTA4LTE5VDAxOjEzOjM4LjEzOVoiIFZlcnNpb249IjIuMCI+PHNhbWwyOklzc3VlciB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDplbnRpdHkiPmh0dHA6Ly93d3cub2t0YS5jb20vZXhrN3hkaTZheFBmb21iengwaDc8L3NhbWwyOklzc3Vlcj48ZHM6U2lnbmF0dXJlIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48ZHM6U2lnbmVkSW5mbz48ZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjcnNhLXNoYTEiLz48ZHM6UmVmZXJlbmNlIFVSST0iI2lkMTk1MjM4OTMzOTcwNDQ4MjIzOTQwNDk3Ij48ZHM6VHJhbnNmb3Jtcz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz48ZHM6RGlnZXN0VmFsdWU+enQ3eG5yTDB1Vmt6azN1NHhkS3hVR0ZtbHVLamM4eXlDOWZvanJ4NXFDbz08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU+ZUZlczNUUEIvZVFlUVBtUHBPYlA0UDNRWklKRGMxY1cwMk5UOHJlVEp1MG9lZElDTm8vTkJEeE9rMWJoODFJMzlMdi90MWRFM0Z3azBrZ0kzRUswV0s0UVpsSWZ2WkIrTkpPSlRjZW9CUnptTXRBeHI5cVlORWlHSWxZeGdwS1BDaG95OHQzcllMV3ZCZVpJc2pKOC9iYmRudXhjSFY3bXpveFkyNHdtYXFucXExNG5QSTFBZ0lIY1NnTVRhL1lqaFJwWjJlU0o2TU9FMU0vNDByL3VvRUlPWDVjMFVoSE1Gbzh3Yml2NCtvaTJPK2RPOVdha3BDN1Y5cHVGelU0OVF6MGR6bDFXaFIwYlp4VG1TYXI2WUY2NXMwZk5DUnorSGJ5a1h3eFZ4OFo0TTUxRUJHN1NMdWlQVFVJTjFNWVRXZXVoZll6MS9Pc2YvcGoxbHFLYlZBPT08L2RzOlNpZ25hdHVyZVZhbHVlPjxkczpLZXlJbmZvPjxkczpYNTA5RGF0YT48ZHM6WDUwOUNlcnRpZmljYXRlPk1JSURvRENDQW9pZ0F3SUJBZ0lHQVZhWjA0UE9NQTBHQ1NxR1NJYjNEUUVCQlFVQU1JR1FNUXN3Q1FZRFZRUUdFd0pWVXpFVE1CRUcKQTFVRUNBd0tRMkZzYVdadmNtNXBZVEVXTUJRR0ExVUVCd3dOVTJGdUlFWnlZVzVqYVhOamJ6RU5NQXNHQTFVRUNnd0VUMnQwWVRFVQpNQklHQTFVRUN3d0xVMU5QVUhKdmRtbGtaWEl4RVRBUEJnTlZCQU1NQ0daeWIyNTBZWEJ3TVJ3d0dnWUpLb1pJaHZjTkFRa0JGZzFwCmJtWnZRRzlyZEdFdVkyOXRNQjRYRFRFMk1EZ3hOekU0TkRVek1Wb1hEVEkyTURneE56RTRORFl6TVZvd2daQXhDekFKQmdOVkJBWVQKQWxWVE1STXdFUVlEVlFRSURBcERZV3hwWm05eWJtbGhNUll3RkFZRFZRUUhEQTFUWVc0Z1JuSmhibU5wYzJOdk1RMHdDd1lEVlFRSwpEQVJQYTNSaE1SUXdFZ1lEVlFRTERBdFRVMDlRY205MmFXUmxjakVSTUE4R0ExVUVBd3dJWm5KdmJuUmhjSEF4SERBYUJna3Foa2lHCjl3MEJDUUVXRFdsdVptOUFiMnQwWVM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDdnBsUU8KTlZ3a25SeTFpQm5hb1p0c096MjhBN1hXMnRScEZXKzBMYTdSSmV4YnppSXdFeTFiUFpFTmhmd2pQWkExb0hIWnFpNWwzMTVCeFhLVwpKcW1tTm1iRENGRG8rL0ZZRkNvSFhsaWlMbTl2cURiUjFicjZCeXFlWTBHZnh5VFBLSFp4YjJGU2VzMzBUZmZEa25wTVFkLzhrQTlZCldhVzV4RGx1Mml2V0pJK3NmY09KT01kNnQrZ2NmWGo1OGE1ZlA4TXdtNlkyMjBLZVpTdnJWcEVWMktEcDlobG43Zmhob3hIWjdLL0IKWWJpZHFkd0x6ZVVRWHBiNkxJcnh0S2R1ZzJGb2ZTK09OczZ5TElRUm1yYkNCN1NWWDFRQThKSW5NbitmenJHdFptRmlIUjBhRmJ5aAppTzc4di91ZkRhNlMrWHBZeXAyYjZENFNuemVnZ25vYkFnTUJBQUV3RFFZSktvWklodmNOQVFFRkJRQURnZ0VCQUoyd2NGVmZmRkhTCmQ5cGo2UmdvTkhYWkJzV3AwSFVack5la2lTYmdvbXI0dFNEZWZXdEtiMDRuRklsUnl0ZlZzL2s3NHdtYk5pUkNFOG5EVkJyQkRGQS8KK1R2LzNQb3daWEhqWEtCb2ZVdVNjVFA0L1R3MU4veXdmN1YrWFk1a1YzVm1MQkw2YXgrVUxKYXVSL1lHSUlNc0ljL3JTMkQwNGFBYwpTY1U5cHFWaDJNTDduVEg3Z0ZxWXJ4eXBhdm1WazZLOTR2TGpzMGdnRjJUR3A3dFhDUmplT2xQUEpTK01PSkhKaFRCV1lGV3ZCTGNsClUzemNyaTN3czdHcUpNcGVpSGE3ck1vSFYwb254V3NaVFpXNTd5YmFJV0tMdDFnb0Fvb0M3aHEwcng3b05sT3ZyeXM1bGxsaEJ5U1kKWUMzeWNxY2EvRDArR3hYTGNFcjlRd1A3VFZ3PTwvZHM6WDUwOUNlcnRpZmljYXRlPjwvZHM6WDUwOURhdGE+PC9kczpLZXlJbmZvPjwvZHM6U2lnbmF0dXJlPjxzYW1sMnA6U3RhdHVzIHhtbG5zOnNhbWwycD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIj48c2FtbDJwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPjwvc2FtbDJwOlN0YXR1cz48c2FtbDI6RW5jcnlwdGVkQXNzZXJ0aW9uIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj48eGVuYzpFbmNyeXB0ZWREYXRhIHhtbG5zOnhlbmM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jIyIgSWQ9Il85ZThmZDJjZTRhZDAyMTJjOThlNzA5MWNhODc2NWZiNCIgVHlwZT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjRWxlbWVudCI+PHhlbmM6RW5jcnlwdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI2FlczI1Ni1jYmMiIHhtbG5zOnhlbmM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jIyIvPjxkczpLZXlJbmZvIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48ZHM6UmV0cmlldmFsTWV0aG9kIFR5cGU9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI0VuY3J5cHRlZEtleSIgVVJJPSIjXzJhZWE3YTY1MWRiYjY4NzkwMmM0ODM0MzJlZDg1NzgwIi8+PC9kczpLZXlJbmZvPjx4ZW5jOkNpcGhlckRhdGEgeG1sbnM6eGVuYz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjIj48eGVuYzpDaXBoZXJWYWx1ZT5KQVJJWlJOMnFPRFhKZ2F2TW9xZXFmZng4QTZLaGcwa0xBT3JYSzQzdW1KVWhpTUI2MzM4dE9IbHNYYWlhdjRnSDZHUG9GbzM0Y1VrWEVkY2VEb2dpSXBKSGNwWnJ3YUVaZW9wM1Q3aHpoSGxRUnBISk9aVXQrWWRqVnliQy9JMmVuNmdGMjdwdVpkTFhIU2dvQkd0akprb1Q1dGp2Yko1WWs5WVdYaHp5eXNva3djNHczNmpjdlVRVEtBUE1nQXoraUJ5Tlc0ajBLcXdHU2RCMXpqeEZjOXhvYy9Ua0FxZlcwSjFxWGJlWG5scmh6SFdQNC9kck9YK0tLS1pxM3VtYnBOZkQ2RXo1cVRueWt4ajhwbnIyV2RFZVVDWldkOTZZY3MycWVXbXY5RUlncVdydzVud3JLaE5qNVJmSzA2NXdUZWc2MFdLWjU5MHdXRjlMek0xZ1dFL2l0U0hDZ2N2NmFPSjNhRVRHV1AvU2pESlFVQmFZY2ZMeFlFNU50clF2ak5HcHVIRlkvNVhHdEIzS1dqWElkWlVFMW91ZHRqNjY0T1podVEyUERTQ2ZmSC92aGJKZ1c2Z0szaXYxM3RZeUJTaUJ6bVVzdWVhSE9HdUZJeUtpaDdxUzh3dFRHTGRjWDZuWTJaRkJZSmZQZXZaMTUzb2JKdXVvM3FFNnVndkRRTUgwL0VwZlhZZTRpUFVtbHQ5OXcwWWdTNEt0dTZaMWFZVnpYZGdWY29maVlVQzhzdzJiczBSQUNiQzVMa1Y3a1ROMndYVStuTjBvQ1lLaUxML1oxWmswbGx0c1gvV1BjY09PR3pjWENMUkwyRmxvdjhyM3BOeVNMV1AweGFCUUdodUlZNmMvYVJvRDZZOXphdG9seWFzeTVHbEJSQVJOK3Ixdy9tWW9laEJ5WnVxdnVINmhDWGF5bnU1L2szR3Q4emdoc1FoNjVwVVYvbDRQa0prMThmNGRzbEdyMUh4eWRJVjQ2YldtVzFwTlNsQ01PeXhBcW5IUEhWd1BBTjJHN3ZpRGZQbkpZZEhXOXlZdkZTUTBhczM5OGtyNkNRWnlJMXRWWXJDZHNGdllLRURrcTI2MTNHWmxsMjRPaUpiYnVHV0VJUk52RDR3VzdsSmlmYk1pQnZkSDNNci9PUHNHYStmamNmaWM3MlpGSnU5TUxoZTBSSnQ2aTVsdGxPdXB5ZU4xVjE1QUR0TnRFZ01IdzRFS3ZkUktWUDVnZytmL3FLQVZLdkV0dlVJOTRSV21DYzZEQ29BVmNRSnJzYnkxblhMOEdxcFZ0V0Qyd0VSd1pWWUh6dVlyM0UrTUFJNXl6eEJOcFlwL3kwTEVjeEdIYkZiUFRacXhuWk9WL1FaL1laWDNKK2svZXdseVhpY2RpWFNXN25RMnB2N0Rna2RqYlQ5NmRXa1hwbDlHQ0JmZTVoVGJXTDZscksxcW9oODYzSHA5c2dOcS92RjArYUlMWFZQK3Z5OHRxZ0F0MDZSRFlKaFRZWWVOSHY1c3luTXRiV2hPREh3TEIrdUVHVWtNZW5mUm9zWDl5N21XSkxIWmdMNGNwektwT1A5WlBhbktYT1RvZVcyanM5TmEwdURDUGI0YkdHdkdGTHh6Mm05U05ETmtDTFZFaEI3aC81d0dabHdYbXpVanZhQlprYnhrbGFEb1dYVG5iQU9jT01Sa1RQRks1d0JYYVRaTkFsUkhpOWh5TWQ2WkJ3OVp2RklFczY4K2wxcEhRY0dKT0RYR1JtYUZNUVMrQlVRV1JxcnNoVXpTY0d1cVljdTVsc1FtRExTSFdnaitHRnEycGE0eGQwZGJRSVN0MDdETGo1RUtmRFUzOXNCRGo1bncvd2FUNzhuYmtXMDd6cE9PbFFEd0F5dG5aRWthdEJtMzUyQnBhaEg2SkxRQzFTNG5TWTlKbmhsS09EOHJLRE5NVTR6VFJOU3FxT0JTRmlwMlRJaU0ydXYvSlVPSkNpRUNYSkFaY05vcEhwZ2UvNE5icU5ycDlzYlBTM1c1T0ZpMjdWMktON0htVk9YY1JWY2FNenZsS1YrRDNIdVUxeGxPdnlGTWI4WFhtZGRyRFV1dDBHWEhTVmNpYys1TDBuUWc4UXVKMHBIVzM1MkVPMHJ2NnRTV3cwUUV6NzZJUzNhWnkwZmkxVC82ajQwTVptR1E1NFJPTDBrRlZwU285UWhTWjgrMnE4RnFGOW5DYWJkOVFzcUVSRFQ3VzhqaWo3QklMVjZ3azMra1lkMjZReGhObmlOOHJkYTZvRnpXb25Ddzl2dzUwUHRwWS8vTUpvd3FLWGFhRFNzY2R4K3FDRWVBWm0vNWxYZFdMb2tHaXRhRU56SEtXR05vYlpJTnVyM29lS25lYmVuMVY0amlvb3RiQjA5WkhHR1R6ZGNDSHZhUXZMWjUzSndTTFdYYXM4NXF0L0ZUVHpvM3NPYUlESFBJMWVQNUhrdENQMHFTL0pyeGZFbVhtdkRrQUt4L2x6cGhLY0tpU1cvWmdqMVh1OTViZURqTklIcVBVZzF5M0d3bTBWbzlJcjR5cGhtY1RoMXZtRTV1bHNlVXJ4SlJ6TEVscGZzR2MxeU5QNHhHY1NsL05HODd6SHdMTTFIRlN5MWdCN0FJTFY4VkpCb29XdHJXQ3pqL1Y5YVBBeU9ySTFYaUpOQmlNamk0SnpCc0VvR1pNQXREc0lyNk5kNlZ2ejlvYUlubUZuUXRjWHE2c0wyTE11NjcvUFlzSGhtN3E3UUFrbHQ5WXNOaGpKUWlzcENkbFdHRk9yc0lFdWpTbGJGS0gvUldyRUwzWWJOdUV0bTRqUWY3MnNQUEMyT0M3c0JqMDZoQjVVZlZUcDM5SlJtc3pmNGUzVE52NHo0SEUramIxVlNGQkQrM0tnaHpwQTNjREVnZEphQmE2ajFrbnJ6RjJUOUZudDJrTTBFSmwydUxuS0dCUnBSU2IrZ2FUWVh3NjlaaUtJa2kyY3Q3dS9sd1BpUXFRU2FjSzJ2M3FLNmtWNFUyb09Xd3BNTkI1WXpPeE1JZTBGeEJoZFl0dEJPT0FNM0dGOWlIaFJObWlhMG5GelVRcXc0b2RzTWVRaU84cnhWNDZzRGZ6bmRpVjc3SzNaaWR5anpCalRPMEpBK0R1NU9lZ1dTaUdTZTNzdUx3Rll0U1VKbTZIN3J0am1hbEhKNEMrTisvdEJmNHVVdlRXaFFkejJOUHpiblV2bmZ4c1YyazlFMTRZSkg1UjZTUndTY1czQ1MzV2EyYmZwSnUvSUg4cGZ4RTVzQmRzZlBmMjNYR2FBdVBocmt0TVBRUzdQaEJWeGkzUk5vb3kwd0NGaTZRMWFTT2FxREJyNS9Gc1cxNy9uT2NOL0tDYmt2NFdiZlZ1eGZBSGQrSXl4M1RTbTRqVFlPY0QvZXcxLzRPT2QxQjdVK2g5Qm5kSjIwRWZiQXNxZVpuRlNyWnpFMWJLRjFwK05VaDRaMnBUMlVOYXo0WEQ5MXA1Z3JPZUsvTkdnUEJvSjIxVis4NXpISmpncjNsYWg4NVdMNFV3YUhHL2tuOTAzZGdqMTR5clYzTis2OXFJeW04ckxtWFFCeHRJYmJaaXFJM0RTNXRJaWJkd3ZUQzU3UnNzaUJ0ZFRFWWVnbFI1SGpTOWQ1ZkZpWjhNeGxsMGhaUXJaS3NERHZUZjMrZjBSVzNDV3RLTFZDRDRtaUw5WUkybXl0SXM3Q3JNSDZ0anFVbWNoNjZ2eTJJRFhqUXltVGc3cXMvSGRwQ2J2U0FvdWt2cUJlam9FRVVwSG5scko3K3B6SmJiUm5jQXFpUDVQd1VzWGZNNXpxbjJueGRxT2RUV3VYOTFGc1FUU2JrcUdHMkNEWHRiUjFiK3JiSVZFVWNHdHgvK2c1eVNYNnVFcFdYV2ZnZ1lGQzUvMWJuTUdmZ0VJYUZnVkp3L20wYVg5b3I3dzQ1T1VqNGpnNHdENG5sd3VuR1ZJUE15YUR5d2dxeWZCOWw2S3AwMjZPa2ZldnlVMVNiQkIybTN0bkZtTDhCSEVuSVplbEhyT2luV1dqMXBTc2M1WkxySU9nRWhIMm1TY3Eya3BSOXdjbU9obkRTV3A2d2h1N0RjTTZnRkw3ZGJ3aU1hSGlTMzNYR05TQlVpRWVQYnJUTVl0L0l6TjVjSGpIM0JFZ2JwY3lRMERnNHEzaVhSTElkYUM0eS9nWHkyRU1iZEFYMFRlUzRoVmxscEtFcEJpMmNsVFgwZWJFWk9aTDFpMWhpRHh6aTJGcG5xNk1qd2hrYmhzT0ZPMGtGYzdYWWVndGZFeGFsUEFWRHR1VUNRb3BScjBtM2s1b3dYSksvNUtUUktRaW5sUm1LakttN1RzNGdsRUhycHpWYWhkV1JZSWtuU2hrV3cxMnNHODdlTFJqa1pZbkxuaDZLMkEvNzlXTkpMZXYwQXlpa1VjbjlKaFBRTS9oUjBxWWc3WXQ4ZmxrQWtaOGk5Snp2Z0pWRHkzRzMySWdtY2J1MjVRTWZaUzZJV0hUSmJ1Uk5ndHNGdm1ndjhtQUZ6UnV3bUdvaXVWUmtTVURRS09VRCtObDdUcm12b0NPWDhiZFgvOHNMZnV0bGZ4YU5DcXRVN2gxcEQ5R1JQTHVSUzUvdzZVSkc5Q0JOM3JMZS9Ha20zQTFDMElaY2E3eEYwZnAzQ3JpQlN2NzFpN2VkM3crcGt2cHVMSUZ3NHZsV2thRkplZTZuQkl4WEpVMmZFMmVkTWs4RXFwSXg5SHlaZk9IbVRVY0QzN2tvbGJPTXlUeU9pQ1RNYjFreFFCNHR6bFh2VG5GK3l2Z3JPUm5GZVVYMmUrNk1lQWY4cXc2TUUwQ3NQOTBqbDR4dHpIQUtxZFlLWjNaSFhyUkZmeEJyWXY4bEN2c0ZGWEtOY25hU25WWkJ2bFVQekI2NmZYMG9WWTIxWkxwMHRUMUE2NzF5aU1odktOTHRFckZXQm9COTFTTVI1SWFlMnlidDE2cTVCWWJod214K3ZxYUo5Zjk1QzVRNUZ2ZWt4bGg3Z2gva1ZlMDl2WXI1cStpVFNqdEo1YWpvcXRBTklJejF5dDAwR1o3RVViRnBvN0VSVGk4c0E4V2JTUWFCZnJjTHljRWw0SVdjVGRTdjhYMjVIcytWeGgvM3FDQVlMdDRjam5Pa1ltS21xamc4c2hLN1RSQmdDcnFWZi84RjdqN0ZjaW9PSTBHakZYZ2tHQWExRXl3dk9RM1k5VXhNTFAvOTBIOUVaSElBRGVZckhpbzAxM0FUdlhNaTY2bU9ETUQrWXRCb21sR2YwRFYxU0g3Qi9wR1hxYS9uTFFxQUE1cDFrZEFBa0t1KzQzdStzNnVhOGk2bHRnMnNDdVlnQ0JzYUFhSXQxWXJQOGp3MG8wZEUvYmo4TTF0Y2JXOFo4UFIwb0VFOGNuK004dnVoU3JTZ2l4ZXl6bHVJSWEzR21BcDRWZ0pldHBnNjllS2RpT1ZlVzFNVUNxdit1bit4MnNOWStUNzFjZTZPMzRqM3FmVFpiNEVrS2haTWk2aEdhOS84U3ptM3FZRklUcDcrb0VrN2tzenNrSTZDZDVGSWd4c0UzTVc1elVlUEVoc1hvVzM3V3ZBZ1lpQjlTRGkyNHB0blk3dFg5R3JKb2VURllJZUt5Vi9mNEZSdmlSMVpjR2tTTEU3MmJqSGs4Skw4eTA4NlJvMVB3K2x6cWd2T01xVmV1YXhEd0laQ3lDZGxlbUJEZnNKdkFBNmVXSkhUdG90VDJjNS9Wc20wbEdGU2FxaWtEOWRRcGJoYzlZaG1rUVpEU1g2SU9FODUzalZOUUxuSEVsb0JHVEpLZEVMR0lRQjVOQVM4dzZ1R3kwN0JzbS9sYllsRG1OS0dWRXdnVm42bUVYN0xQTGxmSlJLdTdzR1pJUW9TRS8zUTA0b0thZUJPaTNIMzRFZ3VnNG9qWEl1SmRSU3pNUWU5U2hNQUNiNDAxY1RzYllNS1Y3anFsWFQzL3pGWG1DRkNsNmZuZG9Wb3RYT2xKVUlWQ3phSnlmY3gxUnFjZnBpTWJYUGMvUWR3RzR0MlYwcGRMY1lOaHp3dDFqd0plZHBYU2dCNlhxVWNDbVFDMTB4SFFrYTRxMWJmRFg3VVl3U3dOZVUydzQ1UjB1MHBrdGFhMXZ4SzJDNnVkU0Z2SkZjTTZSbXluOVl3T1VNbzBRRDlaamdncGRzRVhTZ3lUWENCUGFjUHR0YTBtRjhvRjM3NlZYRUpzNEhkdVVBei9VY3pJcUxZU21lMy9SdXk4aitCY1gydVJUVk9WLzM0bWVLTG1OMHNrY1BMWFQ2VlFHTWtjTFQvK0sxUFFsc0t5TWtRYXAyWnZiTHJEVjQ5UzJkY28zK1l0KzZ5V0ljN3BQdyswUVR3S3A1NGdVdVU1OEVia3hxMytuQmNSOW50M212S0pPZmtQaEZqeVE0WVhzeFlRY3dpdUZMeDJjcHZhOFMybnNxdnRKNGxNdEFsQzJaU3ZUMzJEcEs2NWZiaWR3ZXIvYWVyVTFLUjFqdkZxS3JETzN1SjMwRStKQytoVlFqTWpEanhCY2FBZCtFT0pPSFVqck1wYjFCcmRxa0FaaHMxeUhDSGJOekVMang0V2xUSW81WGM2UkpjdkxZcHhzckh3QVA2dzJLSTg3N21rNFhjUm5CRnV2dkZqOW8wT24raGZuei9HbDZzODZYdXVqSy9tWUhJZEhuYzFYRmxEek5aL3hCTWNFLzVZYXpIUEFQck1yZW1wYTVISmQ3UHRtN21ZVm90VllyT2lPc1JoWHUzRDlVU01Cck1mT2t4L21oVU9jTERXODJUaEpzQXV3aUEvTWk1cU54RURRR3dGSy9lbDF3a2Mybk5tZUgzTTVzTlRDcFVLOHllS25RdlV2ZVFyNzBWYThrYi9RcGJDelNPSEM4RTc0T0wyVWljK05qRzNBbkt0U2pvZSt3ZjE3R0FBN09SdkV6TW42ZVg3bndpZHMvR1FtYVhDVDZiQWdpMTQ5cmVWbGNZdXZUSDZpWGVyWHNkYzZKOGY1aU1NMHlpN0lralpXb1NRbTcrTnlpcFZHRUluaz08L3hlbmM6Q2lwaGVyVmFsdWU+PC94ZW5jOkNpcGhlckRhdGE+PC94ZW5jOkVuY3J5cHRlZERhdGE+PHhlbmM6RW5jcnlwdGVkS2V5IHhtbG5zOnhlbmM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jIyIgSWQ9Il8yYWVhN2E2NTFkYmI2ODc5MDJjNDgzNDMyZWQ4NTc4MCI+PHhlbmM6RW5jcnlwdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI3JzYS1vYWVwLW1nZjFwIiB4bWxuczp4ZW5jPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyMiPjxkczpEaWdlc3RNZXRob2QgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3NoYTEiLz48L3hlbmM6RW5jcnlwdGlvbk1ldGhvZD48ZHM6S2V5SW5mbyB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU+TUlJRXNEQ0NBcGlnQXdJQkFnSUJBREFOQmdrcWhraUc5dzBCQVFVRkFEQVRNUkV3RHdZRFZRUURFd2d4TUM0d0xqRXVOREFlRncweApOREExTURnd01EVTBNVGxhRncweE5EQTFNRGd3TURVME1UbGFNQk14RVRBUEJnTlZCQU1UQ0RFd0xqQXVNUzQwTUlJQ0lqQU5CZ2txCmhraUc5dzBCQVFFRkFBT0NBZzhBTUlJQ0NnS0NBZ0VBNWhxamFyb0pwQithUjhGTUU3aFE5bk1WMGg3TXBLdG1nRkxjSzN2d1A2N2YKZUFLK3hkdDE3aThSeVVoeGlsOUZDRlI1SzA4V2p3bzNOaUhacUhxRUtpdHcrSUpTbmRqTFNzb05nS0VJYWlGU3VnMmVWMW9ZRWx6MAo2REJYVHhjOGlxL0xhem5kcVRVb201MU9kZTl5STlBR2E4OGNETTVpT3FxOW1odUd1dnd1THRveVU3OExkK3MxRWE2TWdmN0w4TTdmClpWTzdOY3UrRmdJekk2R3QwMzVvaFlDTEJtT29NN28wdWo3RGNNRXZLT01Geml3RjQwd1lteXAzaENMbHEzcXdrTTlwVFZKbHR1ejAKQnQxdnFEZHJxM2tUaGVBOUpITWF5UnozSS9CWnhBVjNpUmQ0aHpMS1RrZWdEOFRvVEdVMTBHbWUrWkFyMXcvZXJjNWhWck0wL1hCbQpIUWxuSTVkMzFHVS9tZklrbTBYUFRHUlNwUHk3RStkVXZqOWRqdm0vVnFEZG9qZjN1dXdpckdlTE1SbE85UC9sQ2VyVGt0VzNnMjdTClY4Z24zRVRtMk1tN3JrTnFmMjRLSnBEdjB0S0Rvc2diZGFIcjJJRVlENFJwcXlTcDhrZDI1Qmh6dXNocUtSa1M4WHU1dDdIQWxWU0gKd2lGaHVMcXJyNGRVZmtCOGtaZU0veWNmWkxDbjdvTlVERmRnakdZU1ZNcGFrTDk3c0M5c2xBVzQvOFV0WFhaeExxY3lxL1l4ZHBDeQpzUFlQMWhzQXArVmdQQzdHSTZDeWlOb2pLUE9wdE1xTFpSWW5WaUt4bE9pV0JKQnpVQlJVVnVhYzhMWHJNaUR3OGJ0V0dhMUdoNXZUCmh1RlVLc3ZtUm9ldWs3ZXlYRU45SjdqNitmVFlqbnNDQXdFQUFhTVBNQTB3Q3dZRFZSMFBCQVFEQWdUd01BMEdDU3FHU0liM0RRRUIKQlFVQUE0SUNBUURBUEZVbzBQZ2E3dkI0SWp5OXUzcXBXTFFTQ2Q0eGZ3OGw5MmlxM0pxTFZYQng4R2Y5WFZ5Nkd6YlhXSWU2cG1RSQp6bW9tL0NXUXZoNm83a2MwRjR5NGZ0c1dmcW5xM2swK0hjWDRIZXUxUE4ySFNuVVVQTnNrNUFkZ2dkMzEyOU1ISWRmYUtiOGJTdUxKCnZTTWVNYXljcm1zYitnRUY2SkZQOGtHV09QNHhRWWpBVk9EY0ZiT3lBZkV1VkFodWp3MGJxbExIVCtFbDR2bGZCcnRkVStNWnp0SXEKUWtHRFc3Y21tODZaR2lCci9nYTk3QkNuT0NyZ1pYbHJnbWlhOFNtRjdSZmE0OC9Yemg3YkRtUGZnbUhnbEw1SnhocFJYMklvUFk1WApJdG1SOElhWUtoT0JPck8vcWVyY0o2WjNyUTZmSXJzOEhyWWdlVE8vdUU5d3c2V1JXQ1dEYUNSNG9XRFZ3akt6R2ZQMW9KdEFJUStVCk5qT2RkSDVvdERhd1hKUmxRV3ByNzJxVDcrV09LL3l6SmhOMHhtWERrbXQ1cHNNWS9DRG40a1hNTTB4YVJwZllPbjVTYzFvZWxRK2gKSW04L3JIVksvMGtyaENET25pcWorTC9uZTJTb3lvWFlnUzZvME5sa05odFRIbWpqb3NFN0hWNkpmQVVncTJEOWRxMDBKTzk2N0kzUAowVkY2RjhsY2RhcTB0b3ZKaEtXUmpycmlnWWQ3NTYvM2FUMkI4M0pXQTFSQTluaVhtclhmbkFQWnJOQ2ZXdmorWDJhbFVOL2l6ZElxClJ0czBVcFdUb1ZVcjBveldnbWJtcDVaT0dZT1FoK2xOY0FwM1Y5bE9yZGJaVlNJVE00N1JZR0JaYVpOREEyUGJEekMxM01TL0VqVEUKdlNrb253dGxDZz09PC9kczpYNTA5Q2VydGlmaWNhdGU+PC9kczpYNTA5RGF0YT48L2RzOktleUluZm8+PHhlbmM6Q2lwaGVyRGF0YSB4bWxuczp4ZW5jPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyMiPjx4ZW5jOkNpcGhlclZhbHVlPm4wR3IzSWtSSWRjaDZRVHhsTDJRWkNuUVBGM3R4T0hHbXpSLytObzExUlRSZjYrczBYUGxvK0RqYVd1RVdwMkh0MldkRm5UdXM5RmJwSGF0UVdiSVI1SVdUQXFrN3ZXSWlhTW0wV3prRnVPR1hrYi82ckV4cUdOYnY4UTlJUHVMZW85VVNOOWNrZTF5RFlFK2F2NngyU1ZzUjMydHJINXBCV1VyYkNCV0pGNWwyVXRHVlNwWEVwdUFWenppUVhDWTBycXltdmZSVmFGbGhWMVMyb2RXVW1LZU5YL1ZKNXJuME5adE5Zdlo1ZXFhWWJjNnpUQ2sxMEVkUjB6czV6UDFmQmxYMmtDVE8zdlZqNWhHKzV5TUdvRFR3OWxYWXBZUDNtUVpERHFlU2hDcnNKeitPNjNpU0oxZkdqdndhSWZ5QTB4ditON2MrR3I1Zlh1UzR0clozcU9GYkx5TStNS3NWVUNJNG1wTmZsUHRYNjEvSm1NRXFBZFNreFRadFZtY3NDbDZyNlVoSVlVM2ZEOS9JaGFWZDZtSFVvMVJ5WGVnOTlZNTVBMzl6VVVtNWViNzFsVC9qZjduV0p1ZWI1SWZIa1hMQ0ExVldBZGllV2hTbHNtKzBUd1ZKRE5TYTlocUYwb1ZLL0FLcTZEV202ZStVUmVyazF5NFJscDZQa2owb1hBclJ4dkJFTTJXT0VBQWJxdndyeldtSlIwZ2lnQTdVMHB4YnpGcmRoNzdzOVZuRkFQc1Q2aDZ6WmYrbWt1d1JIQUh4Zmk1dURzU1c3RWw3cVdmMjh1dnhKeXUxL0FjbVNHNDRxSk0xelZhSlQyVmU2bXZFYktOWVJ6K2FCZzVNSG1hcWdjQm82VTd3Uk16bHVPNGlSbjVJSVZ1eDlGRTY5eUVhbWliTFNVPTwveGVuYzpDaXBoZXJWYWx1ZT48L3hlbmM6Q2lwaGVyRGF0YT48eGVuYzpSZWZlcmVuY2VMaXN0Pjx4ZW5jOkRhdGFSZWZlcmVuY2UgVVJJPSIjXzllOGZkMmNlNGFkMDIxMmM5OGU3MDkxY2E4NzY1ZmI0Ii8+PC94ZW5jOlJlZmVyZW5jZUxpc3Q+PC94ZW5jOkVuY3J5cHRlZEtleT48L3NhbWwyOkVuY3J5cHRlZEFzc2VydGlvbj48L3NhbWwycDpSZXNwb25zZT4=', RelayState: '', }, config: { entryPoint: 'https://frontapp.oktapreview.com/app/frontdev584714_front_1/exk7xdi6axPfombzx0h7/sso/saml', cert: 'MIIDoDCCAoigAwIBAgIGAVaZ04POMA0GCSqGSIb3DQEBBQUAMIGQMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxETAPBgNVBAMMCGZyb250YXBwMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMB4XDTE2MDgxNzE4NDUzMVoXDTI2MDgxNzE4NDYzMVowgZAxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKDARPa3RhMRQwEgYDVQQLDAtTU09Qcm92aWRlcjERMA8GA1UEAwwIZnJvbnRhcHAxHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvplQONVwknRy1iBnaoZtsOz28A7XW2tRpFW+0La7RJexbziIwEy1bPZENhfwjPZA1oHHZqi5l315BxXKWJqmmNmbDCFDo+/FYFCoHXliiLm9vqDbR1br6ByqeY0GfxyTPKHZxb2FSes30TffDknpMQd/8kA9YWaW5xDlu2ivWJI+sfcOJOMd6t+gcfXj58a5fP8Mwm6Y220KeZSvrVpEV2KDp9hln7fhhoxHZ7K/BYbidqdwLzeUQXpb6LIrxtKdug2FofS+ONs6yLIQRmrbCB7SVX1QA8JInMn+fzrGtZmFiHR0aFbyhiO78v/ufDa6S+XpYyp2b6D4SnzeggnobAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAJ2wcFVffFHSd9pj6RgoNHXZBsWp0HUZrNekiSbgomr4tSDefWtKb04nFIlRytfVs/k74wmbNiRCE8nDVBrBDFA/+Tv/3PowZXHjXKBofUuScTP4/Tw1N/ywf7V+XY5kV3VmLBL6ax+ULJauR/YGIIMsIc/rS2D04aAcScU9pqVh2ML7nTH7gFqYrxypavmVk6K94vLjs0ggF2TGp7tXCRjeOlPPJS+MOJHJhTBWYFWvBLclU3zcri3ws7GqJMpeiHa7rMoHV0onxWsZTZW57ybaIWKLt1goAooC7hq0rx7oNlOvrys5lllhBySYYC3ycqca/D0+GxXLcEr9QwP7TVw=', decryptionPvk: fs.readFileSync(__dirname + '/static/testshib encryption pvk.pem') }, expectedStatusCode: 200, expectedNameIDStartsWith: 'xavier', mockDate: '2016-08-19T01:15:32.681Z' }, { name: 'Onelogin -- invalid cert (from Okta case) should fail', samlResponse: { SAMLResponse: 'PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0\r\nYzpTQU1MOjIuMDphc3NlcnRpb24iIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6\r\nbmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIElEPSJSNjg5YjA3MzNiY2Nj\r\nYTIyYTEzN2UzNjU0ODMwMzEyMzMyOTQwYjFiZSIgVmVyc2lvbj0iMi4wIiBJ\r\nc3N1ZUluc3RhbnQ9IjIwMTQtMDUtMjhUMDA6MTY6MDhaIiBEZXN0aW5hdGlv\r\nbj0ie3JlY2lwaWVudH0iIEluUmVzcG9uc2VUbz0iX2E2ZmM0NmJlODRlMWUz\r\nY2YzYzUwIj48c2FtbDpJc3N1ZXI+aHR0cHM6Ly9hcHAub25lbG9naW4uY29t\r\nL3NhbWwvbWV0YWRhdGEvMzcxNzU1PC9zYW1sOklzc3Vlcj48c2FtbHA6U3Rh\r\ndHVzPjxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6\r\ndGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz48L3NhbWxwOlN0YXR1cz48\r\nc2FtbDpBc3NlcnRpb24geG1sbnM6eHM9Imh0dHA6Ly93d3cudzMub3JnLzIw\r\nMDEvWE1MU2NoZW1hIiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIw\r\nMDEvWE1MU2NoZW1hLWluc3RhbmNlIiBWZXJzaW9uPSIyLjAiIElEPSJwZngz\r\nYjYzYzdiZS1mZTg2LTYyZmQtOGNiNS0xNmFiNjI3M2VmYWEiIElzc3VlSW5z\r\ndGFudD0iMjAxNC0wNS0yOFQwMDoxNjowOFoiPjxzYW1sOklzc3Vlcj5odHRw\r\nczovL2FwcC5vbmVsb2dpbi5jb20vc2FtbC9tZXRhZGF0YS8zNzE3NTU8L3Nh\r\nbWw6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cu\r\ndzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpD\r\nYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53\r\nMy5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PGRzOlNpZ25hdHVyZU1l\r\ndGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1s\r\nZHNpZyNyc2Etc2hhMSIvPjxkczpSZWZlcmVuY2UgVVJJPSIjcGZ4M2I2M2M3\r\nYmUtZmU4Ni02MmZkLThjYjUtMTZhYjYyNzNlZmFhIj48ZHM6VHJhbnNmb3Jt\r\ncz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcv\r\nMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48ZHM6VHJh\r\nbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94\r\nbWwtZXhjLWMxNG4jIi8+PC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRo\r\nb2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRz\r\naWcjc2hhMSIvPjxkczpEaWdlc3RWYWx1ZT5EQ25QVFFZQmIxaEtzcGJlNmZn\r\nMVUzcTh4bjQ9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2Rz\r\nOlNpZ25lZEluZm8+PGRzOlNpZ25hdHVyZVZhbHVlPmUwK2FGb21BMCtKQVkw\r\nZjl0S3F6SXVxSVZTU3c3TGlGVXNuZUVES1BCV2RpVHoxc01kZ3IvMnkxZTkr\r\ncmphUzJtUm1DaS92U1FMWTN6VFl6MGhwNm5KTlUxOStUV29YbzlrSFF5V1Q0\r\nS2tlUUw0WHMvZ1ovQW9LQzIwaUhWS3RwUHBzMElRME1sL3FSb291U2l0dDZT\r\nZi9XRHoyTFYvcFdjSDJoeDV0djN4U3czNmhLMk5RYzdxdzdyMW1FWG52Y2pY\r\nUmVZbzhyclZmN1hIR0d4Tm9SSUVJQ1VJaTExMHV2c1dlbVNYZjBaMGR5YjBG\r\nVllPV3VTc1FNRGx6TnBoZUFEQmlmRk80VVRmU0VoRlp2bjhrVkNHWlVJd3Ji\r\nT2haMmQvK1lFdGd5dVRnK3F0c2xnZnk0ZHdkNFR2RWNmdVJ6UVRhemVlZnBy\r\nU0Z5aVFja0FYT2pjdz09PC9kczpTaWduYXR1cmVWYWx1ZT48ZHM6S2V5SW5m\r\nbz48ZHM6WDUwOURhdGE+PGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlFRnpDQ0F2\r\nK2dBd0lCQWdJVUZKc1VqUE03QW1Xdk50RXZVTFNIbFRUTWlMUXdEUVlKS29a\r\nSWh2Y05BUUVGQlFBd1dERUxNQWtHQTFVRUJoTUNWVk14RVRBUEJnTlZCQW9N\r\nQ0ZOMVluTndZV05sTVJVd0V3WURWUVFMREF4UGJtVk1iMmRwYmlCSlpGQXhI\r\nekFkQmdOVkJBTU1Gazl1WlV4dloybHVJRUZqWTI5MWJuUWdOREl6TkRrd0ho\r\nY05NVFF3TlRFek1UZ3dOakV5V2hjTk1Ua3dOVEUwTVRnd05qRXlXakJZTVFz\r\nd0NRWURWUVFHRXdKVlV6RVJNQThHQTFVRUNnd0lVM1ZpYzNCaFkyVXhGVEFU\r\nQmdOVkJBc01ERTl1WlV4dloybHVJRWxrVURFZk1CMEdBMVVFQXd3V1QyNWxU\r\nRzluYVc0Z1FXTmpiM1Z1ZENBME1qTTBPVENDQVNJd0RRWUpLb1pJaHZjTkFR\r\nRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFLckF6SmRZOUZ6Rkx0NWJsQXJKZlB6\r\nZ2k4N0VuRkdsVGZjVjVUMVRVRHdMQmxEa1kvMFpHS25NT3BmM0Q3aWUyQzRw\r\nUEZPSW1Pb2djTTVrcERETDdxeFRYWjFld1hWeWpCZE11MjlORzJDNk56V2VR\r\nVFVNVWppMDFFY0hrQzhvK1B0czhBTmlOT1ljanhFZXloRXl6SktnRWl6YmxZ\r\nek1NS3pkck9FVDZRdXFXbzNDODNLKzUrNWRzakRuMW9vS0dSd2ozSHZnc1lj\r\nRnJRbDlOb2pnUUZqb29id3NpRS83QStPSmhMcEJjeS9uU1Znbm9KYU1mck8r\r\nSnNudWtaUHp0Ym50THZPbDU2K1ZyYTBOOG41TkFZaGFTYXlQaXYvYXloalZn\r\namZYZDF0ak1WVE9pRGtuVU93aXpadUoxWTNRSDk0dlV0QmdwMFdCcEJTcy94\r\nTXlUczhDQXdFQUFhT0IyRENCMVRBTUJnTlZIUk1CQWY4RUFqQUFNQjBHQTFV\r\nZERnUVdCQlJRTzRXcE01Zld3eGliNDlXVHVKa2ZZRGJ4T0RDQmxRWURWUjBq\r\nQklHTk1JR0tnQlJRTzRXcE01Zld3eGliNDlXVHVKa2ZZRGJ4T0tGY3BGb3dX\r\nREVMTUFrR0ExVUVCaE1DVlZNeEVUQVBCZ05WQkFvTUNGTjFZbk53WVdObE1S\r\nVXdFd1lEVlFRTERBeFBibVZNYjJkcGJpQkpaRkF4SHpBZEJnTlZCQU1NRms5\r\ndVpVeHZaMmx1SUVGalkyOTFiblFnTkRJek5EbUNGQlNiRkl6ek93SmxyemJS\r\nTDFDMGg1VTB6SWkwTUE0R0ExVWREd0VCL3dRRUF3SUhnREFOQmdrcWhraUc5\r\ndzBCQVFVRkFBT0NBUUVBQ2REQUFvYVpGQ0VZNXBtZndiS3VLclh0TzVpRThs\r\nV3RpQ1BqQ1pFVXVUNmJYUk5jcXJkbnVWL0VBZlg5V1FvWGphbFBpMGVNNzh6\r\nS21idlJHU1RVSHdXdzQ5UkhqRmZlSlVLdkhOZU5uRmdUWERqRVBOaE12aDY5\r\na0htNDUzbEZSbUIra2s2eWp0WFJaYVFFd1M4VXVvMk90K2tyZ05ibDZvVEJa\r\nSjBBSEgxTXRaRUNEbG9tczFLbTd6c0s4d0FpNWk4VFZJS2tWcjViMlZsaHJM\r\nZ0ZNdnpaNVZpQXhJTUdCNnc0N3lZNFFHUUIvNVE4eWE5aEJzOXZrbit3dWJB\r\nK3lyNGoxNEpYWjdibFZLRFNUWXZhNjVFYStQcUh5cnArV25tbmJ3Mk9iUzdp\r\nV2V4aVR5MWpEM0cwUjJhdkRCRmpNOEZqNURiZnVmc0UxYjBVMTBSVHRnPT08\r\nL2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5m\r\nbz48L2RzOlNpZ25hdHVyZT48c2FtbDpTdWJqZWN0PjxzYW1sOk5hbWVJRCBG\r\nb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9y\r\nbWF0OnRyYW5zaWVudCI+cGxvZXJAc3Vic3BhY2Vzdy5jb208L3NhbWw6TmFt\r\nZUlEPjxzYW1sOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2Fz\r\naXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48c2FtbDpTdWJqZWN0\r\nQ29uZmlybWF0aW9uRGF0YSBOb3RPbk9yQWZ0ZXI9IjIwMTQtMDUtMjhUMDA6\r\nMTk6MDhaIiBSZWNpcGllbnQ9IntyZWNpcGllbnR9IiBJblJlc3BvbnNlVG89\r\nIl9hNmZjNDZiZTg0ZTFlM2NmM2M1MCIvPjwvc2FtbDpTdWJqZWN0Q29uZmly\r\nbWF0aW9uPjwvc2FtbDpTdWJqZWN0PjxzYW1sOkNvbmRpdGlvbnMgTm90QmVm\r\nb3JlPSIyMDE0LTA1LTI4VDAwOjEzOjA4WiIgTm90T25PckFmdGVyPSIyMDE0\r\nLTA1LTI4VDAwOjE5OjA4WiI+PHNhbWw6QXVkaWVuY2VSZXN0cmljdGlvbj48\r\nc2FtbDpBdWRpZW5jZT57YXVkaWVuY2V9PC9zYW1sOkF1ZGllbmNlPjwvc2Ft\r\nbDpBdWRpZW5jZVJlc3RyaWN0aW9uPjwvc2FtbDpDb25kaXRpb25zPjxzYW1s\r\nOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxNC0wNS0yOFQwMDox\r\nNjowN1oiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjIwMTQtMDUtMjlUMDA6MTY6\r\nMDhaIiBTZXNzaW9uSW5kZXg9Il8zMGE0YWY1MC1jODJiLTAxMzEtZjhiNS03\r\nODJiY2I1NmZjYWEiPjxzYW1sOkF1dGhuQ29udGV4dD48c2FtbDpBdXRobkNv\r\nbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6\r\nY2xhc3NlczpQYXNzd29yZFByb3RlY3RlZFRyYW5zcG9ydDwvc2FtbDpBdXRo\r\nbkNvbnRleHRDbGFzc1JlZj48L3NhbWw6QXV0aG5Db250ZXh0Pjwvc2FtbDpB\r\ndXRoblN0YXRlbWVudD48L3NhbWw6QXNzZXJ0aW9uPjwvc2FtbHA6UmVzcG9u\r\nc2U+Cgo=\r\n' }, config: { entryPoint: 'https://subspacesw1.okta.com/app/subspacesw_subspacetest_1/kvjj46lsDQEQYUDBZIYW/sso/saml', cert: 'MIICoTCCAgqgAwIBAgIGAUY8zVPYMA0GCSqGSIb3DQEBBQUAMIGTMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxFDASBgNVBAMMC3N1YnNwYWNlc3cxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMB4XDTE0MDUyNzA4MjkyN1oXDTQ0MDUyNzA4MzAyN1owgZMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKDARPa3RhMRQwEgYDVQQLDAtTU09Qcm92aWRlcjEUMBIGA1UEAwwLc3Vic3BhY2VzdzExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKYX/UdV9HLXbNKv0yc6YJBtzdWNuGTPIXWVPCb0OsRvR54lq+0SLPQGJS39flWKiqtUiEusuih6GdLfNvFAVLGPqBTWQ4Lc7r5+zD5qnH6LiTM1KCbaF3uu2P+T+utsGqFUZawA9FEVNLkICe36X1yE40X+/jMygyieQPMeJABvAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAHSWPG4y1bNyJySgbFqDcS/6MUNIrSfkQYIxzIGQ37qy5qAW15YkBUiW9TsGJRcrgusVrZIia18eYz84Zn7FyUZNMFo24L7l6BS0WCitIQScBCKB4QWA/b1szqs7EtpOcPP01TYNq2ras+VqR3aWAXLX2oKfClV/SUwszRf5U85Y=' }, expectedStatusCode: 500, mockDate: '2014-05-28T00:16:08Z' }, { name: 'Onelogin -- valid config should succeed', samlResponse: { SAMLResponse: 'PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0\r\nYzpTQU1MOjIuMDphc3NlcnRpb24iIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6\r\nbmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIElEPSJSNjg5YjA3MzNiY2Nj\r\nYTIyYTEzN2UzNjU0ODMwMzEyMzMyOTQwYjFiZSIgVmVyc2lvbj0iMi4wIiBJ\r\nc3N1ZUluc3RhbnQ9IjIwMTQtMDUtMjhUMDA6MTY6MDhaIiBEZXN0aW5hdGlv\r\nbj0ie3JlY2lwaWVudH0iIEluUmVzcG9uc2VUbz0iX2E2ZmM0NmJlODRlMWUz\r\nY2YzYzUwIj48c2FtbDpJc3N1ZXI+aHR0cHM6Ly9hcHAub25lbG9naW4uY29t\r\nL3NhbWwvbWV0YWRhdGEvMzcxNzU1PC9zYW1sOklzc3Vlcj48c2FtbHA6U3Rh\r\ndHVzPjxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6\r\ndGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz48L3NhbWxwOlN0YXR1cz48\r\nc2FtbDpBc3NlcnRpb24geG1sbnM6eHM9Imh0dHA6Ly93d3cudzMub3JnLzIw\r\nMDEvWE1MU2NoZW1hIiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIw\r\nMDEvWE1MU2NoZW1hLWluc3RhbmNlIiBWZXJzaW9uPSIyLjAiIElEPSJwZngz\r\nYjYzYzdiZS1mZTg2LTYyZmQtOGNiNS0xNmFiNjI3M2VmYWEiIElzc3VlSW5z\r\ndGFudD0iMjAxNC0wNS0yOFQwMDoxNjowOFoiPjxzYW1sOklzc3Vlcj5odHRw\r\nczovL2FwcC5vbmVsb2dpbi5jb20vc2FtbC9tZXRhZGF0YS8zNzE3NTU8L3Nh\r\nbWw6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cu\r\ndzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpD\r\nYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53\r\nMy5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PGRzOlNpZ25hdHVyZU1l\r\ndGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1s\r\nZHNpZyNyc2Etc2hhMSIvPjxkczpSZWZlcmVuY2UgVVJJPSIjcGZ4M2I2M2M3\r\nYmUtZmU4Ni02MmZkLThjYjUtMTZhYjYyNzNlZmFhIj48ZHM6VHJhbnNmb3Jt\r\ncz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcv\r\nMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48ZHM6VHJh\r\nbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94\r\nbWwtZXhjLWMxNG4jIi8+PC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRo\r\nb2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRz\r\naWcjc2hhMSIvPjxkczpEaWdlc3RWYWx1ZT5EQ25QVFFZQmIxaEtzcGJlNmZn\r\nMVUzcTh4bjQ9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2Rz\r\nOlNpZ25lZEluZm8+PGRzOlNpZ25hdHVyZVZhbHVlPmUwK2FGb21BMCtKQVkw\r\nZjl0S3F6SXVxSVZTU3c3TGlGVXNuZUVES1BCV2RpVHoxc01kZ3IvMnkxZTkr\r\ncmphUzJtUm1DaS92U1FMWTN6VFl6MGhwNm5KTlUxOStUV29YbzlrSFF5V1Q0\r\nS2tlUUw0WHMvZ1ovQW9LQzIwaUhWS3RwUHBzMElRME1sL3FSb291U2l0dDZT\r\nZi9XRHoyTFYvcFdjSDJoeDV0djN4U3czNmhLMk5RYzdxdzdyMW1FWG52Y2pY\r\nUmVZbzhyclZmN1hIR0d4Tm9SSUVJQ1VJaTExMHV2c1dlbVNYZjBaMGR5YjBG\r\nVllPV3VTc1FNRGx6TnBoZUFEQmlmRk80VVRmU0VoRlp2bjhrVkNHWlVJd3Ji\r\nT2haMmQvK1lFdGd5dVRnK3F0c2xnZnk0ZHdkNFR2RWNmdVJ6UVRhemVlZnBy\r\nU0Z5aVFja0FYT2pjdz09PC9kczpTaWduYXR1cmVWYWx1ZT48ZHM6S2V5SW5m\r\nbz48ZHM6WDUwOURhdGE+PGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlFRnpDQ0F2\r\nK2dBd0lCQWdJVUZKc1VqUE03QW1Xdk50RXZVTFNIbFRUTWlMUXdEUVlKS29a\r\nSWh2Y05BUUVGQlFBd1dERUxNQWtHQTFVRUJoTUNWVk14RVRBUEJnTlZCQW9N\r\nQ0ZOMVluTndZV05sTVJVd0V3WURWUVFMREF4UGJtVk1iMmRwYmlCSlpGQXhI\r\nekFkQmdOVkJBTU1Gazl1WlV4dloybHVJRUZqWTI5MWJuUWdOREl6TkRrd0ho\r\nY05NVFF3TlRFek1UZ3dOakV5V2hjTk1Ua3dOVEUwTVRnd05qRXlXakJZTVFz\r\nd0NRWURWUVFHRXdKVlV6RVJNQThHQTFVRUNnd0lVM1ZpYzNCaFkyVXhGVEFU\r\nQmdOVkJBc01ERTl1WlV4dloybHVJRWxrVURFZk1CMEdBMVVFQXd3V1QyNWxU\r\nRzluYVc0Z1FXTmpiM1Z1ZENBME1qTTBPVENDQVNJd0RRWUpLb1pJaHZjTkFR\r\nRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFLckF6SmRZOUZ6Rkx0NWJsQXJKZlB6\r\nZ2k4N0VuRkdsVGZjVjVUMVRVRHdMQmxEa1kvMFpHS25NT3BmM0Q3aWUyQzRw\r\nUEZPSW1Pb2djTTVrcERETDdxeFRYWjFld1hWeWpCZE11MjlORzJDNk56V2VR\r\nVFVNVWppMDFFY0hrQzhvK1B0czhBTmlOT1ljanhFZXloRXl6SktnRWl6YmxZ\r\nek1NS3pkck9FVDZRdXFXbzNDODNLKzUrNWRzakRuMW9vS0dSd2ozSHZnc1lj\r\nRnJRbDlOb2pnUUZqb29id3NpRS83QStPSmhMcEJjeS9uU1Znbm9KYU1mck8r\r\nSnNudWtaUHp0Ym50THZPbDU2K1ZyYTBOOG41TkFZaGFTYXlQaXYvYXloalZn\r\namZYZDF0ak1WVE9pRGtuVU93aXpadUoxWTNRSDk0dlV0QmdwMFdCcEJTcy94\r\nTXlUczhDQXdFQUFhT0IyRENCMVRBTUJnTlZIUk1CQWY4RUFqQUFNQjBHQTFV\r\nZERnUVdCQlJRTzRXcE01Zld3eGliNDlXVHVKa2ZZRGJ4T0RDQmxRWURWUjBq\r\nQklHTk1JR0tnQlJRTzRXcE01Zld3eGliNDlXVHVKa2ZZRGJ4T0tGY3BGb3dX\r\nREVMTUFrR0ExVUVCaE1DVlZNeEVUQVBCZ05WQkFvTUNGTjFZbk53WVdObE1S\r\nVXdFd1lEVlFRTERBeFBibVZNYjJkcGJpQkpaRkF4SHpBZEJnTlZCQU1NRms5\r\ndVpVeHZaMmx1SUVGalkyOTFiblFnTkRJek5EbUNGQlNiRkl6ek93SmxyemJS\r\nTDFDMGg1VTB6SWkwTUE0R0ExVWREd0VCL3dRRUF3SUhnREFOQmdrcWhraUc5\r\ndzBCQVFVRkFBT0NBUUVBQ2REQUFvYVpGQ0VZNXBtZndiS3VLclh0TzVpRThs\r\nV3RpQ1BqQ1pFVXVUNmJYUk5jcXJkbnVWL0VBZlg5V1FvWGphbFBpMGVNNzh6\r\nS21idlJHU1RVSHdXdzQ5UkhqRmZlSlVLdkhOZU5uRmdUWERqRVBOaE12aDY5\r\na0htNDUzbEZSbUIra2s2eWp0WFJaYVFFd1M4VXVvMk90K2tyZ05ibDZvVEJa\r\nSjBBSEgxTXRaRUNEbG9tczFLbTd6c0s4d0FpNWk4VFZJS2tWcjViMlZsaHJM\r\nZ0ZNdnpaNVZpQXhJTUdCNnc0N3lZNFFHUUIvNVE4eWE5aEJzOXZrbit3dWJB\r\nK3lyNGoxNEpYWjdibFZLRFNUWXZhNjVFYStQcUh5cnArV25tbmJ3Mk9iUzdp\r\nV2V4aVR5MWpEM0cwUjJhdkRCRmpNOEZqNURiZnVmc0UxYjBVMTBSVHRnPT08\r\nL2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5m\r\nbz48L2RzOlNpZ25hdHVyZT48c2FtbDpTdWJqZWN0PjxzYW1sOk5hbWVJRCBG\r\nb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9y\r\nbWF0OnRyYW5zaWVudCI+cGxvZXJAc3Vic3BhY2Vzdy5jb208L3NhbWw6TmFt\r\nZUlEPjxzYW1sOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2Fz\r\naXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48c2FtbDpTdWJqZWN0\r\nQ29uZmlybWF0aW9uRGF0YSBOb3RPbk9yQWZ0ZXI9IjIwMTQtMDUtMjhUMDA6\r\nMTk6MDhaIiBSZWNpcGllbnQ9IntyZWNpcGllbnR9IiBJblJlc3BvbnNlVG89\r\nIl9hNmZjNDZiZTg0ZTFlM2NmM2M1MCIvPjwvc2FtbDpTdWJqZWN0Q29uZmly\r\nbWF0aW9uPjwvc2FtbDpTdWJqZWN0PjxzYW1sOkNvbmRpdGlvbnMgTm90QmVm\r\nb3JlPSIyMDE0LTA1LTI4VDAwOjEzOjA4WiIgTm90T25PckFmdGVyPSIyMDE0\r\nLTA1LTI4VDAwOjE5OjA4WiI+PHNhbWw6QXVkaWVuY2VSZXN0cmljdGlvbj48\r\nc2FtbDpBdWRpZW5jZT57YXVkaWVuY2V9PC9zYW1sOkF1ZGllbmNlPjwvc2Ft\r\nbDpBdWRpZW5jZVJlc3RyaWN0aW9uPjwvc2FtbDpDb25kaXRpb25zPjxzYW1s\r\nOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxNC0wNS0yOFQwMDox\r\nNjowN1oiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjIwMTQtMDUtMjlUMDA6MTY6\r\nMDhaIiBTZXNzaW9uSW5kZXg9Il8zMGE0YWY1MC1jODJiLTAxMzEtZjhiNS03\r\nODJiY2I1NmZjYWEiPjxzYW1sOkF1dGhuQ29udGV4dD48c2FtbDpBdXRobkNv\r\nbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6\r\nY2xhc3NlczpQYXNzd29yZFByb3RlY3RlZFRyYW5zcG9ydDwvc2FtbDpBdXRo\r\nbkNvbnRleHRDbGFzc1JlZj48L3NhbWw6QXV0aG5Db250ZXh0Pjwvc2FtbDpB\r\ndXRoblN0YXRlbWVudD48L3NhbWw6QXNzZXJ0aW9uPjwvc2FtbHA6UmVzcG9u\r\nc2U+Cgo=\r\n' }, config: { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', cert: TEST_CERT, }, expectedStatusCode: 200, expectedNameIDStartsWith: 'ploer', mockDate: '2014-05-28T00:16:08Z' }, { name: 'Testshib -- valid encrypted response should succeed', samlResponse: { SAMLResponse: 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOlJlc3BvbnNlIHhtbG5zOnNhbWwycD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBEZXN0aW5hdGlvbj0iaHR0cDovL2xvY2FsaG9zdC9icm93c2VyU2FtbExvZ2luIiBJRD0iXzdmOWU5NWM3MTE2NTRhYTQxYjMyNmY4Yjg0N2Y3YTEzIiBJblJlc3BvbnNlVG89Il8zMTM4ZDY3NWQ2ZWQ0MTZkNDNkNiIgSXNzdWVJbnN0YW50PSIyMDE0LTA2LTAyVDE3OjQ4OjU2LjgyMFoiIFZlcnNpb249IjIuMCI+PHNhbWwyOklzc3VlciB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDplbnRpdHkiPmh0dHBzOi8vaWRwLnRlc3RzaGliLm9yZy9pZHAvc2hpYmJvbGV0aDwvc2FtbDI6SXNzdWVyPjxzYW1sMnA6U3RhdHVzPjxzYW1sMnA6U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIi8+PC9zYW1sMnA6U3RhdHVzPjxzYW1sMjpFbmNyeXB0ZWRBc3NlcnRpb24geG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPjx4ZW5jOkVuY3J5cHRlZERhdGEgeG1sbnM6eGVuYz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjIiBJZD0iX2ZiYjE0NzQzNTEwYTYyOTJmODc1MGVmZGUzOWJhNzI2IiBUeXBlPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNFbGVtZW50Ij48eGVuYzpFbmNyeXB0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjYWVzMTI4LWNiYyIgeG1sbnM6eGVuYz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjIi8+PGRzOktleUluZm8geG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjx4ZW5jOkVuY3J5cHRlZEtleSBJZD0iXzQ0YTEwOTk0MDVkYzgxMDJlYTFmZmM3Zjk0YzJhZjkyIiB4bWxuczp4ZW5jPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyMiPjx4ZW5jOkVuY3J5cHRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNyc2Etb2FlcC1tZ2YxcCIgeG1sbnM6eGVuYz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjIj48ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3NoYTEiIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIi8+PC94ZW5jOkVuY3J5cHRpb25NZXRob2Q+PGRzOktleUluZm8+PGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU+TUlJRXNEQ0NBcGlnQXdJQkFnSUJBREFOQmdrcWhraUc5dzBCQVFVRkFEQVRNUkV3RHdZRFZRUURFd2d4TUM0d0xqRXVOREFlRncweApOREExTURnd01EVTBNVGxhRncweE5EQTFNRGd3TURVME1UbGFNQk14RVRBUEJnTlZCQU1UQ0RFd0xqQXVNUzQwTUlJQ0lqQU5CZ2txCmhraUc5dzBCQVFFRkFBT0NBZzhBTUlJQ0NnS0NBZ0VBNWhxamFyb0pwQithUjhGTUU3aFE5bk1WMGg3TXBLdG1nRkxjSzN2d1A2N2YKZUFLK3hkdDE3aThSeVVoeGlsOUZDRlI1SzA4V2p3bzNOaUhacUhxRUtpdHcrSUpTbmRqTFNzb05nS0VJYWlGU3VnMmVWMW9ZRWx6MAo2REJYVHhjOGlxL0xhem5kcVRVb201MU9kZTl5STlBR2E4OGNETTVpT3FxOW1odUd1dnd1THRveVU3OExkK3MxRWE2TWdmN0w4TTdmClpWTzdOY3UrRmdJekk2R3QwMzVvaFlDTEJtT29NN28wdWo3RGNNRXZLT01Geml3RjQwd1lteXAzaENMbHEzcXdrTTlwVFZKbHR1ejAKQnQxdnFEZHJxM2tUaGVBOUpITWF5UnozSS9CWnhBVjNpUmQ0aHpMS1RrZWdEOFRvVEdVMTBHbWUrWkFyMXcvZXJjNWhWck0wL1hCbQpIUWxuSTVkMzFHVS9tZklrbTBYUFRHUlNwUHk3RStkVXZqOWRqdm0vVnFEZG9qZjN1dXdpckdlTE1SbE85UC9sQ2VyVGt0VzNnMjdTClY4Z24zRVRtMk1tN3JrTnFmMjRLSnBEdjB0S0Rvc2diZGFIcjJJRVlENFJwcXlTcDhrZDI1Qmh6dXNocUtSa1M4WHU1dDdIQWxWU0gKd2lGaHVMcXJyNGRVZmtCOGtaZU0veWNmWkxDbjdvTlVERmRnakdZU1ZNcGFrTDk3c0M5c2xBVzQvOFV0WFhaeExxY3lxL1l4ZHBDeQpzUFlQMWhzQXArVmdQQzdHSTZDeWlOb2pLUE9wdE1xTFpSWW5WaUt4bE9pV0JKQnpVQlJVVnVhYzhMWHJNaUR3OGJ0V0dhMUdoNXZUCmh1RlVLc3ZtUm9ldWs3ZXlYRU45SjdqNitmVFlqbnNDQXdFQUFhTVBNQTB3Q3dZRFZSMFBCQVFEQWdUd01BMEdDU3FHU0liM0RRRUIKQlFVQUE0SUNBUURBUEZVbzBQZ2E3dkI0SWp5OXUzcXBXTFFTQ2Q0eGZ3OGw5MmlxM0pxTFZYQng4R2Y5WFZ5Nkd6YlhXSWU2cG1RSQp6bW9tL0NXUXZoNm83a2MwRjR5NGZ0c1dmcW5xM2swK0hjWDRIZXUxUE4ySFNuVVVQTnNrNUFkZ2dkMzEyOU1ISWRmYUtiOGJTdUxKCnZTTWVNYXljcm1zYitnRUY2SkZQOGtHV09QNHhRWWpBVk9EY0ZiT3lBZkV1VkFodWp3MGJxbExIVCtFbDR2bGZCcnRkVStNWnp0SXEKUWtHRFc3Y21tODZaR2lCci9nYTk3QkNuT0NyZ1pYbHJnbWlhOFNtRjdSZmE0OC9Yemg3YkRtUGZnbUhnbEw1SnhocFJYMklvUFk1WApJdG1SOElhWUtoT0JPck8vcWVyY0o2WjNyUTZmSXJzOEhyWWdlVE8vdUU5d3c2V1JXQ1dEYUNSNG9XRFZ3akt6R2ZQMW9KdEFJUStVCk5qT2RkSDVvdERhd1hKUmxRV3ByNzJxVDcrV09LL3l6SmhOMHhtWERrbXQ1cHNNWS9DRG40a1hNTTB4YVJwZllPbjVTYzFvZWxRK2gKSW04L3JIVksvMGtyaENET25pcWorTC9uZTJTb3lvWFlnUzZvME5sa05odFRIbWpqb3NFN0hWNkpmQVVncTJEOWRxMDBKTzk2N0kzUAowVkY2RjhsY2RhcTB0b3ZKaEtXUmpycmlnWWQ3NTYvM2FUMkI4M0pXQTFSQTluaVhtclhmbkFQWnJOQ2ZXdmorWDJhbFVOL2l6ZElxClJ0czBVcFdUb1ZVcjBveldnbWJtcDVaT0dZT1FoK2xOY0FwM1Y5bE9yZGJaVlNJVE00N1JZR0JaYVpOREEyUGJEekMxM01TL0VqVEUKdlNrb253dGxDZz09PC9kczpYNTA5Q2VydGlmaWNhdGU+PC9kczpYNTA5RGF0YT48L2RzOktleUluZm8+PHhlbmM6Q2lwaGVyRGF0YSB4bWxuczp4ZW5jPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyMiPjx4ZW5jOkNpcGhlclZhbHVlPlFPVExoZmlOQ1NoNkduNWRQWmQ1QjB3SEJFUE1nSGxpV3h6TEp2eDlRTWxjelNXdWpnaUp3d2x3N2M4UHZTTUtNZXUxaDhhbTd0ZEUwcnAyd1JpSUJjenpHTlhUbm5xaFM1NzFzMFBLb2hRN0h4ZVRXZ0YxSTJidFcyWTBzSUJsNlYvanV4blBVQjF3SUhQcXdMYVlvdkN6enlWeWVrQnlZamI2WUp1eENPR0xGL3U5MTA1L1NjSXQxd1hja0NrTUlOcWY0dUdaT0FNOGZKQTFzQW9ldzZDcnJ1UG5OakVDWmNhcVNBZjZFUC94MGIwaXUvelZRT09ZMHRZMVRRQmpMRDFROVFoS282TWhCL2dYTS9waW54SnUzeFFxQTVIWEtzVGdWSml3SVlCQldwcHFzb1ZWUWRGUXErYlkyOVpHWDlzTSswc2tnbGJWQm50czhDQnFNdHRISkxTNTRNRnJ4aTJ0Y0x1OHVzek5rNGF6ajVOdmxZMlFmaTJTTGdvbDNaTS9DNGIwRERGS0xXc2Y4K1lkaEZoNnlPb1lkN2NmZ3hkZTlqK0YrVHI2U3pzeXlybjczTnVPd0hJWHV2N2ExZHduS3pIM29oV2ZBSjN1a3JTbWZqRWNrRURkNmkxQWRiajBYZUhYMENsZmlNK0IrRzl3aENhV0VIeFRiL3RjeHVXMTdJY3B4cTJIakZCUmM0bkVIaFRLOVRwcHJKOFFPYkJTZ2puZWxINjN6MmxSSVFWc3lYUDZmV2Q4Z3FhNG1kQ3VaUGs3YWppdDU2dlBxclBZUk1yRzU1N0VaUjkyVm42ZWZya2dDbGtoUnE0VmpPbE1GTWZYNkNKVXBzSW5HVHlISnRqdFgvR1U1NWRib1dqVEt0bmRxeEMyNTZLbTJlM3NWT2ZUOUpzPTwveGVuYzpDaXBoZXJWYWx1ZT48L3hlbmM6Q2lwaGVyRGF0YT48L3hlbmM6RW5jcnlwdGVkS2V5PjwvZHM6S2V5SW5mbz48eGVuYzpDaXBoZXJEYXRhIHhtbG5zOnhlbmM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jIyI+PHhlbmM6Q2lwaGVyVmFsdWU+dytwQjNXTlcxcUV1YmhDQ0tPUmtkc1ZNYTUzOVB5czJMSmR1dGlzN1RuMlhwdm5xREdZUG9YblZqSCtTdTQrTVRQdi9nZ0FnUlJnUW84NE1SUVJHZUs2OE1pcDhMLzRhQ3Y2ZmZUM0czVEpPdGc5Y3BhQVI4RkpyMXp6NFZhbi9UWGtScmpVRWRIUVlJTmhkR3ZUYVdSWUx3dDA2SExRckVoNlgxekJLbHFHanNEenk3Zm5LT1E5SEJqY01INnNGSTNENVZnOUtoc085QmFTNG9aL1J1LytUdC84SWg2VUhDcURTM0VUcnVqTUdCdDNRMFhaMWxCOHpWSUVIVXhoemlhZkF4aGlzZ1B3QWxYcTR6T0hteSt6YnJxekFQVjhhQ3JBT2RtbkZwYlA1VUV4MnRNcWJ5aU9jZVJ0R3doaUV5R3ozT1pyM0dtMXR3ZTJtNW05S05OZmt4eW56N0hVQndqS3hkcTNQTmFiMFNhOWVmNWRESHhiNHdFVDVJYUtSRGF6TDVlQWVkUnljL1FlbG1aNFhUQWljVGtySGRpR1VxeUhQdm9Jd2VmU3hhK3pyQTNoRjl1ODlLMmdQQTlGTHljWUJMc3AzVU5HMC90RkxkRnFhK01CVGNRZTRYSWJodlJsTVI1TU1zUHNPbm9Fclp4ckVXNjdvUzBpakJsaUlrY2VCcE1HaWJ6VUZtUDJsRFcxeDRjTEprTFlxWmVua1hSVURvbmVicXVjdXNIdFNOenNTK0g2MU8rNTI3NFhOM3FvRzZpdEZLVEUybjVQRTU0M0hMOG5Ib1dmWjdBTG1VeUdZSzAxTnVjWjF0L3B5SytCNkFhT3RSY1lvMWlwcTVWNzU5cmNUTGFVdFoxeVdCNVlZSVdtMUkvNGt4WEw0bGpPcng5V1BiMUJGTnJVZ0FBQTV5Qzd1T2s1MXh4S1RiaGZoakpra3AwcEU5WWF3cTdBY2lrb2VadDRJcDFpQ0JoZjZCdjB6RCs3c0tyeE5XQUxzNXVYOU40ZDgxekZBamU0eGlHMDFZUzBjOWtEWk5zU1E3ZDI2alE5ait0YVBYa2Z6aFVRZithdnczMXVDbk0vNFBHckc1UGlPeFhrVmcrUnVrZGVaUjU1VEEzZXBmamhSbEM1UmFnWGlGeURLOEcrK0dDSEJvVUtBN0pNcmtacmlZczdDNE9SNVdDQVNrOUhTTEIrc0VicnJTcnF1aGpKZUNTR0ZyQmpGckw3OGx3QnI2QWxhN2Z6bzhmNnNmL25nSUNxNDNmL1FzYXpwWHpyZzlYN3NTWTBONDJJaUtIN2FiSzhSTXpvbmpETzhFb1p1U0tLT00vN3VVSGxMalVXbjh1V0dBa21zV01qN2lUa3hQRkxRNVFKM3VzZHl6U1FndUZRMERVVmF3ZmJlb2NtMk90cjNTdC8wT3VVOHBzdHZodHdTWnVJc2s2NFk5MGFGZ01kRHcvdWJNS3lzQUh0aXowdUhGenpDMW9iTmFaY3BLS0tVUml5ZkYvNkY0dmhNbDErRC9ubWpUQTdRVm9yQURDS0lpUnFlNXRzdG1tcHJIbWRibFpmaGI5cGcxcDJBMVZPTStzRldoRG9QWXk4dWRaKzBQSGRmTkh6bDNLVHNIVjhUSmR4bTBXTTJiWURsYi9TSTBsZVBRUytSWUlsODJ0V2ZqUzIwT2VuZ1RoZjdHWUFLUGJUaUtnWHdJazMzbE5pa2cxSWdRMGhPcnFlZUV1MHBvb05NV1pOMlJBVkZpY1hmUkRhQ21lOFFFWUdWY0ZaOTFGWkY5MWRPZ3Z1cXY5NHVCcUlsUWtVWWl0SUh2cEFWc2RuU1VjQk4xN3JPMWFQVUcvemlUNFc5K1RsWFVTMmxjcXRKR2xwTjFCejd4Wm5GOXZBQjRDNy9xRC9XcFhZUlJUQ2VuUTJZbStMeHcxNXJMQThadURaTU1qdWxyMXErN016K0h0dXBtalV1eVJJRjNMZmtRVkFMa1YwUTl1bGw3djgyOVRHN2ZhSE00ZjJOR20xVHdXTkw0aXVJVHBsTy9LTHJBR08ydHRQdE1rZ1RXdzV5WWVTd0pSQ1B4SFhTa0pVQ01EblcxU05KZHZSNUJ6RXNZakpTQ0Q0dkpqTVJTM015ZHJldzBzdFNHZkwzajdScjgvUlVXbDlXTWlQOEFyU1d4S3JFRCtBNzJua3hlNnFtRFZtNm91YWpiSk9rYVY4cDZMNW1XWUZ3MnBobVpQRElvTndCUzY3K1lGc28yOXJTL1dOZUJRQ1RTVWR1VW9tbk4yRFNib0x5eTVzM0o3M2xyNXBrZktQODgvL2dDQUxQbG0zQ1E3VktiK0RIUDd0VUxpaFVkTmJYV29YL2IzZXk0QzdDRmhtclhYRTViQ25sWnQ2TFlIZlhNSjJvRmxDOHJyOTBSY0VZWjlnNjVRdktOVDFabVJVR3JveVBYbjdHTThhU1N5RGZLeDhCQ0V1d3FYL1VzN2tWWkxDczhyMW1xQUl1eTlMb09oVlIrMEJ4TDZhTTRLMEpvLzhIUy9mNE80c1BRd2JGMWp4UU1ZYVlabHBLdzBzL0o4UGtLSnBBUzlyM1RtajZFVlNqb3dscmtmT1hpUVhaWkY3dXVwdlNvOUwrVnVXZ1Vuckg4dXpmMUhlQVhUMXlYRDAyT0dTR2JyUnF2alJZWFhTVFFpTnZxQXo3UzBKOHJSNTE5WUFiQk5KdzlwUExXRjVMZWZ2VVc0NnpYcDVZdE9LTWlENnk5dmJMaTlJbHRzM0MydUxJY0ZIbXRRMmZ1RlBwbzIzeTI5YXV4U2IxdXQ2Si9BK2tyTFRKWWFjNEczS3B3ZVFnVEs2dXBHeGdZM2p3c2FzTjMyWGs3eC9rUzZsVThBM0FjNElmQTh3VlMyVFF4S0FaZnNJNHFrZVJqNVkvUWlkTmM0TTlWWUZCeXo1aHNJdmxObjFtMy9oV1dvdDRDVzhlNzFENGN4UnUvQTJjVGwwSHBybWZ2cVFmTVhmMU5kZ0Fya0kwSVIydkMwUWZCYm9FS0tDYno3RThJTWJJbjdWK1BmdGdoOG4zOXMvU2F5c21TMXMzdzRHdFFvZHdRMTdmK2gyRVR0RVZOMkh2VWZMRENoQy82dGVhaU9hd3dJWXFvUGlaczlOZDFrZUZ3YlFOSGpkbUE4ZW43UHYzdXhIRTFLcmduUXNqci9yZ3c1ZEdwNjdmSFpkcUpuZHgyVVNPV2tnZmdLRHZ0SlNXSWZtT2I3WnluUGpxZ3ZLYzV5RWFQUXQ2TUNXVXF0WEEvVTJ5WG9wWGhDYVN3cXFIZlYzVGRrb3JkcURucW9jYTJKdDRGaUdTQWhEclY0VVNSblVvUWoxblArS1F3RktDVDcvME5Rb3Q0VWhWWndVNlAxUFRUSExBNkEva1JoMkFsaGZZMTlzOUh0SVl0SHpMTm9nbWFkT3pxR3NCNHFSQko2blZ2N3lXVER2ejhtVVdMTjNmVlBzdnUxZS9YYTlKUWQzK3pKUXRVSXhQWjBPaW9jbWh2M0U1TzFRSzNodVgvdTdWaXAwbFBEcHNvMkRmTDNqNU50blBhQWt4TUEzVDN2ek56WFcyV3ZyeE5HYjkvRDdESEpuZ3NqdUF4OWw4VTl1RHJPNzVmaDJiREc3RzhFUUNBRktQMkJjZWxybkREY1B3d0wwQS9wSW1zaEdwUlFzMzgzeERDZGxVa0toTUJnbDI1cXJmWGJCQVJOQmFtV0hFNGZQem1iYk9MYWtRUVg3VFJJRFNWTGNiTTQrdU1idlROL0R2TUFXZlA2ZW9YU1pHWGQxME9ET2FPVzZJVzNITG9seUg4QzU0cUwxN2dVeFJRMElNdjNGc2tHYmZ5enBvWi9GRmdBa2I2Qjg4eW9EOW5SbTB2czJmYlRrd1ZLNDNENE5iN1JuOHZtL1lCZGkwVytXTUdMdU9lb1d5RGl6NVk2YnZNR3kySjI5V2pwaFgwaGphWGVySlVKdFpRT0tLclAybUdCWjVNSHlmMUtFSVdraFdtemlOYTZXbmFzSU8xM2o2TkRqYnptbkF1QTU1VzBFQlhVMHRYTE1pckJvd29iR3lzVXZMOVBvTTV0TDBuOUVYTGtwbHhCS0gxVmZtNG1MR2M2cGNVVU5sK0dWc3daaHdZVVNtV3hNQU10M25YemkrSlFWOUIwRGhCU3gweGZ2bEZkSmUvSkcrTmM1ZmprcTlSbkFWMHNweXlwTnZacnZ4NXZ3T3d3Q3hCc0VNSWV3RDlNOHQzM2VGRnRYRnRBeDF2Zlo0SzlQV2VRblV0Rm9yR05ZYjF5cVFnbHIxMGxGeVpXWWdpMHJSUXlqTHFmdWxSODRmTkpUYjNabnNIeWNuK1I3WXBsM3k2WWlvRUF1bThtYlRmRVZCNUVoTXptaVB1Tjc1V2NxY1JTZDdlYnprY0JBL2JYNGZYMEVRWSs5cE41dUt6WE1USzU0OTZPM09KV2R4ZXllQXQrN0cwZVNkREo4OXEvbGp6T1g5OVFZU01zQ0NISWwrdElYdG9aMjFqb2dZVnEzc1RtUGhscThHVHZmeElPSTI2WnM3cm1FOWJFTGs2U1NYeFFoNy9KSUEyZXVSY0RUWDlSM1FXalMrUFRnTUJObEZXYTlEOERycVJPVWVyT0V6eFMwYS9oTXJyUHZub1o3US9mTDgzQ1JhanM4RTBwYndGZnNuSVF6MVoxNWlXeklBVlFFRnBOZXZ3eVkzSmlYSndkRTM1dVIzbVRYdXRkNzRrLzNuTXYrQmszVjZYRnpkMVp5dDg2Nkd2Vmd1alMrSWFqNllRNmZGckc0NW1lekU3d3VJWDBWMlZVU1Rjam9tcndaNThXclhvM2M1MHdRNHNlV0tkNnV2WCt5dlNBWnlxclhTbkdhWDNZUHlBemVhMFFWa2JLWGhCWHVLYUpGMzNMS1RFWGt6eVJvOThLRko2Z1dPSExWQm5mRTdrWlFKUEkzNEpTSnZzZTExbmlmYkMzZ1lpK3MzSlVSOGQwSmI1c1JkcU5Fc1l2d1lIM0xQcGRYRkxOUXBNM2ViYm1UUGdKR2J5bFJTUDFWelJVRURsbXgwbjRVUGs5SGFZNksvZkZWSEt0ek0vVnpJUm5IK1VRRnFXN1RSMkxFdXI5dmNKcytGaGFieG8xUHc3VlV0R1lZVkJMMjVZbC9aQmR2THFBY3hLN0xVTFk4Yk80V2lCKzcwMlUxZERQRENaQWNYWnlid0duNDQxRE1rcHJrck5DOHVxbkFQRHA0ekNMTnBENWM4NXg2Q2pDMDlJei9TYnorbkxLcXgyRnY3MVBCcmh6RXlvbHNVNWpEZVVtSGcrTFplVzk0dlVNQ2lZalY5b09ma0ZIa2RHbk10NGl6dmJPd3FETG5JSFhCWU9MYUNuNmUwd005Ums4NjhtRWpoYXRBUXRvRm1lKzMxL0M2clJ1cW1NbSszNVNKY0ROejZuWEFVWWVVOFZjVkorNU5IWE56MUF1UXh3cWo2VlNsMHRmSmZUaDk0V1gxNHlzSXlBZnlTeTlDTXNHMW9aNDZ2djJkNEZETjFyMWwvN3hEYWtBYmZLUGNPK0F3U0dGWkxCQ09DaFR4dkVlQTdvWlhJVFRLTVdPUlJZVXVkb3JOQ2FOKy9IMktzcHo4eTMzUm54OHJaTUd2cnlPUm5nME5LSnBrT1oyOGlDczVGQmJPa2UvZWROeVFibm90b3hCUjJIbHcydVY0SWRsd1c1NVZkcHNtaWJ5alArS0NaSFNGOWV2WTFHci9VdDVYL0l1S21NbTBiWGQ2UFp0VjcyWWxkbDg3NHB2YSt3Y0NsOTBwcTRIU2x1T0JFQm9haUt1cXQyUCtHY1BZa2tRSitEUVBYdktYYlFWanZWbCtXS3FPL1VZbmRTMlR4b3dINk5ZMWNuVE5INGtWR3RmaHNSc3FCQzlSRjRsSGxRK2w4UnZaTmZMcHliWjJ0T3RwSmZaUXQyNTNnZE4zZGdzUEsxVTVISEZKd2RwYzA2QlY4YTNueWZvNWh4aEorOXVaTisxdDdGYUtpdng5QWhscE8xTytMcGIxenovM1VucVBRR3FwbEJVemtINko0VmVSTFdHNDd0SkVZNVRZbmxrZHpvTGF3dUdjM3ZwMWhZUjZZVEg0Y0I5bGlsMUs5cHgvUFI5UGRhM2R4T25zelZ5ZG13RWw3QjZHb3VrK3hXMWF5NG1iT0hDa3JwdEVoa3NEcjY4WWE3b05GUXVZMnNEUmdla0VidHo2RFZFako1b0hkUmVvSFZMRm1TM3pSZ3lwNFJRZ3YxMG9wUWNpTU1hNER1OGh4dVpVN3JYMVNGYm5uQ2owaWZoZDUyd2JyOVEyWisyYnNKaTEvczZkV05JS3ZDaDhxUE9YU21IL21YMFpETkFDbDV4K0phTTNOTGl4dEFlZFVxcjV6dDlza0t4Qzd5cURUbVhMRkIzRjJNRm15UzBtMFVRcDdDb2daUVI0MjI4TlR5WFpSK3FYZExhMUlaU1owOC9BOGUwMzRJZ0FzS0YvQXhJdFNuNllZZXhHOXFYeU5aU2x2OGpPS3FiWGdidWZnZHorVjY2OHVGMnpzRk5RY2pBUUxydGxqWnRFR0g4WEIwMFozT3ptb1ZmcWFqWFhMSlN6UjcwSFJHUWpYK2d6SFVBUlF3Z2ZxUVFtVWcwZmtBMStyNmZPWTVYMDVRdkxNaFprWmJwN0RuUmczQUZKMU9hYnRPYndJek9WRmhsN0p2SzZlTk9kK0NTNkttZUZSS3BwSExCNSt4Z3NpNGRSQ1VYL3VGZkVFZ2FxNm0xems5OXprSWpTZDdRWFhXQUpIWE52K1NuUjcwTzVkdkRTam1ZTSt2MnVVOGZNMlBiZzU1OWJ1LzIvYW5VQkxEMWJxZG9pTC9GSHFlb1B2am1zRktkcFdnRjFHRGVkam9sVmRzUWNTeUxoYlN0eXUzSWE5RU1OK0h6V3ZmVXd4M1hSOGQxMHpSS2lBL1J0Qjc1cUVFZm5UQTREa1grVUxCVGd1WkxkWklJYVVFTG5XN1UwZldnVEFuaEdqTVp1Tmdkdk5qb1BGRmRlcmxmRFplazM0aDVGQUJvM2srTlJuUk9USmhZaUhHOHE2MDF0NEVsaklCVnoyYkw4UW9vL055ejE4VFF5NkRGMUVhK08rVXkwUlhlMk51QXZBekpUVlAwU3prMGE4WTU3d0xZVElPdW55UUtKY3JxemVaSkUyZVFKNVM4bUtlR25ZOE5MRVFaNlpXZS9CK0UvOU9ORVFCSGhPUzVkMUtVV2NvakV4SE53b2p4VUF2cTZYOThmM3orRzYrakorcEl1aFNlaEdjcFFOVFVxYjIvSjdsbU9vSHF2dy9lbG9MRk96b3pya21wQURUVERDV1FsMCs0QllkbmRPN0FOZFVhRlBYMmtlUk1YaUQzZ3lxWDlzcmdTVHBzSlRuTHZWR2I0KzhrT1kzcSt5aUd0T3ZxMFpCZmZ5aDcyd3E2alVuNjZPR0hXS2oxM3RNM29GcnR3WmZXK3FnMDhCSGg1amlFVjFBbUhUSm1CaHUvSWtZMWl1YnpCZm0xdm4xMGhSYllnb2N6UkFNV3dkVWhIWnBmMUdjVUV2NUQ5djMrL1g5SjUxRWFwVGdaQlhtaUZqdUVtQ3lQK3hXWmRnTTFLRlZpTWhObWhiYjJwNmZSaEt3d2VwUGhrR1VKbnR1aTNuZDh3SFNlSVpQR3d4bDNpcFBJSmMzLzR6UTdmMk9tTFByNTNoMzRqRGhrTUhCcW1acURCV3VQelZQdFd3cEZCb01yZWpKTThCUGcxUmZtUEJxUEw2NnFBWFJJQnRnTmdIaHhLRm00dTVMd1o1Y1J0UGZkVXUrcTlvZ215WDNnU00zSDVYeXo3K0lSaWIySGErRmpHMmNGU2hvbXJTS0RaZFpGaEJOYVdnd21rU0Z1TDlpdTF5QmlLZ1p1aERCUkZMNVZOb08wd1hLWGJBeC90OG9hdElyTjRHRDlWYk4ycWdwMFBvRUw5dXVyUDZFU2prcTFJa3Q5UGtBOVNrMkRhMTZFdEJsM0ovRG9DSUczdDNvbFRjZ2RMakJ0N0R6S0EyWVlmMTRiZGI1ZStVOHBkbzMxemVWbkZTUXBTdmZUVU5KNHVuTlVkbEtIcFoxb1BDQnAyQy9wTVppMkJxVk1QdGNDeWZsb1Z5UlZFQ0RsZlBvLytQMzYvTy9aUEJKZ3pqcWdxOXdRUnliaW9FKzE4RDh0UXM3RGNaYnZ1VGlSbFlCNUkrRkd6YTk4QUZ1YTlCZklYR2d5b0pPNXNVVnVVYWh1VEYvYjZWc2ZSNmlRVlFXWVNvWlNTRnlMaFFTQncvM0FXUDRld0xOd0ZSZFFqUWM0NWpkdkdibmliY20ySVBVQjdzN0xhb1UvV2l2MWY0ZEoyMUlpSFlKQU1jeGo1cW9mNVNxNUdCVElDV0c3TVA4SHFFOHFmcElIVUsybTZRRVBMenFWNEkyTjlMRUxZTWE5OWZubzcxaDc4cDJhd20wR2VWSmZUd3k4V2NkYTJuQXlhMEFwd20wUGhIdFJoeDBrRTlQTDM0VWd4NUEzR3gxbDdiZjkxa3BqeE9QT2NoSjREUGFaSER3MmIvYk9HcnNDcTBJZms4dkluM2JxcFk5U3VYbmZpOHpHenNTb05SanhHZWdKOVZiYkh6MFpCK0p4b2JzdldDK2Z2MEpSb2FQM2ZDSkZ1bGdsazdOVk5EK05hTEgvR1JqVDJTbCtjS3ByV0R5THlqK0UzcE1yY2ZLWFNKck0xZHIyaVl6RDBPb3BRVWpnR2IxOFIzczdKVXZ0QVBSOUp5MU1KcmlIbjNjV2xZSXZCWXRmQ3lXQ1pIdUc5NTF1c3dYMWt1WURYaGVDUmM1ek9Td2o3SDVWR295eWZSdzBMdnNVZmdhUXNhT2dibTZLTFJRcGtQZkl5ajdiMWE2M3RrQ0lOSTI5cHNyTUdVei8zT0JYbkNBR0d2Q3BxZkFwL3hHZzByaDdwMWVLaE93alUrN2NVbWlUS0lsUFR6TVBITWtJMytFTDlLc1JzV2J5OGoyWVdmUWNCUHAwNGQ2QzVNdHJYeCtFMWhoamNTSEE3RklpSkh2V0V6RVpxRkpXTDFCdHp1UFEwNlVZcVRDb3ZxTjlnZFFkZ2NUQ1lub2FpN2QvZ2M1alJ1TGowa2QwdjVxbHlyQzdsYjJ5eGVLQmFuamVxVXloQ1FXdGc4MmlZVWJOMkVhSVZiVXBRaUlOT0YxTTZ2TmFtZUFGL3I2QjZRSy94VUxEalMvWms4WExhMG82ekYySWh4VjExUTkrRUZ4d2h1MVVZZkltbkx5OU5MODJtRFNQTUZxS3FsT1NvQWRxcTU3cUxvZmpGMndwY3kyTTdvWGNrQ2tPaVp6T0U5QkMzeGNsVjhoRVB4T2JKQTNjSk96emc4UUl2RjNrSmxaNTJMcDlMSnQ5Q0g2ZThyZEM5clZNZ1BneDU5YWlLTm1iMkFsOXBaN0hpUWZWRUZ6QkM5SEhDVjRPZzVKZmt1VzY1UjM0QUI5SUt3WEFyTmNDTWFWajcyL2ZPbnRhdVNDa0NIZ3RKdVdDNlphcmFzaVpIYWc2NG1kOFVWbWtwRUJ2WE1OYTZJN3Rtdm1YL1lmUE0rR3Y2MzcvR1U1MmhGRTRIRVVsK2l3eWlJQ2JxSndHNDNQenRkcVpuWTRvYmNydVlJMGJKSFdSSzhhZ1Y1aTkxbGx2Qm14WDVtelB1Y3Aza0JJSkkyWDNFVEZ6SDlRam8xbktrYzhtY3FlSWtmZWl3ekpyL1ZmeEY4UXg2VmJWSjJhN1o2VEVNd2NiVDRJUVZjaUlyKzYxUEdlV0svT3F5bGdZODIzMTczNHhpSG4rcGFnWGpCc2lObHcxQm1ublhKeHZucTJWRGw5Z0h0czJqMy9mcjYrbEgvaDUvY25CK3czRElVQzlGTmI5UFZtb1B6dkdJZ2ZiV2puSDI3SFRZOFBjaDRpZkVHV0tRMG51a2s2TytpbW4yUTdkZC9LYnNYTW5IdXZETDRHNmxlVWZpTnFvMUQ2OGJJT0IyQ3dkeHVvbk5yenF6ZVBZb0VPdHZQSE9iRmhuVUlXaGJXUG84Skx3ZU80UFNIYjh4U3dOa1JVOVNZaHZ1bWwyZWZMWi9maFo3ZzdGb2lIeS90ak1sK3R6am9JL0tKNEh2YWdINTYySEg4VFlNYUtCekpzVjdJdkVEV2J2Um9HOU1FWnlBdlJ0amw5WmZUMjlTdkgvRk9zejgrQ0lzZUJWSlVpbitDK3pZZDhKTDNIMzdkSDNLVVZxN0xKYXBESEZrRmtSU09tNllHKzVicnAxTXV0a3FaSUpaMWxOd00xTW15L1pmSnFWMUl6SHdPWE0rVm5xa25WZVk5SytUNzNiRlRWOUhmR0VQMVduVEczNWxjbUoyUHZ1TmdhVTIyejNWUVdmalNndG1JMWthVUxtd3lHMytlcmF4Nk1yWFJsZFBXYXJlZi9BTFJGUURhOWdXSTQzT3czVFE2SXpFRkVsS0czaDdHdE5Ba1NFU003MCtsWnNjMURUYnNrMjdNRUlha25MdUhjMkJXYmYra213eUIxZEozVENmd1RMR0VQZFNBa3BCa0ZtaXphMVFVeVhib3lsQnpZcEpucFYxV0dWWDU0R1hjb0p1cnR2RzNwN2lPeTlBcEpZcUl6U1pMYVJIazhCRHpXdDJjekhsMWJaN1VZMGNtbUxQUzlBc05SYnJWdm9LY2htUVNUZTJMcG9rTWpaaXltVGp0TG1OM2wxRE5VNHgxQXhTT1FhTVptNHlvUm94YUY2ckNBUlI4MFdsbHRvY0ZDK0lYTVJHMzlBSklwUGlRRTNwQmVHNHcrWTBGVUFLTDZHUmtqL01YbnQ0ckw5M1BkRldTZjN6MjU4V3VsQjRIcmVoaHl3UEh2dk5NUUJQYUtVb3VKc3BRZmpKYWpnMmZUbDVDMGVxZVh6UEM0YXM5M25uczY0ME5kQk95T3dRTnpXbEdsL3FrekUwS203WXBjRk43UjM2YnRqczF2dWtoQ0p4Z2hqTk5QUHdvei9xWE9oNDVYN2h4djQ1eHA5M0h6TE1Eam81ZjNEWXVsSkRNVXhONitySmdGdDJwbTV1VklkSXVNdFQ5eTBqcXdJS0dEaDR6elQ0MDloVzFZY204ZTVjRkdKWjRNeWR3dHNOT0l1Q0J0d2NFdDUxdG9kVWRYVDBrcTJ1WmR4TGorNGhZYk52OXVhMEFYLy9JNTdydVZhTTdkdVZDZU9oR1BVWU1UQWgzSnk5UktXOUxUbG9vVDJQM1JRQXJ1SFNGajlzSFBhQ2RodXNFbnY1V1VNWWd2SVAybU9YRUdhbCtVeTh6M3FZRStyU0Q5N0tRUkUvOEJlRkM5b3pNUUlEVXhQOW0veXVFMUlKdHBrVzRNaHdtM3MvUzVpK3kyeG1pQ1JlT3d3ZVV6Y3dMcjBNR08raHhtSDM2anVMQU5ZdEVWZm80aHlUY1FSdU83MVRMOE1NbWhITEJnVi85ZGN0Qkx4WC9CRmxRQW9SNVh3UHhWYktNMENMNE13RnNwUE1SYno3NXRzajJVZDQ2TkxoRHVBRjZVVGpNdDVxclBYT1pMSUNNQVFsbGlUK1lMZzhMamdTYWdKdkFSamEwczlWUnVOaHJIRjVXMU1LY0haRThLQklWR0orYktjLzFLWGJFT3dmUHUrZUxmSS9QR0pScnZlL2NWbTBhUXRMZ1VFcmNwRUpUd1FhMWUrRE1aUHJQS0h5VU9WZ1FkMTBEbTNTMElrL2NNWGx3d3RUSDVFR2YvZXY3R1pOL3EwYWRyY1l3OHVhZXRTVENzOXlhdnpuMTQ4M1RsRUQ1WE82eWZHOE9MdDA3TjFDNmxMTElpajdVb0xrRUlKTGpGY2VCTWU3amhOK1BmN2M3MXVzYUVCMjgrdDRSOEsvbGV6bzc4MEYzNS9ZZklKeGErVHZxbGVxdGhGempzSnpYOHZHSXNlWHpQaU1acHpwbUlxVHhNbzhPTUtlcFlPN3hnRzZZakUvZGtvdFFhUTIwUTRiOWpPaVdYNW9KSDAzcGY3eW9Sc0ZyamE3ZTBFeU1haGNsRlR1TE5lc3dXNkgyTDVhTzlzU3hjUG50a2JNbXpJMFcva1g1eUNMdlQ5WGIrVFM2cUdCV3pSNGFQdzVNQVpuWGxFcStUYm5RWTkrOW9xSTZoclMyQ1VUaUNFMWIzVjBOQ2w2bW1RK2NzV0tRSllBdVM1cDdqRzRDelcyVFQ5QXpGczNteE1TTnk3cVUzQ21sdlhNcDB0UDdnNEovWE91UXdBWCtMNDlidmVxZ2VWRUs4VVFkNDZZS2lRVkdsUHluNGF2T0k0a0dXNjF6NjVJUVBOOVVPcjZFRnhPVXhJWnIyb0ZEdEdVUnFuSzNVZEt3Nzdtdjkxd1NkZGRESlIvTHRkN0c3Wlpmb2lHR3hHZ0lLYzNCQUxleHhUOE5aMGNReHVFL0ZTMlR4dWVzSEJ6Y3lSNXkvVGZOeHVGdlRENzFrZElEeEk4eXVsYzZoUXNjMktudnZXTmNSMEREU3FmeFhDUjJ4OGp1WmxBWkkxbXUzcDBNRTJiV0lpUXgzaEFwdmljSkorN0JoRGhZLzh4R2U0WEVrVXhEMnJ3NWFremRWSkdWSTdEQnAwazhHMEV2YWw2cmUvQnpjRlVFNFJhZW94T1U2bDVRRjNZYjY2NnpvTnEzNzhnTzd1cDY2TmoxZGdFZ1lwOVhJUVN2WEo3Uk9FcEFscUxMRC82NWdOWE5wYmlWNXZ1bG1iMC9nQ3ZqcThRZ2ozTU0xNjAzNUhFZGlTdEpoanMydFJKRGhJQ1lHR09PVWdpTmlmKzYyOWlSajBGWHdNcXhncE9nTytLalo0R24vQU5YSFhGK0U5TlVLVk95c0ZkWkpQUGNpYU1kVXEva2F5TzFNSVluTktRQWZWRHgrME5qMVN5S0Yxc3dLVmxxY3NsaUVzaXVRaS9nL1NFaU9Gam9UcEcxSFdxdkdTYXJpU2VubXc5eE9ZZy9uU0F0c0FrMlF4S0g5Sk91TUh1L0N5c3REUXdOMHV0ZmpjNHNUQnFXdkRONUY1a3JXa1J1eWxLRkQvK0M4MjBCd2R2d3VobU0wQlplZklmTlJmQzd3cHF6dlRUWE1Dc1I0anFaeElsSW9Tc2swWjhtcGN4bGF5ZGx4RWVhdXYrYytYZ2xRV05QVFhMcEEwWm5WaW5uUS8wQXNPcm9Lb2ZnaGphcENneTFCL0FrMnk3Z0NXV1RrRkp6ZmZWQzY5QnJnOEYrYzJJMkRKa3JkT056aGcyVFB1YzduM0dFZXJHdWIxMkZybFRMODdzM2UwNk45QUl6TFlGa3M0MmVEWnN1QUlwM0ZmSzU0MlkzT0U3dkR2eFd5UEhFd1ZuanNyWndZaGdBUXV4Tjc2cUVRTkh6bkl3TzQyRzQwRTRFYlRTRUFTbDAyR2VQMUZ0TEVsZ1hZUEJXSGFtNnZhd0t2M0lMTmNNZmRBdnJJOThFZmx6K3Vma0pRL29JZFdnYU90Ly9BeXpPRFE1Zm94ZzhCNE5IQ3F4MTVWQ1dTWk9EV0RkOFlnTzNBcUNDSlpzMGxzdTN1TGpWcjZ0Z0thND08L3hlbmM6Q2lwaGVyVmFsdWU+PC94ZW5jOkNpcGhlckRhdGE+PC94ZW5jOkVuY3J5cHRlZERhdGE+PC9zYW1sMjpFbmNyeXB0ZWRBc3NlcnRpb24+PC9zYW1sMnA6UmVzcG9uc2U+' }, config: { entryPoint: 'https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO', cert: 'MIIEDjCCAvagAwIBAgIBADANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzEVMBMGA1UECBMMUGVubnN5bHZhbmlhMRMwEQYDVQQHEwpQaXR0c2J1cmdoMREwDwYDVQQKEwhUZXN0U2hpYjEZMBcGA1UEAxMQaWRwLnRlc3RzaGliLm9yZzAeFw0wNjA4MzAyMTEyMjVaFw0xNjA4MjcyMTEyMjVaMGcxCzAJBgNVBAYTAlVTMRUwEwYDVQQIEwxQZW5uc3lsdmFuaWExEzARBgNVBAcTClBpdHRzYnVyZ2gxETAPBgNVBAoTCFRlc3RTaGliMRkwFwYDVQQDExBpZHAudGVzdHNoaWIub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArYkCGuTmJp9eAOSGHwRJo1SNatB5ZOKqDM9ysg7CyVTDClcpu93gSP10nH4gkCZOlnESNgttg0r+MqL8tfJC6ybddEFB3YBo8PZajKSe3OQ01Ow3yT4I+Wdg1tsTpSge9gEz7SrC07EkYmHuPtd71CHiUaCWDv+xVfUQX0aTNPFmDixzUjoYzbGDrtAyCqA8f9CN2txIfJnpHE6q6CmKcoLADS4UrNPlhHSzd614kR/JYiks0K4kbRqCQF0Dv0P5Di+rEfefC6glV8ysC8dB5/9nb0yh/ojRuJGmgMWHgWk6h0ihjihqiu4jACovUZ7vVOCgSE5Ipn7OIwqd93zp2wIDAQABo4HEMIHBMB0GA1UdDgQWBBSsBQ869nh83KqZr5jArr4/7b+QazCBkQYDVR0jBIGJMIGGgBSsBQ869nh83KqZr5jArr4/7b+Qa6FrpGkwZzELMAkGA1UEBhMCVVMxFTATBgNVBAgTDFBlbm5zeWx2YW5pYTETMBEGA1UEBxMKUGl0dHNidXJnaDERMA8GA1UEChMIVGVzdFNoaWIxGTAXBgNVBAMTEGlkcC50ZXN0c2hpYi5vcmeCAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAjR29PhrCbk8qLN5MFfSVk98t3CT9jHZoYxd8QMRLI4j7iYQxXiGJTT1FXs1nd4Rha9un+LqTfeMMYqISdDDI6tv8iNpkOAvZZUosVkUo93pv1T0RPz35hcHHYq2yee59HJOco2bFlcsH8JBXRSRrJ3Q7Eut+z9uo80JdGNJ4/SJy5UorZ8KazGj16lfJhOBXldgrhppQBb0Nq6HKHguqmwRfJ+WkxemZXzhediAjGeka8nz8JjwxpUjAiSWYKLtJhGEaTqCYxCCX2Dw+dOTqUzHOZ7WKv4JXPK5G/Uhr8K/qhmFT2nIQi538n6rVYLeWj8Bbnl+ev0peYzxFyF5sQA==', identifierFormat: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient', decryptionPvk: fs.readFileSync(__dirname + '/static/testshib encryption pvk.pem') }, expectedStatusCode: 200, mockDate: '2014-06-02T17:48:56.820Z' } ]; var server; function testForCheck(check) { return function (done) { var pp = new passport.Authenticator(); var app = express(); app.use(bodyParser.urlencoded({extended: false})); app.use(pp.initialize()); var config = check.config; config.callbackUrl = 'http://localhost:3033/login'; var profile = null; pp.use(new SamlStrategy(config, function (_profile, done) { profile = _profile; done(null, { id: profile.nameID }); }) ); var userSerialized = false; pp.serializeUser(function(user, done) { userSerialized = true; done(null, user); }); fakeClock = sinon.useFakeTimers(Date.parse(check.mockDate)); app.post('/login', pp.authenticate("saml"), function (req, res) { res.status(200).send("200 OK"); }); app.use(function (err, req, res, next) { // console.log( err.stack ); res.status(500).send('500 Internal Server Error'); }); server = app.listen(3033, function () { var requestOpts = { url: 'http://localhost:3033/login', method: 'POST', form: check.samlResponse }; request(requestOpts, function (err, response, body) { should.not.exist(err); response.statusCode.should.equal(check.expectedStatusCode); if (response.statusCode == 200) { userSerialized.should.be.true; if (check.expectedNameIDStartsWith) profile.nameID.should.startWith(check.expectedNameIDStartsWith); } done(); }); }); }; } function testPassReqToCallback(check) { return function (done) { var pp = new passport.Authenticator(); var app = express(); app.use(bodyParser.urlencoded({extended: false})); app.use(pp.initialize()); var config = check.config; config.callbackUrl = 'http://localhost:3033/login'; config.passReqToCallback = true; var passedRequest = null; pp.use(new SamlStrategy(config, function (req, _profile, done) { passedRequest = req; done(null, { id: _profile.nameID }); }) ); pp.serializeUser(function(user, done) { done(null, user); }); fakeClock = sinon.useFakeTimers(Date.parse(check.mockDate)); app.post('/login', pp.authenticate("saml"), function (req, res) { res.status(200).send("200 OK"); }); app.use(function (err, req, res, next) { // console.log( err.stack ); res.status(500).send('500 Internal Server Error'); }); server = app.listen(3033, function () { var requestOpts = { url: 'http://localhost:3033/login', method: 'POST', form: check.samlResponse }; request(requestOpts, function (err, response, body) { should.not.exist(err); response.statusCode.should.equal(check.expectedStatusCode); if (response.statusCode == 200) { should.exist(passedRequest); passedRequest.url.should.eql('/login'); passedRequest.method.should.eql('POST'); should(passedRequest.body).match(check.samlResponse); } else { should.not.exist(passedRequest); } done(); }); }); }; } for( var i = 0; i < capturedChecks.length; i++ ) { var check = capturedChecks[i]; it(check.name, testForCheck(check)); it(check.name + ' passReqToCallback', testPassReqToCallback(check)); } afterEach(function (done) { fakeClock.restore(); server.close(done); }); }); describe( 'captured SAML requests /', function() { var capturedChecks = [ { name: "Empty Config", config: {}, result: { 'samlp:AuthnRequest': { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Version: '2.0', ProtocolBinding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', AssertionConsumerServiceURL: 'http://localhost:3033/login', Destination: 'https://wwwexampleIdp.com/saml'}, 'saml:Issuer': [ { _: 'onelogin_saml', '$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ], 'samlp:NameIDPolicy': [ { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Format: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', AllowCreate: 'true' } } ], 'samlp:RequestedAuthnContext': [ { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Comparison: 'exact' }, 'saml:AuthnContextClassRef': [ { _: 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport', '$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ] } ] } } }, { name: "Empty Config w/ HTTP-POST binding", config: { authnRequestBinding: 'HTTP-POST' }, result: { 'samlp:AuthnRequest': { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Version: '2.0', ProtocolBinding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', AssertionConsumerServiceURL: 'http://localhost:3033/login', Destination: 'https://wwwexampleIdp.com/saml'}, 'saml:Issuer': [ { _: 'onelogin_saml', '$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ], 'samlp:NameIDPolicy': [ { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Format: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', AllowCreate: 'true' } } ], 'samlp:RequestedAuthnContext': [ { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Comparison: 'exact' }, 'saml:AuthnContextClassRef': [ { _: 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport', '$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ] } ] } } }, { name: "Config #2", config: { issuer: 'http://exampleSp.com/saml', identifierFormat: 'alternateIdentifier', passive: true, attributeConsumingServiceIndex: 123, forceAuthn: false }, result: { 'samlp:AuthnRequest': { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Version: '2.0', ProtocolBinding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', AssertionConsumerServiceURL: 'http://localhost:3033/login', AttributeConsumingServiceIndex: '123', Destination: 'https://wwwexampleIdp.com/saml', IsPassive: 'true'}, 'saml:Issuer': [ { _: 'http://exampleSp.com/saml', '$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ], 'samlp:NameIDPolicy': [ { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Format: 'alternateIdentifier', AllowCreate: 'true' } } ], 'samlp:RequestedAuthnContext': [ { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Comparison: 'exact' }, 'saml:AuthnContextClassRef': [ { _: 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport', '$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ] } ] } } }, { name: "Uncompressed config #2", config: { issuer: 'http://exampleSp.com/saml', identifierFormat: 'alternateIdentifier', passive: true, attributeConsumingServiceIndex: 123, skipRequestCompression: true }, result: { 'samlp:AuthnRequest': { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Version: '2.0', ProtocolBinding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', AssertionConsumerServiceURL: 'http://localhost:3033/login', AttributeConsumingServiceIndex: '123', Destination: 'https://wwwexampleIdp.com/saml', IsPassive: 'true' }, 'saml:Issuer': [ { _: 'http://exampleSp.com/saml', '$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ], 'samlp:NameIDPolicy': [ { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Format: 'alternateIdentifier', AllowCreate: 'true' } } ], 'samlp:RequestedAuthnContext': [ { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Comparison: 'exact' }, 'saml:AuthnContextClassRef': [ { _: 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport', '$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ] } ] } } }, { name: "Config #3", config: { issuer: 'http://exampleSp.com/saml', identifierFormat: 'alternateIdentifier', passive: true, attributeConsumingServiceIndex: 123, skipRequestCompression: true, disableRequestedAuthnContext: true, forceAuthn: true }, result: { 'samlp:AuthnRequest': { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Version: '2.0', ProtocolBinding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', AssertionConsumerServiceURL: 'http://localhost:3033/login', AttributeConsumingServiceIndex: '123', Destination: 'https://wwwexampleIdp.com/saml', IsPassive: 'true', ForceAuthn: 'true' }, 'saml:Issuer': [ { _: 'http://exampleSp.com/saml', '$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ], 'samlp:NameIDPolicy': [ { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Format: 'alternateIdentifier', AllowCreate: 'true' } } ] } } }, { name: "Config with AuthnContext", config: { issuer: 'http://exampleSp.com/saml', identifierFormat: 'alternateIdentifier', passive: true, attributeConsumingServiceIndex: 123, authnContext: 'myAuthnContext' }, result: { 'samlp:AuthnRequest': { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Version: '2.0', ProtocolBinding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', AssertionConsumerServiceURL: 'http://localhost:3033/login', AttributeConsumingServiceIndex: '123', Destination: 'https://wwwexampleIdp.com/saml', IsPassive: 'true'}, 'saml:Issuer': [ { _: 'http://exampleSp.com/saml', '$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ], 'samlp:NameIDPolicy': [ { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Format: 'alternateIdentifier', AllowCreate: 'true' } } ], 'samlp:RequestedAuthnContext': [ { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Comparison: 'exact' }, 'saml:AuthnContextClassRef': [ { _: 'myAuthnContext', '$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ] } ] } } }, { name: "Config with ProviderName", config: { issuer: 'http://exampleSp.com/saml', identifierFormat: 'alternateIdentifier', providerName: 'myProviderName' }, result: { 'samlp:AuthnRequest': { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Version: '2.0', ProtocolBinding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', ProviderName: 'myProviderName', AssertionConsumerServiceURL: 'http://localhost:3033/login', Destination: 'https://wwwexampleIdp.com/saml'}, 'saml:Issuer': [ { _: 'http://exampleSp.com/saml', '$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ], 'samlp:NameIDPolicy': [ { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Format: 'alternateIdentifier', AllowCreate: 'true' } } ], 'samlp:RequestedAuthnContext': [ { '$': { 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol', Comparison: 'exact' }, 'saml:AuthnContextClassRef': [ { _: 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport', '$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ] } ] } } } ]; var server; function testForCheck( check ) { return function( done ) { var app = express(); app.use( bodyParser.urlencoded({extended: false}) ); app.use( passport.initialize() ); var config = check.config; config.callbackUrl = 'http://localhost:3033/login'; config.entryPoint = 'https://wwwexampleIdp.com/saml'; var profile = null; passport.use( new SamlStrategy( config, function(_profile, done) { profile = _profile; done(null, { id: profile.nameID } ); }) ); app.get( '/login', passport.authenticate( "saml", { samlFallback: 'login-request', session: false } ), function(req, res) { res.status(200).send("200 OK"); }); app.use( function( err, req, res, next ) { console.log( err.stack ); res.status(500).send('500 Internal Server Error'); }); server = app.listen( 3033, function() { var requestOpts = { url: 'http://localhost:3033/login', method: 'get', followRedirect: false }; request(requestOpts, function(err, response, body) { should.not.exist(err); var encodedSamlRequest; if ( check.config.authnRequestBinding === "HTTP-POST" ) { response.statusCode.should.equal(200); body.should.match(/[^]*/); encodedSamlRequest = body.match( /https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'ploer@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + ''; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlObj = new SAML( samlConfig ); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.not.exist( err ); profile.nameID.should.startWith( 'ploer' ); done(); }); }); it( 'onelogin xml document with altered assertion should fail', function( done ) { var xml = 'https://app.onelogin.com/saml/metadata/371755' + 'https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'ben@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + ''; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlObj = new SAML( samlConfig ); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.exist( err ); err.message.should.match( 'Invalid signature' ); done(); }); }); it( 'onelogin xml document with duplicate altered assertion should fail', function( done ) { var xml = 'https://app.onelogin.com/saml/metadata/371755' + 'https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'ploer@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + 'https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'ben@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + ''; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlObj = new SAML( samlConfig ); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.exist( err ); err.message.should.match( 'Invalid signature' ); done(); }); }); it( 'onelogin xml document with extra unsigned & altered assertion should fail', function( done ) { var xml = 'https://app.onelogin.com/saml/metadata/371755' + 'https://app.onelogin.com/saml/metadata/371755ben@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + 'https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'ploer@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + ''; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlObj = new SAML( samlConfig ); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.exist( err ); err.message.should.match( 'Invalid signature' ); done(); }); }); it( 'onelogin xml document with extra nexted assertion should fail', function( done ) { var xml = 'https://app.onelogin.com/saml/metadata/371755' + 'https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'' + '' + 'https://app.onelogin.com/saml/metadata/371755ploer@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + '' + 'ploer@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + ''; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlObj = new SAML( samlConfig ); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.exist( err ); err.message.should.match( 'Invalid signature' ); done(); }); }); }); }); describe( 'getAuthorizeUrl request signature checks /', function() { var fakeClock; beforeEach(function(){ fakeClock = sinon.useFakeTimers(Date.parse('2014-05-28T00:13:09Z')); }); afterEach(function(){ fakeClock.restore(); }); it( 'acme_tools request signed with sha256', function( done ) { var samlConfig = { entryPoint: 'https://adfs.acme_tools.com/adfs/ls/', issuer: 'acme_tools_com', callbackUrl: 'https://relyingparty/adfs/postResponse', privateCert: fs.readFileSync(__dirname + '/static/acme_tools_com.key', 'utf-8'), authnContext: 'http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password', identifierFormat: null, signatureAlgorithm: 'sha256', additionalParams: { customQueryStringParam: 'CustomQueryStringParamValue' } }; var samlObj = new SAML( samlConfig ); samlObj.generateUniqueID = function () { return '12345678901234567890' }; samlObj.getAuthorizeUrl({}, function(err, url) { var qry = require('querystring').parse(require('url').parse(url).query); qry.SigAlg.should.match('http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'); qry.Signature.should.match('SL85w0h6Pt7ejplGrR4OOTh4Zo9zs/MQHZep27kSzs4+U/0QdQi7hg5T0TKqCSRBZpVtspMpw+i6F0tZrFot0dIJgeCgkvMA2Tllwt6K0DbKWOiNXW5S2M9tUZktdJVfjr2D5e0SG4jQIwa4PVONgNQEKFxydIqwxVh9NGYeDeMUGq5/4QpMDLgYOvLfShyvhlzmqeUs7LBlZbKJLCeXZi/Z5bnF+QOAugtKuh0G6kFOS0CmKVLIW/4XicLHmggUBDlt0VJaskxUx2amHSNUoYe3Z9/9TeZqc7IswNUOEiq/oy0DLhokLnBEj+dBRMlgkAHp/gaWcc1Vp/1jSlVAvg=='); qry.customQueryStringParam.should.match('CustomQueryStringParamValue'); done(); }); }); it( 'acme_tools request signed with sha1', function( done ) { var samlConfig = { entryPoint: 'https://adfs.acme_tools.com/adfs/ls/', issuer: 'acme_tools_com', callbackUrl: 'https://relyingparty/adfs/postResponse', privateCert: fs.readFileSync(__dirname + '/static/acme_tools_com.key', 'utf-8'), authnContext: 'http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password', identifierFormat: null, signatureAlgorithm: 'sha1', additionalParams: { customQueryStringParam: 'CustomQueryStringParamValue' } }; var samlObj = new SAML( samlConfig ); samlObj.generateUniqueID = function () { return '12345678901234567890' }; samlObj.getAuthorizeUrl({}, function(err, url) { var qry = require('querystring').parse(require('url').parse(url).query); qry.SigAlg.should.match('http://www.w3.org/2000/09/xmldsig#rsa-sha1'); qry.Signature.should.match('VnYOXVDiIaio+Vt8D2XXVwdyvwhDcdvgrQSkeq85G+MfU31yK9fvYEPFARK5pF1uJakMsYrKzVBv7HLCFcYuztpuIZloMFvFkado0MxFK4A/QFZn+EYDJE8ddLSvrW3iyuoxyVBSnH0+KLzDiI81B28YZNU3NFJIKCKzQSGIllJ7Vgw6KjH/BmE5DY0eSeUCEe6OygHgazjSrNIWQQjww5nSGIqAQl94OVanZtQBrYIUtik+d1lAhnginG0UnPccstenxEMAun2uMGp9hVqroWQvWRbX/xspRpjPOrIkvv63FzEgmRObXVNqpzDICJRUSlhTLdXAm2hb+ScYocO6EQ=='); qry.customQueryStringParam.should.match('CustomQueryStringParamValue'); done(); }); }); }); describe( 'getAdditionalParams checks /', function() { it ( 'should not pass any additional params by default', function( done ) { var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', }; var samlObj = new SAML( samlConfig ); ['logout', 'authorize'].forEach( function( operation ) { var additionalParams = samlObj.getAdditionalParams({}, operation); additionalParams.should.be.empty }); done(); }); it ( 'should not pass any additional params by default apart from the RelayState in request query', function( done ) { var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', }; var samlObj = new SAML( samlConfig ); ['logout', 'authorize'].forEach( function( operation ) { var additionalParams = samlObj.getAdditionalParams({query:{RelayState: "test"}}, operation); Object.keys(additionalParams).should.have.length(1); additionalParams.should.containEql({'RelayState': 'test'}); }); done(); }); it ( 'should not pass any additional params by default apart from the RelayState in request body', function( done ) { var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', }; var samlObj = new SAML( samlConfig ); ['logout', 'authorize'].forEach( function( operation ) { var additionalParams = samlObj.getAdditionalParams({body:{RelayState: "test"}}, operation); Object.keys(additionalParams).should.have.length(1); additionalParams.should.containEql({'RelayState': 'test'}); }); done(); }); it ( 'should pass additional params with all operations if set in additionalParams', function( done ) { var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', additionalParams: { 'queryParam': 'queryParamValue' } }; var samlObj = new SAML( samlConfig ); ['logout', 'authorize'].forEach( function( operation ) { var additionalParams = samlObj.getAdditionalParams({}, operation); Object.keys(additionalParams).should.have.length(1); additionalParams.should.containEql({'queryParam': 'queryParamValue'}); }); done(); }); it ( 'should pass additional params with "authorize" operations if set in additionalAuthorizeParams', function( done ) { var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', additionalAuthorizeParams: { 'queryParam': 'queryParamValue' } }; var samlObj = new SAML( samlConfig ); var additionalAuthorizeParams = samlObj.getAdditionalParams({}, 'authorize'); Object.keys(additionalAuthorizeParams).should.have.length(1); additionalAuthorizeParams.should.containEql({'queryParam': 'queryParamValue'}); var additionalLogoutParams = samlObj.getAdditionalParams({}, 'logout'); additionalLogoutParams.should.be.empty; done(); }); it ( 'should pass additional params with "logout" operations if set in additionalLogoutParams', function( done ) { var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', additionalLogoutParams: { 'queryParam': 'queryParamValue' } }; var samlObj = new SAML( samlConfig ); var additionalAuthorizeParams = samlObj.getAdditionalParams({}, 'authorize'); additionalAuthorizeParams.should.be.empty; var additionalLogoutParams = samlObj.getAdditionalParams({}, 'logout'); Object.keys(additionalLogoutParams).should.have.length(1); additionalLogoutParams.should.containEql({'queryParam': 'queryParamValue'}); done(); }); it ( 'should merge additionalLogoutParams and additionalAuthorizeParams with additionalParams', function( done ) { var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', additionalParams: { 'queryParam1': 'queryParamValue' }, additionalAuthorizeParams: { 'queryParam2': 'queryParamValueAuthorize' }, additionalLogoutParams: { 'queryParam2': 'queryParamValueLogout' } }; var samlObj = new SAML( samlConfig ); var additionalAuthorizeParams = samlObj.getAdditionalParams({}, 'authorize'); Object.keys(additionalAuthorizeParams).should.have.length(2); additionalAuthorizeParams.should.containEql({'queryParam1': 'queryParamValue', 'queryParam2': 'queryParamValueAuthorize'}); var additionalLogoutParams = samlObj.getAdditionalParams({}, 'logout'); Object.keys(additionalLogoutParams).should.have.length(2); additionalLogoutParams.should.containEql({'queryParam1': 'queryParamValue', 'queryParam2': 'queryParamValueLogout'}); done(); }); it ( 'should prioritize additionalLogoutParams and additionalAuthorizeParams over additionalParams', function( done ) { var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', additionalParams: { 'queryParam': 'queryParamValue' }, additionalAuthorizeParams: { 'queryParam': 'queryParamValueAuthorize' }, additionalLogoutParams: { 'queryParam': 'queryParamValueLogout' } }; var samlObj = new SAML( samlConfig ); var additionalAuthorizeParams = samlObj.getAdditionalParams({}, 'authorize'); Object.keys(additionalAuthorizeParams).should.have.length(1); additionalAuthorizeParams.should.containEql({'queryParam': 'queryParamValueAuthorize'}); var additionalLogoutParams = samlObj.getAdditionalParams({}, 'logout'); Object.keys(additionalLogoutParams).should.have.length(1); additionalLogoutParams.should.containEql({'queryParam': 'queryParamValueLogout'}); done(); }); }); describe( 'InResponseTo validation checks /', function(){ var fakeClock = null; afterEach(function() { if (fakeClock) { fakeClock.restore(); fakeClock = null; } }); it( 'onelogin xml document with InResponseTo from request should validate', function( done ) { var requestId = '_a6fc46be84e1e3cf3c50'; var xml = 'https://app.onelogin.com/saml/metadata/371755' + 'https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'ploer@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + ''; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', cert: TEST_CERT, validateInResponseTo: true }; var samlObj = new SAML( samlConfig ); fakeClock = sinon.useFakeTimers(Date.parse('2014-05-28T00:13:09Z')); // Mock the SAML request being passed through Passport-SAML samlObj.cacheProvider.save(requestId, new Date().toISOString(), function(){}); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.not.exist( err ); profile.nameID.should.startWith( 'ploer' ); samlObj.cacheProvider.get(requestId, function(err, value){ should.not.exist(value); done(); }); }); }); it( 'onelogin xml document without InResponseTo from request should fail', function( done ) { var requestId = '_a6fc46be84e1e3cf3c50'; var xml = 'https://app.onelogin.com/saml/metadata/371755' + 'https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'ploer@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + ''; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', cert: TEST_CERT, validateInResponseTo: true }; var samlObj = new SAML( samlConfig ); fakeClock = sinon.useFakeTimers(Date.parse('2014-05-28T00:13:09Z')); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.exist( err ); err.message.should.match( 'InResponseTo is not valid' ); done(); }); }); it( 'xml document with SubjectConfirmation InResponseTo from request should be valid', function(done){ var requestId = '_dfab47d5d46374cd4b71'; var xml = 'Verizon IDP HubQecaVjMY/2M4VMJsakvX8uh2Mrg=QTJ//ZHEQRe9/nA5qTkhECZc2u6M1dHzTkujKBedskLSRPL8LRBb4Yftla0zu848sYvLd3SXzEysYu/jrAjaVDevYZIAdyj/3HCw8pS0ZnQDaCgYuAkH4JmYxBfW1Sc9Kr0vbR58ihwWOZd4xHIn/b8xLs8WNsyTHix2etrLGznioLwTOBO3+SgjwSiSP9NUhrlOvolbuu/6xhLi37/L08JaBvOw3o0k4V8xS87SFczhm4f6wvQM5mP6sZAreoNcWZqQM7vIHFjL0/H9vTaLAN8+fQOc81xFtateTKwFQlJMUmdWKZ8L7ns0Uf1xASQjXtSAACbXI+PuVLjz8nnm3g==MIIC7TCCAdmgAwIBAgIQuIdqos+9yKBC4oygbhtdfzAJBgUrDgMCHQUAMBIxEDAOBgNVBAMTB1Rlc3RTVFMwHhcNMTQwNDE2MTIyMTEwWhcNMzkxMjMxMjM1OTU5WjASMRAwDgYDVQQDEwdUZXN0U1RTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmhReamVYbeOWwrrAvHPvS9KKBwv4Tj7wOSGDXbNgfjhSvVyXsnpYRcuoJkvE8b9tCjFTbXCfbhnaVrpoXaWFtP1YvUIZvCJGdOOTXltMNDlNIaFmsIsomza8IyOHXe+3xHWVtxO8FG3qnteSkkVIQuAvBqpPfQtxrXCZOlbQZm7q69QIQ64JvLJfRwHN1EywMBVwbJgrV8gBdE3RITI76coSOK13OBTlGtB0kGKLDrF2JW+5mB+WnFR7GlXUj+V0R9WStBomVipJEwr6Q3fU0deKZ5lLw0+qJ0T6APInwN5TIN/AbFCHd51aaf3zEP+tZacQ9fbZqy9XBAtL2pCAJQIDAQABo0cwRTBDBgNVHQEEPDA6gBDECazhZ8Ar+ULXb0YTs5MvoRQwEjEQMA4GA1UEAxMHVGVzdFNUU4IQuIdqos+9yKBC4oygbhtdfzAJBgUrDgMCHQUAA4IBAQAioMSOU9QFw+yhVxGUNK0p/ghVsHnYdeOE3vSRhmFPsetBt8S35sI4QwnQNiuiEYqp++FabiHgePOiqq5oeY6ekJik1qbs7fgwnaQXsxxSucHvc4BU81x24aKy6jeJzxmFxo3mh6y/OI1peCMSH48iUzmhnoSulp0+oAs3gMEFI0ONbgAA/XoAHaVEsrPj10i3gkztoGdpH0DYUe9rABOJxX/3mNF+dCVJG7t7BoSlNAWlSDErKciNNax1nBskFqNWNIKzUKBIb+GVKkIB2QpATMQB6Oe7inUdT9kkZ/Q7oPBATZk+3mFsIoWr8QRFSqvToOhun7EY2/VtuiV1d932Verizon IDP HubUIS/jochen-workUIS/jochen-workUIS usere9aba0c4-ece8-4b44-9526-d24418aa95dctestorgTest User::1'; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', cert: 'MIIC7TCCAdmgAwIBAgIQuIdqos+9yKBC4oygbhtdfzAJBgUrDgMCHQUAMBIxEDAOBgNVBAMTB1Rlc3RTVFMwHhcNMTQwNDE2MTIyMTEwWhcNMzkxMjMxMjM1OTU5WjASMRAwDgYDVQQDEwdUZXN0U1RTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmhReamVYbeOWwrrAvHPvS9KKBwv4Tj7wOSGDXbNgfjhSvVyXsnpYRcuoJkvE8b9tCjFTbXCfbhnaVrpoXaWFtP1YvUIZvCJGdOOTXltMNDlNIaFmsIsomza8IyOHXe+3xHWVtxO8FG3qnteSkkVIQuAvBqpPfQtxrXCZOlbQZm7q69QIQ64JvLJfRwHN1EywMBVwbJgrV8gBdE3RITI76coSOK13OBTlGtB0kGKLDrF2JW+5mB+WnFR7GlXUj+V0R9WStBomVipJEwr6Q3fU0deKZ5lLw0+qJ0T6APInwN5TIN/AbFCHd51aaf3zEP+tZacQ9fbZqy9XBAtL2pCAJQIDAQABo0cwRTBDBgNVHQEEPDA6gBDECazhZ8Ar+ULXb0YTs5MvoRQwEjEQMA4GA1UEAxMHVGVzdFNUU4IQuIdqos+9yKBC4oygbhtdfzAJBgUrDgMCHQUAA4IBAQAioMSOU9QFw+yhVxGUNK0p/ghVsHnYdeOE3vSRhmFPsetBt8S35sI4QwnQNiuiEYqp++FabiHgePOiqq5oeY6ekJik1qbs7fgwnaQXsxxSucHvc4BU81x24aKy6jeJzxmFxo3mh6y/OI1peCMSH48iUzmhnoSulp0+oAs3gMEFI0ONbgAA/XoAHaVEsrPj10i3gkztoGdpH0DYUe9rABOJxX/3mNF+dCVJG7t7BoSlNAWlSDErKciNNax1nBskFqNWNIKzUKBIb+GVKkIB2QpATMQB6Oe7inUdT9kkZ/Q7oPBATZk+3mFsIoWr8QRFSqvToOhun7EY2/VtuiV1d932', validateInResponseTo: true }; var samlObj = new SAML( samlConfig ); fakeClock = sinon.useFakeTimers(Date.parse('2014-06-05T12:07:07.662Z')); // Mock the SAML request being passed through Passport-SAML samlObj.cacheProvider.save(requestId, new Date().toISOString(), function(){}); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.not.exist( err ); profile.nameID.should.startWith( 'UIS/jochen-work' ); samlObj.cacheProvider.get(requestId, function(err, value){ should.not.exist(value); done(); }); }); }); it( 'xml document with multiple AttributeStatements should have all attributes present on profile', function(done){ var requestId = '_dfab47d5d46374cd4b71'; var xml = 'Verizon IDP HubVerizon IDP HubUIS/jochen-workUIS/jochen-workUIS usere9aba0c4-ece8-4b44-9526-d24418aa95dctestorgTest User::1qD+sVCaEdy1dTJoUQdo6o+tYsuU=aLl+1yT7zdT4WnRXKh9cx7WWZnUi/NoxMJWhXP5d+Zu9A4/fjKApSywimU0MTTQxYpvZLjOZPsSwmvc1boJOlXveDsL7A3YWi/f7/zqlVWOfXLE8TVLqUE4jtLsJHFWIJXmh8CI0loqQNf6QcYi9BwCK82FhhXC+qWA5WCZIIWUUMxjxnPbunQ7mninEeW568wqyhb9pLV8QkThzZrZINCqxNvWyGuK/XGPx7ciD6ywbBkdOjlDbwRMaKQ9YeCzZGGzJwOe/NuCXj+oUyzfmzUCobIIR0HYLc4B5UplL7XIKQzpOA2lDDsLe6ZzdTv1qjxSm+dlVfo24onmiPlQUgA=='; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', cert: 'MIIDtTCCAp2gAwIBAgIJAKg4VeVcIDz1MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTUwODEzMDE1NDIwWhcNMTUwOTEyMDE1NDIwWjBFMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxG3ouM7U+fXbJt69X1H6d4UNg/uRr06pFuU9RkfIwNC+yaXyptqB3ynXKsL7BFt4DCd0fflRvJAx3feJIDp16wN9GDVHcufWMYPhh2j5HcTW/j9JoIJzGhJyvO00YKBt+hHy83iN1SdChKv5y0iSyiPP5GnqFw+ayyHoM6hSO0PqBou1Xb0ZSIE+DHosBnvVna5w2AiPY4xrJl9yZHZ4Q7DfMiYTgstjETio4bX+6oLiBnYktn7DjdEslqhffVme4PuBxNojI+uCeg/sn4QVLd/iogMJfDWNuLD8326Mi/FE9cCRvFlvAiMSaebMI3zPaySsxTK7Zgj5TpEbmbHI9wIDAQABo4GnMIGkMB0GA1UdDgQWBBSVGgvoW4MhMuzBGce29PY8vSzHFzB1BgNVHSMEbjBsgBSVGgvoW4MhMuzBGce29PY8vSzHF6FJpEcwRTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAKg4VeVcIDz1MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJu1rqs+anD74dbdwgd3CnqnQsQDJiEXmBhG2leaGt3ve9b/9gKaJg2pyb2NyppDe1uLqh6nNXDuzg1oNZrPz5pJL/eCXPl7FhxhMUi04TtLf8LeNTCIWYZiFuO4pmhohHcv8kRvYR1+6SkLTC8j/TZerm7qvesSiTQFNapa1eNdVQ8nFwVkEtWl+JzKEM1BlRcn42sjJkijeFp7DpI7pU+PnYeiaXpRv5pJo8ogM1iFxN+SnfEs0EuQ7fhKIG9aHKi7bKZ7L6SyX7MDIGLeulEU6lf5D9BfXNmcMambiS0pXhL2QXajt96UBq8FT2KNXY8XNtR4y6MyyCzhaiZZcc8=', validateInResponseTo: true }; var samlObj = new SAML( samlConfig ); fakeClock = sinon.useFakeTimers(Date.parse('2014-06-05T12:07:07.662Z')); // Mock the SAML request being passed through Passport-SAML samlObj.cacheProvider.save(requestId, new Date().toISOString(), function(){}); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.not.exist( err ); profile.nameID.should.startWith( 'UIS/jochen-work' ); profile['vz::identity'].should.equal( 'UIS/jochen-work' ); profile['vz::subjecttype'].should.equal( 'UIS user' ); profile['vz::account'].should.equal( 'e9aba0c4-ece8-4b44-9526-d24418aa95dc' ); profile['vz::org'].should.equal( 'testorg' ); profile['vz::name'].should.equal( 'Test User' ); profile['net::ip'].should.equal( '::1' ); samlObj.cacheProvider.get(requestId, function(err, value){ should.not.exist(value); done(); }); }); }); describe( 'InResponseTo server cache expiration tests /', function() { it( 'should expire a cached request id after the time', function(done){ var requestId = '_dfab47d5d46374cd4b71'; var samlConfig = { validateInResponseTo: true, requestIdExpirationPeriodMs: 100 }; var samlObj = new SAML( samlConfig ); // Mock the SAML request being passed through Passport-SAML samlObj.cacheProvider.save(requestId, new Date().toISOString(), function(){}); setTimeout(function(){ samlObj.cacheProvider.get(requestId, function(err, value){ should.not.exist(value); done(); }); }, 300); }); it( 'should expire many cached request ids after the time', function(done){ var expiredRequestId1 = '_dfab47d5d46374cd4b71'; var expiredRequestId2 = '_dfab47d5d46374cd4b72'; var requestId = '_dfab47d5d46374cd4b73'; var samlConfig = { validateInResponseTo: true, requestIdExpirationPeriodMs: 100 }; var samlObj = new SAML( samlConfig ); samlObj.cacheProvider.save(expiredRequestId1, new Date().toISOString(), function(){}); samlObj.cacheProvider.save(expiredRequestId2, new Date().toISOString(), function(){}); setTimeout(function(){ // Add one more that shouldn't expire samlObj.cacheProvider.save(requestId, new Date().toISOString(), function(){}); samlObj.cacheProvider.get(expiredRequestId1, function(err, value){ should.not.exist(value); }); samlObj.cacheProvider.get(expiredRequestId2, function(err, value){ should.not.exist(value); }); samlObj.cacheProvider.get(requestId, function(err, value){ should.exist(value); }); // Let the expiration timer run again and we should have no more cached setTimeout(function(){ samlObj.cacheProvider.get(requestId, function(err, value){ should.not.exist(value); done(); }); }, 300) }, 300); }); }); }); describe( 'assertion condition checks /', function() { var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', cert: TEST_CERT, }; var fakeClock; beforeEach(function() { fakeClock = sinon.useFakeTimers(Date.parse('2014-05-28T00:13:09Z')); }); afterEach(function() { fakeClock.restore(); }); it( 'onelogin xml document with current time after NotBefore time should validate', function( done ) { var xml = 'https://app.onelogin.com/saml/metadata/371755' + 'https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'ploer@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + ''; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlObj = new SAML( samlConfig ); // Fake the current date to be within the valid time range fakeClock = sinon.useFakeTimers(Date.parse('2014-05-28T00:13:09Z')); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.not.exist( err ); profile.nameID.should.startWith( 'ploer' ); done(); }); }); it( 'onelogin xml document with current time equal to NotBefore (plus default clock skew) time should validate', function( done ) { var xml = 'https://app.onelogin.com/saml/metadata/371755' + 'https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'ploer@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + ''; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlObj = new SAML( samlConfig ); // Fake the current date to be within the valid time range fakeClock = sinon.useFakeTimers(Date.parse('2014-05-28T00:13:08Z')); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.not.exist( err ); profile.nameID.should.startWith( 'ploer' ); done(); }); }); it( 'onelogin xml document with current time before NotBefore time should fail', function( done ) { var xml = 'https://app.onelogin.com/saml/metadata/371755' + 'https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'ploer@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + ''; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlObj = new SAML( samlConfig ); // Fake the current date to be after the valid time range fakeClock = sinon.useFakeTimers(Date.parse('2014-05-28T00:13:07Z')); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.exist( err ); err.message.should.match( 'SAML assertion not yet valid' ); done(); }); }); it( 'onelogin xml document with current time equal to NotOnOrAfter (minus default clock skew) time should fail', function( done ) { var xml = 'https://app.onelogin.com/saml/metadata/371755' + 'https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'ploer@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + ''; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlObj = new SAML( samlConfig ); // Fake the current date to be after the valid time range fakeClock = sinon.useFakeTimers(Date.parse('2014-05-28T00:19:08Z')); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.exist( err ); err.message.should.match( 'SAML assertion expired' ); done(); }); }); it( 'onelogin xml document with current time after NotOnOrAfter time (minus default clock skew) should fail', function( done ) { var xml = 'https://app.onelogin.com/saml/metadata/371755' + 'https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'ploer@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + ''; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlObj = new SAML( samlConfig ); // Fake the current date to be after the valid time range fakeClock = sinon.useFakeTimers(Date.parse('2014-05-28T00:19:09Z')); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.exist( err ); err.message.should.match( 'SAML assertion expired' ); done(); }); }); it( 'onelogin xml document with current time after NotOnOrAfter time with accepted clock skew equal to -1 should pass', function( done ) { var xml = 'https://app.onelogin.com/saml/metadata/371755' + 'https://app.onelogin.com/saml/metadata/371755DCnPTQYBb1hKspbe6fg1U3q8xn4=e0+aFomA0+JAY0f9tKqzIuqIVSSw7LiFUsneEDKPBWdiTz1sMdgr/2y1e9+rjaS2mRmCi/vSQLY3zTYz0hp6nJNU19+TWoXo9kHQyWT4KkeQL4Xs/gZ/AoKC20iHVKtpPps0IQ0Ml/qRoouSitt6Sf/WDz2LV/pWcH2hx5tv3xSw36hK2NQc7qw7r1mEXnvcjXReYo8rrVf7XHGGxNoRIEICUIi110uvsWemSXf0Z0dyb0FVYOWuSsQMDlzNpheADBifFO4UTfSEhFZvn8kVCGZUIwrbOhZ2d/+YEtgyuTg+qtslgfy4dwd4TvEcfuRzQTazeefprSFyiQckAXOjcw=='+TEST_CERT+'ploer@subspacesw.com{audience}urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + ''; var base64xml = new Buffer( xml ).toString('base64'); var container = { SAMLResponse: base64xml }; var samlConfig = { entryPoint: 'https://app.onelogin.com/trust/saml2/http-post/sso/371755', cert: TEST_CERT, acceptedClockSkewMs: -1 }; var samlObj = new SAML( samlConfig ); // Fake the current date to be after the valid time range fakeClock = sinon.useFakeTimers(Date.parse('2014-05-28T00:20:09Z')); samlObj.validatePostResponse( container, function( err, profile, logout ) { should.not.exist( err ); profile.nameID.should.startWith( 'ploer' ); done(); }); }); }); }); describe('validatePostRequest()', function() { var samlObj; beforeEach(function() { samlObj = new SAML({ cert: fs.readFileSync(__dirname + '/static/cert.pem', 'ascii') }); }); it('errors if bad xml', function(done) { var body = { SAMLRequest: "asdf" }; samlObj.validatePostRequest(body, function(err) { should.exist(err); done(); }); }); it('errors if bad signature', function(done) { var body = { SAMLRequest: fs.readFileSync(__dirname + '/static/logout_request_with_bad_signature.xml', 'base64') }; samlObj.validatePostRequest(body, function(err) { should.exist(err); err.should.eql(new Error('Invalid signature')); done(); }); }); it('returns profile for valid signature', function(done) { var body = { SAMLRequest: fs.readFileSync(__dirname + '/static/logout_request_with_good_signature.xml', 'base64') }; samlObj.validatePostRequest(body, function(err, profile) { should.not.exist(err); profile.should.eql({ ID: 'pfxd4d369e8-9ea1-780c-aff8-a1d11a9862a1', issuer: 'http://sp.example.com/demo1/metadata.php', nameID: 'ONELOGIN_f92cc1834efc0f73e9c09f482fce80037a6251e7', nameIDFormat: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient' }); done(); }); }); it('returns profile for valid signature including session index', function(done) { var body = { SAMLRequest: fs.readFileSync(__dirname + '/static/logout_request_with_session_index.xml', 'base64') }; samlObj.validatePostRequest(body, function(err, profile) { should.not.exist(err); profile.should.eql({ ID: 'pfxd4d369e8-9ea1-780c-aff8-a1d11a9862a1', issuer: 'http://sp.example.com/demo1/metadata.php', nameID: 'ONELOGIN_f92cc1834efc0f73e9c09f482fce80037a6251e7', nameIDFormat: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient', sessionIndex: '1' }); done(); }); }); it('errors if bad privateCert to requestToURL', function(done){ var samlObj = new SAML({ entryPoint: "foo", privateCert: "-----BEGIN CERTIFICATE-----\n"+ "8mvhvrcCOiJ3mjgKNN1F31jOBJuZNmq0U7n9v+Z+3NfyU/0E9jkrnFvm5ks+p8kl\n" + "BjuBk9RAkazsU9l02XMS/VxOOIifxKC7R9bDtx0hjolYxgqxPIO5s4rmjj0rLzvo\n" + "vQTTTx/tB5e+hbdx922QSeTjP4DO4ms6cIexcH+ZEUOJ3wXiHToJW83SXLRtwPI9\n" + "JbWKeS9nWPnzcedbDNZkGtohW5vf32BHuvLsWcl6eFXRSkdX/7+rgpXmDRB7caQ+\n" + "2SXVY7ORily7LTKg1cFmuKHDzKTGFIp5/GU6dwIDAQABAoIBAArgFQ+Uk4UN4diY\n" + "gJWCAaQlTVmP0UEHZQt/NmJrc9ZVduuhOP0hH6gF53nREHz5UQb4nXB2Ksa3MtYD\n" + "Z1vhJcu/T7pvmib4q+Ij6oAmlyeL/xwVY3IUURMxX3tCdPItlk4PEFELKeqQOiIS\n" + "7B0DYxWfJbMle3c95w5ruYEr2A+fHCKVSlDpg7uPd9VQ6t7bGMZZvc9tDSC1qPXQ\n" + "Gd/WOMXxi+t/TpyVZ6tOcEekQzAMLmWElUUPx3TJ0ur0Zl2LZ7IvQEXXias4lUHV\n" + "fnH3akDCMmdhlJSVqUfplrh85zAOh6fLloZagphj/Kpgfw1TZ+njSDYqSLYE0NZ1\n" + "j+83feECgYEA2aNGgbc+t6QLrJJ63l9Mz541lVV3IUAxZ5ACqOnMkQVuLoa5IMwM\n" + "oENIo38ptfHQqjQ9x8/tEINFqOHnQuOJ/+1xP9f0Me+0clRDCqjGYqNYgmakKyD7\n" + "vey/q6kwHk679RVGiI1p+HdoA+CbEKWHJiRxE0RhAA3G3wGAq7kpJocCgYEAxp4/\n" + "tCft+eHVRivspfDN//axc2TR6qWP9E1ueGvbiXPXv0Puag0W9cER/df/s5jW4Rqg\n" + "CE8649HPUZ0FJT+YaeKgu2Sw9SMcGl4/uyHzg7KnXIeYyQZJPqQkKyXmIix8cw3+\n" + "HBGRtwX5nOy0DgFdaMiH0F08peNI9QHKKTBoWJECgYEAyymJ1ekzWMaAR1Zt8EvS\n" + "LjWoG4EuthFwjRZ4BSpLVk1Vb4VAKAeS+cAVfNpmG3xip6Ag0/ebe0CvtFk9QsmZ\n" + "txj2EP0M7div/9H8y2SF3OpS41fhhIlDtyXcPuivDHu/Jaf4sdwgwlrk9EmlN0Lu\n" + "CIMYMz4vtpclwGNss+EjMt0CgYEAqepD0Vm/iuCaVhfJsgSaFvnywSdlNfpBdtyv\n" + "PzH2dFa4IZZ55hwgoklznNgmlnyQh68BbVpqpO+fDtDnz//h4ePRYb84a96Hcj9j\n" + "AjJ/YxF5f/04xfEsw/wkPQ2FHYM1TDCSTWzyXcMs0gTl3H1qbfPvzF+XPMt+ZKwN\n" + "SMNy4SECgYB3ig6t+XVfNkw8oBOh0Gx37XKbmImXsA8ucDAX9KUbMIvD03XCEf34\n" + "jF3SNJh0SmHoT62vc+cJqPxMDP6E7Q1nZxsEyaAkKr2H4dSM4SlRm0VB+bS+jXsz\n" + "PCiRGSm8eupuxfix05LMMreo4mC7e3Ir4JhdCsXxAMZIvbNyXcvUMA==\n" + "-----END CERTIFICATE-----\n" }); var request = 'onelogin_samlurn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'; samlObj.requestToUrl(request, null, 'authorize', {}, function(err) { should.exist(err); err.message.should.eql('error:0906D06C:PEM routines:PEM_read_bio:no start line'); done(); }); }); }); });