[midPoint] SAML authentication : issues with signature key

Frédéric Lohier frederic at lohier.org
Thu May 6 16:24:44 CEST 2021


Hello,



I am settting up the SAML authentication using the flexible authentication
features specified here :
https://docs.evolveum.com/midpoint/reference/security/authentication/flexible-authentication/#module-configuration



I was able to to setup the SSO without signature.

The SSO Login works with our IDP (HTTP POST or REDIRECT bindings) but the
SLO (HTTP REDIRECT binding) does not work since the logout request must be
signed according to the SAML 2 standard (error on my IDP :
org.opensaml.saml.common.SAMLException: Logout request is not signed but
should be.).



But if I try to setup the SP signature key in
<serviceProvider><keys><activeSimpleKey> and enable
<signRequests>true</signRequests>, then I get the error below.



I also tried to use <activeKeyStoreKey> instead of <activeSimpleKey> but
then I get the error



[http-nio-10.104.16.170-8080-exec-5] ERROR
(com.evolveum.midpoint.web.security.filter.TranslateExceptionFilter):
*Credential
cannot be null*
net.shibboleth.utilities.java.support.logic.ConstraintViolationException:
Credential cannot be null

        at
net.shibboleth.utilities.java.support.logic.Constraint.isNotNull(Constraint.java:227)

        at
org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorManager.getFactory(KeyInfoGeneratorManager.java:82)



*Does anyone has a working example with SP signature keys?*



I also opened a JIRA issue with more details :
https://jira.evolveum.com/browse/MID-7034



-Frederic



----



Full error when using <activeSimpleKey> :



2021-05-06 12:31:51,334 [MODEL] [http-nio-10.104.16.170-8080-exec-3] ERROR
(com.evolveum.midpoint.web.security.filter.TranslateExceptionFilter): *class
org.bouncycastle.asn1.pkcs.PrivateKeyInfo cannot be cast to class
org.bouncycastle.*

*openssl.PEMKeyPair (org.bouncycastle.asn1.pkcs.PrivateKeyInfo and
org.bouncycastle.openssl.PEMKeyPair are in unnamed module of loader
org.springframework.boot.loader.LaunchedURLClassLoader @6659c656*)

java.lang.ClassCastException: class
org.bouncycastle.asn1.pkcs.PrivateKeyInfo cannot be cast to class
org.bouncycastle.openssl.PEMKeyPair
(org.bouncycastle.asn1.pkcs.PrivateKeyInfo and
org.bouncycastle.openssl.PEMKeyPair are in unname

d module of loader org.springframework.boot.loader.LaunchedURLClassLoader
@6659c656)

        at
org.springframework.security.saml.util.X509Utilities.readPrivateKey(X509Utilities.java:110)

        at
org.springframework.security.saml.spi.SamlKeyStoreProvider.getKeyStore(SamlKeyStoreProvider.java:49)

        at
com.evolveum.midpoint.web.security.MidpointSamlKeyStoreProvider.getKeyStore(MidpointSamlKeyStoreProvider.java:56)

        at
com.evolveum.midpoint.web.security.MidpointOpenSamlImplementation.getCredentialsResolver(MidpointOpenSamlImplementation.java:32)

        at
org.springframework.security.saml.spi.opensaml.OpenSamlImplementation.getKeyDescriptor(OpenSamlImplementation.java:1916)

        at
org.springframework.security.saml.spi.opensaml.OpenSamlImplementation.getRoleDescriptors(OpenSamlImplementation.java:958)

        at
org.springframework.security.saml.spi.opensaml.OpenSamlImplementation.internalToXml(OpenSamlImplementation.java:886)

        at
org.springframework.security.saml.spi.opensaml.OpenSamlImplementation.toXml(OpenSamlImplementation.java:391)

        at
org.springframework.security.saml.spi.DefaultSamlTransformer.toXml(DefaultSamlTransformer.java:55)

        at
org.springframework.security.saml.provider.AbstractHostedProviderService.toXml(AbstractHostedProviderService.java:313)

        at
org.springframework.security.saml.provider.SamlMetadataFilter.doFilterInternal(SamlMetadataFilter.java:67)

        at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

        at
com.evolveum.midpoint.web.security.filter.MidpointAuthFilter$VirtualFilterChain.doFilter(MidpointAuthFilter.java:418)

        at
org.springframework.security.saml.provider.config.ThreadLocalSamlConfigurationFilter.doFilterInternal(ThreadLocalSamlConfigurationFilter.java:42)

        at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

        at
com.evolveum.midpoint.web.security.filter.MidpointAuthFilter$VirtualFilterChain.doFilter(MidpointAuthFilter.java:418)

        at
com.evolveum.midpoint.web.security.filter.RedirectForLoginPagesWithAuthenticationFilter.doFilterInternal(RedirectForLoginPagesWithAuthenticationFilter.java:39)

        at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

        at
com.evolveum.midpoint.web.security.filter.MidpointAuthFilter$VirtualFilterChain.doFilter(MidpointAuthFilter.java:418)

        at
org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)

        at
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)

        at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

        at
com.evolveum.midpoint.web.security.filter.MidpointAuthFilter$VirtualFilterChain.doFilter(MidpointAuthFilter.java:418)

        at
com.evolveum.midpoint.web.security.filter.MidpointAuthFilter.processingOfAuthenticatedRequest(MidpointAuthFilter.java:374)

        at
com.evolveum.midpoint.web.security.filter.MidpointAuthFilter.doFilterInternal(MidpointAuthFilter.java:191)

        at
com.evolveum.midpoint.web.security.filter.MidpointAuthFilter.doFilter(MidpointAuthFilter.java:109)

        at
com.evolveum.midpoint.web.security.filter.MidpointFilterChainProxy$VirtualFilterChain.doFilter(MidpointFilterChainProxy.java:169)

        at
com.evolveum.midpoint.web.security.filter.TranslateExceptionFilter.doFilterInternal(TranslateExceptionFilter.java:32)

        at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

        at
com.evolveum.midpoint.web.security.filter.MidpointFilterChainProxy$VirtualFilterChain.doFilter(MidpointFilterChainProxy.java:171)

        at
org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:147)

        at
org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:125)

        at
com.evolveum.midpoint.web.security.filter.MidpointFilterChainProxy$VirtualFilterChain.doFilter(MidpointFilterChainProxy.java:171)

        at
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)

        at
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)

        at
com.evolveum.midpoint.web.security.filter.MidpointFilterChainProxy$VirtualFilterChain.doFilter(MidpointFilterChainProxy.java:171)

        at
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)

        at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

        at
com.evolveum.midpoint.web.security.filter.MidpointFilterChainProxy$VirtualFilterChain.doFilter(MidpointFilterChainProxy.java:171)

        at
com.evolveum.midpoint.web.security.filter.MidpointFilterChainProxy.doFilterInternal(MidpointFilterChainProxy.java:95)

        at
com.evolveum.midpoint.web.security.filter.MidpointFilterChainProxy.doFilter(MidpointFilterChainProxy.java:60)

        at
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)

        at
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)

        at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

        at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

        at
org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)

        at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

        at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

        at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

        at
org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)

        at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

        at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

        at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

        at
org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)

        at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

        at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

        at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

        at
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)

        at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

        at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

        at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

        at
com.evolveum.midpoint.web.boot.TrailingSlashRedirectingFilter.doFilterInternal(TrailingSlashRedirectingFilter.java:60)

        at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

        at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

        at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

        at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)

        at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)

        at
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)

        at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)

        at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)

        at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)

        at
com.evolveum.midpoint.web.boot.NodeIdHeaderValve.invoke(NodeIdHeaderValve.java:46)

        at
com.evolveum.midpoint.web.boot.TomcatRootValve.invoke(TomcatRootValve.java:62)

        at
org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:764)

        at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)

        at
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)

        at
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)

        at
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:887)

        at
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1684)

        at
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)

        at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)

        at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)

        at
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

        at java.base/java.lang.Thread.run(Thread.java:829)





For reference, here is my <securityPolicy><authentication> configuration
(cleaned for lisibility) :



<securityPolicy >

    <name>Default Security Policy</name>

    <authentication>

        <sequence>

            <name>admin-gui-default</name>

            <description>

                Default GUI authentication sequence.

                We want to try company SSO, federation and internal.
In that order.

                Just one of then need to be successful to let user in.

            </description>

            <channel>

                <channelId>
http://midpoint.evolveum.com/xml/ns/public/common/channels-3#user</channelId
>

                <default>true</default>

                <urlSuffix>default</urlSuffix>

            </channel>

            <module>

                <name>sp-saml</name>

                <order>1</order>

                <necessity>sufficient</necessity>

            </module>

        </sequence>

        <sequence>

            <name>admin-gui-emergency</name>

            <description>

                Special GUI authentication sequence that is using just
the internal user password.

                It is used only in emergency. It allows to skip SAML
authentication cycles, e.g. in case

                that the SAML authentication is redirecting the
browser incorrectly.

            </description>

            <channel>

                <channelId>
http://midpoint.evolveum.com/xml/ns/public/common/channels-3#user</channelId
>

                <default>false</default>

                <urlSuffix>emergency</urlSuffix>

            </channel>

            <requireAssignmentTarget oid=
"00000000-0000-0000-0000-000000000004" relation="org:default" type=
"c:RoleType">

                <!-- Superuser -->

            </requireAssignmentTarget>

            <module>

                <name>internalLoginForm</name>

                <order>1</order>

                <necessity>sufficient</necessity>

            </module>

        </sequence>

        <modules>

            <loginForm>

                <name>internalLoginForm</name>

                <description>
Internal username/password authentication, default user password, login form
</description>

            </loginForm>

            <saml2>

                <name>sp-saml</name>

                <description>SAML configuration</description>

                <network>

                    <readTimeout>10000</readTimeout>

                    <connectTimeout>5000</connectTimeout>

                </network>

                <serviceProvider>

                    <!-- URL to build SP metadata : https://
<midpoint-host>/midpoint/auth/default/sp-saml/metadata -->

                    <entityId>https://<midpoint-host>/midpoint</entityId>

                    <alias>idm</alias>

                    <aliasForPath>idm</aliasForPath>

                    <signRequests>false</signRequests>

                    <wantAssertionsSigned>false</wantAssertionsSigned>

                    <singleLogoutEnabled>true</singleLogoutEnabled>

                    <!-- <nameId>TRANSIENT</nameId> -->

                    <keys>

                        <activeSimpleKey>

                            <name>sp-signing-key</name>

                            <privateKey>

                                <clearValue>-----BEGIN PRIVATE KEY-----

MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD5FPVacrgJD04D

-----END PRIVATE KEY-----</clearValue>

                            </privateKey>

                            <passphrase>

                                <t:clearValue>password</t:clearValue>

                            </passphrase>

                            <certificate>

                                <clearValue>-----BEGIN CERTIFICATE-----

MIIELzCCAxegAwIBAgIUfjmGd9DOFSbI4ADNcUqDoooMSvUwDQYJKoZIhvcNAQEL

-----END CERTIFICATE-----</clearValue>

                            </certificate>

                        </activeSimpleKey>

                        <!-- <activeKeyStoreKey>


<keyStorePath>/opt/midpoint/var/samlKeystore.jks</keyStorePath>

                            <keyStorePassword>

                                <clearValue>password</clearValue>

                            </keyStorePassword>

                            <keyAlias>

                                <clearValue>sp-signing</clearValue>

                            </keyAlias>

                            <keyPassword>

                                <clearValue>password</clearValue>

                            </keyPassword>

                        </activeKeyStoreKey> -->

                    </keys>

                    <provider>

                        <entityId>https://<idp-host>/idp</entityId>

                        <alias>idp</alias>

                        <linkText>My IDP</linkText>

                        <metadata>

                            <pathToFile>/var/lib/midpoint/idp-metadata.xml</
pathToFile>

                        </metadata>

                        <metadataTrustCheck>false</metadataTrustCheck>

                        <skipSslValidation>true</skipSslValidation>

                        <authenticationRequestBinding>
urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect</
authenticationRequestBinding>

                        <nameOfUsernameAttribute>Login</
nameOfUsernameAttribute>

                    </provider>

                </serviceProvider>

            </saml2>

        </modules>

    </authentication>

</securityPolicy>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.evolveum.com/pipermail/midpoint/attachments/20210506/a5a572bb/attachment-0001.htm>


More information about the midPoint mailing list