Problemas comunes de la autenticación SAML
En esta página, encontrará una descripción general del Building Block Security Assertion Markup Language (SAML) 2.0, además de los problemas comunes relacionados con el inicio de sesión único (SSO) y las técnicas para la resolución de problemas del proveedor de la autenticación SAML.
Importante
Si por alguna razón se carga un archivo XML de metadatos de IdP nuevo o actualizado en la GUI de Blackboard en la página Configuración de autenticación SAML en la sección Configuración del proveedor de identidad para un proveedor de autenticación SAML, el SAML B2 y ese proveedor de autenticación SAML también deben alternarse Inactivo/Disponible, mientras que el proveedor de autenticación SAML está en estado "Activo", para garantizar que se borren los metadatos de IdP almacenados en caché y que los metadatos de IdP actualizados se utilicen por completo.
Términos clave
Son siguientes términos y abreviaturas se utilizan en toda esta guía:
SAML: Lenguaje de marcado de aserción de seguridad
IdP: Proveedor de identidad
SP: Proveedor de servicio
ADFS: Servicios de federación de Active Directory
GUI: Interfaz gráfica de usuario. En el contexto de Blackboard, esto significa trabajar dentro del software.
Editar los ajustes de configuración de SAML
Para ayudarlo a solucionar los problemas de la autenticación SAML, en la versión 3200.2.0 se actualizó el Building Block SAML, que ahora incluye estos ajustes y opciones de configuración:
Definir la duración límite de la sesión SAML
Elegir un tipo de algoritmo de firma
Regenerar los certificados
Cambiar el valor de ResponseSkew
Errores y excepciones
Los errores o excepciones relacionados con SAML se incluyen en estos registros:
/usr/local/blackboard/logs/bb-services-log.txt
/usr/local/blackboard/logs/tomcat/stdout-stderr-<date>.log
/usr/local/blackboard/logs/tomcat/catalina-log.txt
Cuando se investiga un problema de autenticación SAML informado siempre se deben consultar estos registros.
SAML Tracer
Con las iteraciones de solución de problemas de autenticación SAML 2.0, en algún punto puede ser necesario confirmar/ver los atributos que realmente se liberan del IdP y se envían a Blackboard durante el proceso de autenticación. Si los atributos del IdP NO están cifrados en la respuesta de SAML, puede utilizar el complemento SAML Tracer del navegador Firefox o SAML Message Decoder de Chrome para verlos.
Atributo no asignado correctamente
Si el atributo que contiene el userName no se asigna correctamente como se especifica en el campo ID de usuario remoto en la sección Asignar atributos SAML en la página Configuración de autenticación SAML en la GUI de Bb, se registrará el siguiente evento en el registro bb-servicios al intentar iniciar sesión en Bb a través de la autenticación SAML:
2016-06-28 12:48:12 -0400 - userName is null or empty
Un Error de inicio de sesión! mensaje que se muestra en el navegador: Blackboard actualmente no puede iniciar sesión en su cuenta mediante el inicio de sesión único. Póngase en contacto con su administrador para obtener ayuda.

Se mostrará una entrada de Error de autenticación en el registro bb-services:
2016-06-28 12:48:12 -0400 - BbSAMLExceptionHandleFilter - javax.servlet.ServletException: Authentication Failure
at blackboard.auth.provider.saml.customization.handler.BbAuthenticationSuccessHandler.checkAuthenticationResult(BbAuthenticationSuccessHandler.java:81)
at blackboard.auth.provider.saml.customization.handler.BbAuthenticationSuccessHandler.onAuthenticationSuccess(BbAuthenticationSuccessHandler.java:57)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.successfulAuthentication(AbstractAuthenticationProcessingFilter.java:331)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:245)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
[SNIP]Hay dos opciones para solucionar el problema. En primer lugar, seleccione la opción Crear cuentas si no existen en el sistema en la página Configuración de autenticación SAML en la GUI de Blackboard. O bien, puede intentar ver el valor de los atributos publicados por el IdP mediante SAML Tracer o el registro de depuración si estos atributos NO están cifrados:
<saml2:Attribute Name="urn:oid:0.9.2342.19200300.100.1.3">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="xs:anyType"
>bbuser_saml2@bbchjones.net</saml2:AttributeValue>
</saml2:Attribute>y asigne el Nombre de atributo que tiene el AttributeValue deseado al ID de usuario remoto en la página Configuración de autenticación SAML en la GUI de Blackboard.
Origen de datos compatible no seleccionado
Los usuarios no podrán iniciar sesión en Blackboard a través de la autenticación SAML si la Fuente de datos para los usuarios no está seleccionada en la sección Configuración del proveedor de servicio > fuentes de datos compatibles en la página Configuración de autenticación SAML en la GUI de Blackboard. El siguiente evento se registrará en el registro de Bb-servicios al intentar iniciar sesión en Blackboard a través de la autenticación SAML:
2016-09-23 12:33:13 -0500 - userName is null or empty
Aparecerá el mensaje Error de inicio de sesión en el navegador, al igual que el Error de autenticación en el registro bb-services:
2016-09-23 12:33:13 -0500 - BbSAMLExceptionHandleFilter - javax.servlet.ServletException: Authentication Failure
at blackboard.auth.provider.saml.customization.handler.BbAuthenticationSuccessHandler.checkAuthenticationResult(BbAuthenticationSuccessHandler.java:82)
at blackboard.auth.provider.saml.customization.handler.BbAuthenticationSuccessHandler.onAuthenticationSuccess(BbAuthenticationSuccessHandler.java:58)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.successfulAuthentication(AbstractAuthenticationProcessingFilter.java:331)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:245)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter (SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at sun.reflect.GeneratedMethodAccessor3399.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
[SNIP]Obtenga el nombre de usuario del usuario que no puede iniciar la sesión.
En la GUI de Blackboard, vaya a Administrador del sistema > usuarios y busque el usuario.
Copie la Clave del origen de datos del usuario.
Vaya a Administrador del sistema > Autenticación > "nombre del proveedor" > Configuración de SAML > Orígenes de datos compatibles.
Coloque una marca junto a Origen de datos en la columna Nombre y haga clic en Enviar.
Mensaje de error "La URL proporcionada tiene un formato incorrecto"
Si OneLogin está configurado como el IdP para el proveedor de autenticación SAML en Blackboard, es posible que se muestre un error La URL dada no está bien formada en la página después de ingresar las credenciales de OneLogin al intentar iniciar sesión en Blackboard.
Se mostrará lo siguiente en el registro bb-services:
2016-09-16 09:43:40 -0400 - Given URL is not well formed<P><span class="captionText">For reference, the Error ID is 17500f44-7809-4b9f-a272-3bed1d1af131.</span> - java.lang.IllegalArgumentException: Given URL is not well formed
at org.opensaml.util.URLBuilder.<init>(URLBuilder.java:120)
at org.opensaml.util.SimpleURLCanonicalizer.canonicalize(SimpleURLCanonicalizer.java:87)
at org.opensaml.common.binding.decoding.BasicURLComparator.compare(BasicURLComparator.java:57)
at org.opensaml.common.binding.decoding.BaseSAMLMessageDecoder.compareEndpointURIs(BaseSAMLMessageDecoder.java:173)
at org.opensaml.common.binding.decoding.BaseSAMLMessageDecoder.checkEndpointURI(BaseSAMLMessageDecoder.java:213)
at org.opensaml.saml2.binding.decoding.BaseSAML2MessageDecoder.decode(BaseSAML2MessageDecoder.java:72)
at org.springframework.security.saml.processor.SAMLProcessorImpl.retrieveMessage(SAMLProcessorImpl.java:105)
at org.springframework.security.saml.processor.SAMLProcessorImpl.retrieveMessage(SAMLProcessorImpl.java:172)
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:80)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
[SNIP]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.MalformedURLException: no protocol: {recipient}
at java.net.URL.<init>(URL.java:593)
at java.net.URL.<init>(URL.java:490)
at java.net.URL.<init>(URL.java:439)
at org.opensaml.util.URLBuilder.<init>(URLBuilder.java:77)
... 203 moreActive el complemento SAML Tracer del navegador Firefox y replique el problema del inicio de sesión.
Revise el comienzo del evento SAML POST:
<samlp:Response Destination="{recipient}" ID="R8afbfbfee7292613f98ad4ec4115de7c6b385be6" InResponseTo="a3g2424154bb0gjh3737ii66dadbff4" IssueInstant="2016-09-16T18:49:09Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" > <saml:Issuer>https://app.onelogin.com/saml/metadata/123456</saml:Issuer> [SNIP]En la primera línea de la respuesta, observe que el campo Destination= está establecido solo para el destinatario.
Haga que el cliente vaya a la sección Configuración de su IdP de OneLogin.
Confirme que el campo Destinatario esté en blanco.
Copie el valor de la URL de ACS (Consumidor), péguelo en el campo Destinatario y haga clic en Guardar.
Posibles problemas del IdP/SP
Si se produce un error antes que usted sea redirigido a la página de inicio de sesión del IdP, es posible que los metadatos del IdP no sean válidos.
Si en cambio el error se produce después de que usted inicia sesión en la página del IdP, estos podrían ser los motivos:
La asignación de los atributos entre el SP y el IdP no es correcta o el IdP no devolvió una ID del usuario remoto válida.
El SP no validó la respuesta de SAML del IdP. Esto podría deberse a lo siguiente:
El IdP firma la respuesta de SAML con un certificado que no fue emitido por una autoridad válida, y este certificado no está incluido en el almacén de claves del SP.
El reloj del sistema del SP no es correcto.
Active Directory Federation Services (ADFS)
Los nombres de los atributos distinguen entre mayúsculas y minúsculas en la sección Asignar atributos SAML en la página Configuración de autenticación SAML en la GUI de Blackboard. Por lo tanto, si el ID de usuario remoto tiene sAMAccountName para el Nombre de atributo en la página de configuración y el POST SAML real del IdP tiene esto para el Nombre de atributo en la AttributeStatement:
<AttributeStatement>
<Attribute Name="SamAccountName>
<AttributeValue>Test-User</AttributeValue>
</Attribute>
</AttributeStatement>El usuario no podrá iniciar sesión. El valor del nombre del atributo ID de usuario remoto de la página Configuración de autenticación SAML debería cambiarse de sAMAccountName a SamAccountName.
Esta sección contiene algunos de los problemas comunes que pueden impedir que un usuario inicie sesión en Blackboard a través de la autenticación SAML con ADFS cuando No se encontró el recurso especificado o no tiene permiso para acceder a él o Error de inicio de sesión! mensaje se muestra en la GUI de Blackboard.
Después de introducir las credenciales de inicio de sesión en la página de inicio de sesión de ADFS, es posible que se muestre un error después de ser redirigido a la GUI de Blackboard: No se encontró el recurso especificado o no tiene permiso para acceder a él.

El error aparece junto a un mensaje correspondiente en el registro stdout-stderr:
INFO | jvm 1 | 2016/06/22 06:08:33 | - No mapping found for HTTP request with URI [/auth-saml/saml/SSO] in DispatcherServlet with name 'saml'
El problema se produce porque se utiliza el método noHandlerFound() en el código DispatcherServlet.java y no es posible ubicar o asignar la solicitud HTTP SSO.
/**
* No handler found -> set appropriate HTTP response status.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception if preparing the response failed
*/
protected void noHandlerFound(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (pageNotFoundLogger.isWarnEnabled()) {
pageNotFoundLogger.warn("No mapping found for HTTP request with URI [" + getRequestUri(request) +
"] in DispatcherServlet with name '" + getServletName() + "'");
}
if (this.throwExceptionIfNoHandlerFound) {
throw new NoHandlerFoundException(request.getMethod(), getRequestUri(request),
new ServletServerHttpRequest(request).getHeaders());
}
else {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}Esto suele ocurrir porque el ID de entidad para el SP configurado en la GUI de Blackboard es incorrecto. Para resolver este problema, vaya a Administrador del sistema > Autenticación > Configuración de autenticación de SAML > Configuración de proveedor de servicios y actualice el ID de entidad. Para ADFS, la configuración predeterminada para el ID de entidad sería https://[Blackboard Server Hostname]/auth-saml/saml/SSO o inicio de sesión único.
Nota
Si un instituto cambia su URL de la https://school.blackboard.com predeterminada a https://their.school.edu, el ID de entidad en la GUI de Blackboard en la página Configuración de autenticación SAML debe actualizarse a https://their.school.edu/auth-saml/saml/SSO o inicio de sesión único.
Después de introducir las credenciales de inicio de sesión en la página de inicio de sesión de ADFS, es posible que se muestre un error después de ser redirigido a la GUI de Blackboard: No se encontró el recurso especificado o no tiene permiso para acceder a él.
El error aparece junto a un mensaje correspondiente en el registro stdout-stderr:
INFO | jvm 1 | 2016/06/22 06:08:33 | - No mapping found for HTTP request with URI [/auth-saml/saml/SSO] in DispatcherServlet with name 'saml'
Además, se muestra este mensaje en el registro catalina:
ERROR 2016-06-27 10:47:03,664 connector-6: userId=_2_1, sessionId=62536416FB80462298C92064A7022E50 org.opensaml.xml.encryption.Decrypter - Error decrypting the encrypted data element
org.apache.xml.security.encryption.XMLEncryptionException: Illegal key size
Original Exception was java.security.InvalidKeyException: Illegal key size
at org.apache.xml.security.encryption.XMLCipher.decryptToByteArray(XMLCipher.java:1822)
at org.opensaml.xml.encryption.Decrypter.decryptDataToDOM(Decrypter.java:596)
at org.opensaml.xml.encryption.Decrypter.decryptUsingResolvedEncryptedKey(Decrypter.java:795)
at org.opensaml.xml.encryption.Decrypter.decryptDataToDOM(Decrypter.java:535)
at org.opensaml.xml.encryption.Decrypter.decryptDataToList(Decrypter.java:453)
at org.opensaml.xml.encryption.Decrypter.decryptData(Decrypter.java:414)
at org.opensaml.saml2.encryption.Decrypter.decryptData(Decrypter.java:141)
at org.opensaml.saml2.encryption.Decrypter.decrypt(Decrypter.java:69)
at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:199)
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:82)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167)
[SNIP]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.security.InvalidKeyException: Illegal key size
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)
at javax.crypto.Cipher.init(Cipher.java:1393)
at javax.crypto.Cipher.init(Cipher.java:1327)
at org.apache.xml.security.encryption.XMLCipher.decryptToByteArray(XMLCipher.java:1820)
... 205 moreJunto a este mensaje en el registro bb-services:
2016-06-27 10:47:03 -0400 - unsuccessfulAuthentication - org.springframework.security.authentication.AuthenticationServiceException: Error validating SAML message
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:100)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167)
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:87)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at sun.reflect.GeneratedMethodAccessor3422.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:277)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:274)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAsPrivileged(Subject.java:549)
at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:309)
at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:249)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:55)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:191)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:187)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:186)
at blackboard.auth.provider.saml.customization.filter.BbSAMLExceptionHandleFilter.doFilterInternal(BbSAMLExceptionHandleFilter.java:30)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at sun.reflect.GeneratedMethodAccessor3421.invoke(Unknown Source)
[SNIP]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.opensaml.common.SAMLException: Response doesn't have any valid assertion which would pass subject validation
at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:229)
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:87)
... 229 moreEl problema se produce porque, de forma predeterminada, ADFS cifra los atributos que envía mediante AES-256 y el tiempo de ejecución de Java utilizado por Blackboard no es compatible con AES-256 listo para usar.
Una opción de resolución universal es abrir un PowerShell en el servidor ADFS y configurar el usuario de confianza creado para Blackboard para que envíe los atributos como sin cifrar. Dado que toda la comunicación se realiza a través de SSL, no afectará la seguridad de la autenticación. También facilita la depuración de cualquier problema, ya que los atributos se pueden ver mediante herramientas de depuración como el complemento de seguimiento SAML del navegador Firefox y no es necesario reiniciar el sistema Blackboard. Para configurar el usuario de confianza creado para Blackboard para que envíe los atributos como sin cifrar, abra un PowerShell y ejecute el siguiente comando, reemplazando TargetName por el nombre de la Confianza de usuario de confianza que se encuentra en la consola de administración de ADFS en Relaciones de confianza > Confianzas de usuario de confianza.
set-ADFSRelyingPartyTrust –TargetName "yourlearnserver.blackboard.com" –EncryptClaims $False
Después de este cambio, el servicio ADFS deberá reiniciarse con el comando: Restart-Service ADFSSRV
Después de ingresar las credenciales de inicio de sesión en la página de inicio de sesión de ADFS, es posible que se muestre un error después de ser redirigido a la GUI de Blackboard: No se encontró el recurso especificado o no tiene permiso para acceder a él o ¡Error de inicio de sesión!
En ambos casos, aparecen estos eventos relacionados de SAML similares en el registro stdout-stderr:
INFO | jvm 1 | 2016/09/06 20:33:04 | - /saml/login?apId=_107_1&redirectUrl=https%3A%2F%2Fbb.fraser.misd.net%2Fwebapps%2Fportal%2Fexecute%2FdefaultTab at position 1 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' INFO | jvm 1 | 2016/09/06 20:33:04 | - No HttpSession currently exists INFO | jvm 1 | 2016/09/06 20:33:04 | - No SecurityContext was available from the HttpSession: null. A new one will be created. INFO | jvm 1 | 2016/09/06 20:33:04 | - /saml/login?apId=_107_1&redirectUrl=https%3A%2F%2Fbb.fraser.misd.net%2Fwebapps%2Fportal%2Fexecute%2FdefaultTab at position 2 of 10 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' INFO | jvm 1 | 2016/09/06 20:33:04 | - /saml/login?apId=_107_1&redirectUrl=https%3A%2F%2Fbb.fraser.misd.net%2Fwebapps%2Fportal%2Fexecute%2FdefaultTab at position 3 of 10 in additional filter chain; firing Filter: 'HeaderWriterFilter' INFO | jvm 1 | 2016/09/06 20:33:04 | - /saml/login?apId=_107_1&redirectUrl=https%3A%2F%2Fbb.fraser.misd.net%2Fwebapps%2Fportal%2Fexecute%2FdefaultTab at position 4 of 10 in additional filter chain; firing Filter: 'FilterChainProxy' INFO | jvm 1 | 2016/09/06 20:33:04 | - Checking match of request : '/saml/login'; against '/saml/login/**' INFO | jvm 1 | 2016/09/06 20:33:04 | - /saml/login?apId=_107_1&redirectUrl=https%3A%2F%2Fbb.fraser.misd.net%2Fwebapps%2Fportal%2Fexecute%2FdefaultTab at position 1 of 1 in additional filter chain; firing Filter: 'SAMLEntryPoint' INFO | jvm 1 | 2016/09/06 20:33:04 | - Request for URI http://www.w3.org/2000/09/xmldsig#rsa-sha1 INFO | jvm 1 | 2016/09/06 20:33:04 | - Request for URI http://www.w3.org/2000/09/xmldsig#rsa-sha1 INFO | jvm 1 | 2016/09/06 20:33:04 | - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession. INFO | jvm 1 | 2016/09/06 20:33:04 | - SecurityContextHolder now cleared, as request processing completed INFO | jvm 1 | 2016/09/06 20:33:07 | - /saml/SSO at position 1 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' INFO | jvm 1 | 2016/09/06 20:33:07 | - HttpSession returned null object for SPRING_SECURITY_CONTEXT INFO | jvm 1 | 2016/09/06 20:33:07 | - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@6708a718. A new one will be created. INFO | jvm 1 | 2016/09/06 20:33:07 | - /saml/SSO at position 2 of 10 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' INFO | jvm 1 | 2016/09/06 20:33:07 | - /saml/SSO at position 3 of 10 in additional filter chain; firing Filter: 'HeaderWriterFilter' INFO | jvm 1 | 2016/09/06 20:33:07 | - /saml/SSO at position 4 of 10 in additional filter chain; firing Filter: 'FilterChainProxy' INFO | jvm 1 | 2016/09/06 20:33:07 | - Checking match of request : '/saml/sso'; against '/saml/login/**' INFO | jvm 1 | 2016/09/06 20:33:07 | - Checking match of request : '/saml/sso'; against '/saml/logout/**' INFO | jvm 1 | 2016/09/06 20:33:07 | - Checking match of request : '/saml/sso'; against '/saml/bbsamllogout/**' INFO | jvm 1 | 2016/09/06 20:33:07 | - Checking match of request : '/saml/sso'; against '/saml/sso/**' INFO | jvm 1 | 2016/09/06 20:33:07 | - /saml/SSO at position 1 of 1 in additional filter chain; firing Filter: 'SAMLProcessingFilter' INFO | jvm 1 | 2016/09/06 20:33:07 | - Authentication attempt using org.springframework.security.saml.SAMLAuthenticationProvider INFO | jvm 1 | 2016/09/06 20:33:07 | - Forwarding to / INFO | jvm 1 | 2016/09/06 20:33:07 | - DispatcherServlet with name 'saml' processing POST request for [/auth-saml/saml/SSO] INFO | jvm 1 | 2016/09/06 20:33:07 | - No mapping found for HTTP request with URI [/auth-saml/saml/SSO] in DispatcherServlet with name 'saml' INFO | jvm 1 | 2016/09/06 20:33:07 | - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession. INFO | jvm 1 | 2016/09/06 20:33:07 | - Successfully completed request INFO | jvm 1 | 2016/09/06 20:33:07 | - Skip invoking on INFO | jvm 1 | 2016/09/06 20:33:07 | - SecurityContextHolder now cleared, as request processing completed
O bien, estas excepciones de SAML similares en el registro bb-services:
2016-11-29 09:04:24 -0500 - unsuccessfulAuthentication - org.springframework.security.authentication.AuthenticationServiceException: Error validating SAML message
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:100)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167)
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:87)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at sun.reflect.GeneratedMethodAccessor853.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:282)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:279)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAsPrivileged(Subject.java:549)
at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:314)
at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:253)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)
at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:46)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:148)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:144)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:143)
at blackboard.auth.provider.saml.customization.filter.BbSAMLExceptionHandleFilter.doFilterInternal(BbSAMLExceptionHandleFilter.java:30)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at sun.reflect.GeneratedMethodAccessor853.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[SNIP]
at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:677)
at blackboard.tomcat.valves.LoggingRemoteIpValve.invoke(LoggingRemoteIpValve.java:44)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:1110)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:785)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1425)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.opensaml.common.SAMLException: Response issue time is either too old or with date in the future, skew 60, time 2016-11-29T14:03:16.634Z
at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:126)
at blackboard.auth.provider.saml.customization.consumer.BbSAMLWebSSOProfileConsumerImpl.processAuthenticationResponse(BbSAMLWebSSOProfileConsumerImpl.java:40)
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:87)
... 230 moreEl problema se produce cuando el servidor ADFS y el servidor de la aplicación Blackboard tienen un desfase de tiempo cercano o superior al valor predeterminado de 60 segundos.
Hay dos opciones para solucionar el problema:
Sincronización manual de los relojes de los servidores de la aplicación Blackboard y del servidor ADFS. Para Blackboard, la hora actual y la zona horaria del servidor se pueden ver en un navegador web agregando
/webapps/portal/healthCheckal final de una URL de Blackboard.Ejemplo: https://mhtest1.blackboard.com//webapps/portal/healthCheck
Hostname: ip-10-145-49-11.ec2.internal Status: Active - Database connectivity established Running since: Sat, Dec 3, 2016 - 05:39:11 PM EST Time of request: Thu, Dec 8, 2016 - 05:12:43 PM EST
Nota
Una institución puede usar la URL anterior para comparar la zona horaria y el reloj del sistema Blackboard con los de su servidor ADFS y, a continuación, ajustar esos elementos según sea necesario en el servidor ADFS para que estén sincronizados con el sitio de Blackboard.
Después de ingresar las credenciales de inicio de sesión en la página de inicio de sesión de ADFS, es posible que se muestre un error después de ser redirigido a la GUI de Blackboard: No se encontró el recurso especificado o no tiene permiso para acceder a él o ¡Error de inicio de sesión!
Se mostrarán las excepciones siguientes en el registro bb-services:
2016-11-01 12:47:19 -0500 - unsuccessfulAuthentication - org.springframework.security.authentication.AuthenticationServiceException: Error validating SAML message
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:100)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167)
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:87)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at sun.reflect.GeneratedMethodAccessor929.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:282)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:279)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAsPrivileged(Subject.java:549)
at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:314)
at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:253)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)
at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:46)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:148)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:144)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:143)
at blackboard.auth.provider.saml.customization.filter.BbSAMLExceptionHandleFilter.doFilterInternal(BbSAMLExceptionHandleFilter.java:30)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
[SNIP]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.opensaml.common.SAMLException: Response has invalid status code urn:oasis:names:tc:SAML:2.0:status:Responder, status message is null
at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:113)
at blackboard.auth.provider.saml.customization.consumer.BbSAMLWebSSOProfileConsumerImpl.processAuthenticationResponse(BbSAMLWebSSOProfileConsumerImpl.java:40)
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:87)
... 230 more
2016-11-01 12:47:19 -0500 - BbSAMLExceptionHandleFilter - javax.servlet.ServletException: Unsuccessful Authentication
at blackboard.auth.provider.saml.customization.filter.BbSAMLProcessingFilter.unsuccessfulAuthentication(BbSAMLProcessingFilter.java:31)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:235)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at sun.reflect.GeneratedMethodAccessor929.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:282)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:279)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAsPrivileged(Subject.java:549)
at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:314)
at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:253)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)
at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:46)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:148)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:144)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:143)
at blackboard.auth.provider.saml.customization.filter.BbSAMLExceptionHandleFilter.doFilterInternal(BbSAMLExceptionHandleFilter.java:30)
[SNIP]Vaya al Panel del administrador.
En la sección Integraciones, seleccione Building Blocks.
Seleccione Herramientas instaladas .
Busque la opción Proveedor de la autenticación: SAML en la lista. Abra el menú y seleccione Ajustes.
En Configuración del algoritmo de firma, elija SHA-256 en la lista. Después de seleccionar la opción Tipo de algoritmo de firma, reinicie el Building Block SAML para que se apliquen los nuevos ajustes.
Seleccione Enviar para guardar los cambios.
Después de ingresar las credenciales de inicio de sesión en la página de inicio de sesión de ADFS, es posible que se muestre un error después de ser redirigido a la GUI de Blackboard: No se encontró el recurso especificado o no tiene permiso para acceder a él o ¡Error de inicio de sesión!
Se mostrarán las excepciones siguientes en el registro bb-services:
2017-01-04 22:52:58 -0700 - unsuccessfulAuthentication - org.springframework.security.authentication.AuthenticationServiceException: Error validating SAML message
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:100)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167)
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:87)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at sun.reflect.GeneratedMethodAccessor935.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:282)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:279)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAsPrivileged(Subject.java:549)
at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:314)
at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:253)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)
at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:46)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:148)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:144)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:143)
at blackboard.auth.provider.saml.customization.filter.BbSAMLExceptionHandleFilter.doFilterInternal(BbSAMLExceptionHandleFilter.java:30)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
[SNIP]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.opensaml.common.SAMLException: NameID element must be present as part of the Subject in the Response message, please enable it in the IDP configuration
at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:252)
at blackboard.auth.provider.saml.customization.consumer.BbSAMLWebSSOProfileConsumerImpl.processAuthenticationResponse(BbSAMLWebSSOProfileConsumerImpl.java:40)
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:87)
... 214 moreTal como se indicó en la excepción de SAML anterior, falta el elemento NameID en el Asunto del mensaje de la Respuesta. El problema se produce comúnmente cuando el elemento NameID no está establecido como un Tipo de notificación saliente en una Regla de notificaciones para la Relación de confianza para usuario autenticado en el IdP de ADFS de la institución o la Regla de notificaciones para NameID no está en el orden correcto para la Relación de confianza para usuario autenticado en el IdP de ADFS de la institución, que a su vez hace que el elemento NameID falte en el Asunto del mensaje de la respuesta.
<Subject>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData InResponseTo="a22ai8iig0f75ae22hd28748b12da50"
NotOnOrAfter="2017-01-03T05:57:58.234Z"
Recipient="https://yourschool.blackboard.com/auth-saml/saml/SSO"
/>
</SubjectConfirmation>
</Subject><Subject>
<NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">testadfs</NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData InResponseTo="a5903d39if463ea87ieiab5135j9ji"
NotOnOrAfter="2017-01-05T04:33:12.715Z"
Recipient="https://yourschool.blackboard.com/auth-saml/saml/SSO"
/>
</SubjectConfirmation>
</Subject>Nota
Puede usar el complemento SAML Tracer de Firefox para ver el Asunto en el mensaje de la Respuesta.
Hay tres métodos para solucionas este problema.
Confirme que se hayan seguido correctamente los pasos de la Guía de configuración de SAML B2 para ADFS y haga los cambios necesarios para transformar una notificación entrante para la Relación de confianza para usuario autenticado del IdP de ADFS:
Seleccione Editar las reglas de notificaciones.
Elija Agregar regla.
En la página Seleccionar una plantilla para la regla, elija la opción Transformar una notificación entrante para la plantilla de la regla de notificaciones y seleccione Siguiente.
En la página Configurar la regla, en el campo Nombre de la regla de notificaciones, escriba Transformar el correo electrónico en la ID del nombre.
El tipo notificación entrante debe ser SamAccountName (debe coincidir con el Tipo de notificación saliente que se creó inicialmente en la regla Transformar el nombre de usuario en la ID del nombre).
El Tipo de notificación saliente es la ID del nombre.
El formato de la ID del nombre saliente es el correo electrónico.
Confirme que se haya seleccionado Aplicar a todos los valores de notificaciones y seleccione Finalizar.
Seleccione Aceptar para guardar la regla y, nuevamente, Aceptar para completar las asignaciones de los atributos.
En lo que respecta al orden de las Reglas de notificaciones utilizadas para el IdP de ADFS, asegúrese de que no haya reglas opcionales que se ejecuten antes de la regla que contiene el elemento NameID.
Si usa un atributo personalizado, asegúrese de que el elemento NameID esté en la Confianza del usuario de confianza ya que Blackboard aún espera que su IdP de ADFS publique un valor NameID.
Cuando inicia sesión en Blackboard a través de la autenticación SAML, el usuario intenta cerrar sesión haciendo clic en el botón Cerrar sesión en el lado izquierdo de la página y luego hace clic en el botón Finalizar sesión de SSO o inicio de sesión único un Error de inicio de sesión! se muestra inmediatamente.
Sign On Error! Blackboard Learn is currently unable to log into your account using single sign-on. Contact your administrator for assistance. For reference, the Error ID is [error ID].
Se mostrará la excepción siguiente en el registro bb-services:
2017-05-08 15:10:46 -0400 - BbSAMLExceptionHandleFilter Error Id: f3299757-8d4e-4fab-98cf-49cd99f4891e - javax.servlet.ServletException: Incoming SAML message failed security validation
at org.springframework.security.saml.SAMLLogoutProcessingFilter.processLogout(SAMLLogoutProcessingFilter.java:145)
at org.springframework.security.saml.SAMLLogoutProcessingFilter.doFilter(SAMLLogoutProcessingFilter.java:104)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
[SNIP]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.opensaml.ws.security.SecurityPolicyException: Validation of request simple signature failed for context issuer
at org.opensaml.common.binding.security.BaseSAMLSimpleSignatureSecurityPolicyRule.doEvaluate(BaseSAMLSimpleSignatureSecurityPolicyRule.java:139)
at org.opensaml.common.binding.security.BaseSAMLSimpleSignatureSecurityPolicyRule.evaluate(BaseSAMLSimpleSignatureSecurityPolicyRule.java:103)
at org.opensaml.ws.security.provider.BasicSecurityPolicy.evaluate(BasicSecurityPolicy.java:51)
at org.opensaml.ws.message.decoder.BaseMessageDecoder.processSecurityPolicy(BaseMessageDecoder.java:132)
at org.opensaml.ws.message.decoder.BaseMessageDecoder.decode(BaseMessageDecoder.java:83)
at org.opensaml.saml2.binding.decoding.BaseSAML2MessageDecoder.decode(BaseSAML2MessageDecoder.java:70)
at org.springframework.security.saml.processor.SAMLProcessorImpl.retrieveMessage(SAMLProcessorImpl.java:105)
at org.springframework.security.saml.processor.SAMLProcessorImpl.retrieveMessage(SAMLProcessorImpl.java:172)
at org.springframework.security.saml.SAMLLogoutProcessingFilter.processLogout(SAMLLogoutProcessingFilter.java:131)
... 244 moreEl error se produce debido a la configuración del Tipo de servicio del cierre de sesión único en la página Ajustes de SAML.
La configuración debe configurarse en Blackboard y en el servidor ADFS.
Para ADFS como IdP, seleccione solo la configuración Publicar y elimine el punto de enlace de redireccionamiento para la confianza del usuario de confianza de la instancia de Blackboard en el servidor ADFS.
En Blackboard, vaya a Admin > Authentication > (Nombre del proveedor) > Configuración de SAML > Tipo de servicio de cierre de sesión único.
Seleccione Publicación y quite la marca de la casilla de verificación Redirigir.
En el servidor ADFS, vaya a la confianza del usuario de confianza para su instancia de Blackboard.
Seleccione Propiedades > Extremos. Figuran dos extremos de cierre de sesión de SAML.
Elimine el extremo Redireccionamiento. Seleccione Eliminar extremo para quitarlo y, luego, haga clic en Aplicar y Aceptar.
Después de realizar los cambios anteriores en Blackboard y el servidor ADFS, el botón de cierre de sesión Finalizar sesión de SSO o inicio de sesión único funcionará para cerrar la sesión del usuario correctamente.
Después de escribir las credenciales de inicio de sesión en la página de inicio de sesión de ADFS, aparece un error Iniciar sesión! se muestra cuando se redirige a Blackboard.
Se mostrará la excepción siguiente de SAML en el registro bb-services:
2017-05-26 07:39:30 -0400 - unsuccessfulAuthentication - org.springframework.security.authentication.AuthenticationServiceException: Error validating SAML message
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:100)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167)
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:87)
at blackboard.auth.provider.saml.customization.filter.BbSAMLProcessingFilter.attemptAuthentication(BbSAMLProcessingFilter.java:46)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at sun.reflect.GeneratedMethodAccessor380.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:282)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:279)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAsPrivileged(Subject.java:549)
at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:314)
at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:253)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)
at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:46)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:148)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:144)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:143)
at blackboard.auth.provider.saml.customization.filter.BbSAMLExceptionHandleFilter.doFilterInternal(BbSAMLExceptionHandleFilter.java:37)
[SNIP]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.opensaml.common.SAMLException: Response has invalid status code urn:oasis:names:tc:SAML:2.0:status:Responder, status message is null
at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:113)
at blackboard.auth.provider.saml.customization.consumer.BbSAMLWebSSOProfileConsumerImpl.processAuthenticationResponse(BbSAMLWebSSOProfileConsumerImpl.java:56)
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:87)
... 247 moreHay una opción para regenerar el certificado de cifrado SAML navegando a Administrador del sistema > Bloque de creación > Proveedor de autenticación: Configuración de > SAML > Regenerar certificado. El problema del Error de inicio de sesión puede ocurrir si el usuario hace clic en el botón Volver a generar el certificado después de que los metadatos de SP ya se hayan cargado a la Relación de confianza para usuario autenticado para el sitio de Blackboard en el servidor de ADFS. Para solucionar el problema:
Vaya a Administrador del sistema > Autenticación > [nombre del proveedor de SAML] > Configuración de SAML.
Elija la opción Generar junto a los metadatos del proveedor de servicios para guardar el archivo nuevo de metadatos.
Acceda a su servidor ADFS y cargue los nuevos metadatos de SP en la confianza de usuario de confianza para su sitio de Blackboard.
Nota
Si genera un certificado nuevo con la configuración de B2, debe alternar SAML B2 entre Inactivo y Activo para forzar el cambio. Luego, puede volver a la configuración del proveedor y generar los metadatos nuevos para importarlos al IdP. Si no alterna la configuración, es posible que aún se incluya el certificado anterior al generar metadatos nuevos. El IDP no se actualizará y la próxima vez que Blackboard se reinicie, presentará el nuevo certificado. La autenticación de SAML se interrumpirá debido a esta discrepancia.
Con los Servicios de federación de Active Directory (ADFS), dado que los metadatos de una federación de ADFS que normalmente se encuentran en https://[ADFS Server Hostname]/FederationMetadata/2007-06/FederationMetadata.xml incluyen un elemento que es incompatible con SAML 2.0, los metadatos deben editarse para eliminar el elemento incompatible antes de la carga en la sección Configuración del proveedor de identidad en la página Configuración de autenticación de SAML en la GUI de Blackboard. Si se cargan los metadatos con el elemento incompatible, se producirá un error al seleccionar el enlace de inicio de sesión SAML en la página de inicio de sesión de Blackboard: No se encontraron los metadatos de la entidad [entidad] y el rol {}. Para su referencia, la Id. del error es [ID del error].
Y el seguimiento de la pila de Java correspondiente para la ID del error en el registro bb-services es el siguiente:
2016-06-21 11:42:51 -0700 - Metadata for entity https://<Learn Server Hostname>/adfs/ls/ and role {urn:oasis:names:tc:SAML:2.0:metadata}SPSSODescriptor wasn't found<P><span class="captionText">For reference, the Error ID is c99511ae-1162-4941-b823-3dda19fea157.</span> - org.opensaml.saml2.metadata.provider.MetadataProviderException: Metadata for entity https://ulvsso.laverne.edu/adfs/ls/ and role {urn:oasis:names:tc:SAML:2.0:metadata}SPSSODescriptor wasn't found
at org.springframework.security.saml.context.SAMLContextProviderImpl.populateLocalEntity(SAMLContextProviderImpl.java:319)
at org.springframework.security.saml.context.SAMLContextProviderImpl.populateLocalContext(SAMLContextProviderImpl.java:216)
at org.springframework.security.saml.context.SAMLContextProviderImpl.getLocalAndPeerEntity(SAMLContextProviderImpl.java:126)
at org.springframework.security.saml.SAMLEntryPoint.commence(SAMLEntryPoint.java:146)
at org.springframework.security.saml.SAMLEntryPoint.doFilter(SAMLEntryPoint.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at sun.reflect.GeneratedMethodAccessor1652.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
[SNIP]Dado que la ubicación de metadatos predeterminada para una federación de ADFS es https://[ADFS server hostname]/FederationMetadata/2007-06/FederationMetadata.xml:
Descargue el archivo y ábralo en el editor de texto. Elimine con cuidado la sección que comienza
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> ... </X509Data></KeyInfo>and ending</ds:Signature><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> <ds:Reference URI="#_43879f32-9a91-4862-bc87-e98b85b51158"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> <ds:DigestValue>z1H1[SNIP]jaYM=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue> FVj[SNIP]edrfNKWvsvk5A== </ds:SignatureValue> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <X509Data> <X509Certificate> FDdd[SNIP]qTNKdk5F/vf1AocDaX </X509Certificate> </X509Data> </KeyInfo> </ds:Signature>Cargue el archivo XML de metadatos actualizado en la GUI de Blackboard en la página Configuración de autenticación SAML en la sección Configuración del proveedor de identidad
Alterne el proveedor de autenticación SAML y SAML B2 entre Inactivo y Disponible mientras el proveedor de autenticación SAML se encuentra "Activo".
Importante
Si una institución está probando la autenticación SAML en un sitio de Blackboard y tiene varios proveedores de autenticación SAML que comparten el mismo archivo XML de metadatos de ADFS IdP subyacente en el sitio de Blackboard, incluso si los otros proveedores de autenticación SAML están configurados como Inactivos, también deberán cargar el archivo XML de metadatos actualizado en la GUI de Blackboard en la página Configuración de autenticación SAML en la sección Configuración del proveedor de identidad. Luego, se deberá alternar SAML B2 entre Inactivo y Disponible, mientras el proveedor de autenticación SAML se encuentra en estado "Activo", para garantizar que todo el sistema reconozca el archivo XML de metadatos actualizado.
Después de ingresar las credenciales de inicio de sesión en la página de inicio de sesión de ADFS, el usuario es redirigido a la GUI de Blackboard, pero no ha iniciado sesión en Blackboard.
El ÚNICO evento relacionado con la autenticación SAML en el registro bb-services es el siguiente:
2016-10-18 13:03:28 -0600 - userName is null or empty
Inicie sesión en Blackboard como administrador con la autenticación interna predeterminada de Blackboard.
Vaya a Administrador del sistema > "nombre del proveedor de la autenticación SAML" > Editar.
Cambie el Método de búsqueda de usuarios de UID de lote a Nombre de usuario.
ADFS intenta agregar un botón de cierre de sesión adicional Finalizar sesión de SSO o inicio de sesión único en el ¿Finalizar todas las sesiones? página que se muestra después de seleccionar primero el botón de cierre de sesión en la parte superior derecha de la GUI de Blackboard.
Para ello, se debe agregar un elemento SingleLogoutService extra al archivo de metadatos del IdP:
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://your.server.name/adfs/ls/"/> <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://your.server.name/adfs/ls/"/>
Dado que se trata de una configuración opcional de IdP de SAML B2 y la firma que se proporciona en el punto de conexión de redireccionamiento no es correcta, se producirá un error al seleccionar el botón adicional Finalizar sesión de SSO o inicio de sesión único en el Finalizar todas las sesiones? página: Error en la validación de seguridad del mensaje SAML entrante. Se produjo un error en la firma simple de la solicitud de validación para el emisor del contexto. Para su referencia, la Id. del error es [ID del error].
El seguimiento de la pila de Java correspondiente para el ID del error en el registro bb-services es el siguiente:
2016-10-17 16:57:44 -0400 - Incoming SAML message failed security validation Validation of request simple signature failed for context issuer<P><span class="captionText">For reference, the Error ID is 930c7767-8710-475e-8415-2077152280e0.</span> - org.opensaml.ws.security.SecurityPolicyException: Validation of request simple signature failed for context issuer
at org.opensaml.common.binding.security.BaseSAMLSimpleSignatureSecurityPolicyRule.doEvaluate(BaseSAMLSimpleSignatureSecurityPolicyRule.java:139)
at org.opensaml.common.binding.security.BaseSAMLSimpleSignatureSecurityPolicyRule.evaluate(BaseSAMLSimpleSignatureSecurityPolicyRule.java:103)
at org.opensaml.ws.security.provider.BasicSecurityPolicy.evaluate(BasicSecurityPolicy.java:51)
at org.opensaml.ws.message.decoder.BaseMessageDecoder.processSecurityPolicy(BaseMessageDecoder.java:132)
at org.opensaml.ws.message.decoder.BaseMessageDecoder.decode(BaseMessageDecoder.java:83)
at org.opensaml.saml2.binding.decoding.BaseSAML2MessageDecoder.decode(BaseSAML2MessageDecoder.java:70)
at org.springframework.security.saml.processor.SAMLProcessorImpl.retrieveMessage(SAMLProcessorImpl.java:105)
at org.springframework.security.saml.processor.SAMLProcessorImpl.retrieveMessage(SAMLProcessorImpl.java:172)
at org.springframework.security.saml.SAMLLogoutProcessingFilter.processLogout(SAMLLogoutProcessingFilter.java:131)
at org.springframework.security.saml.SAMLLogoutProcessingFilter.doFilter(SAMLLogoutProcessingFilter.java:104)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at sun.reflect.GeneratedMethodAccessor1652.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
[SNIP]Acceda al servidor ADFS y vaya a la Confianza de usuario de confianza para la instancia de Blackboard.
Seleccione la pestaña Propiedades > Extremos.
En la ficha Extremos, encontrará 2 Extremos de cierre de sesión SAML.
Elimine el extremo Redireccionamiento.
Seleccione Eliminar extremo para quitarlo y, luego, haga clic en Aplicar y Aceptar.
Una vez que haya quitado el extremo Redireccionamiento, el botón Finalizar la sesión SSO funcionará correctamente cuando el usuario intente salir.
Cuando intente solucionar un problema de autenticación SAML en ADFS, es posible que deba revisar los registros de la aplicación ADFS de la institución en el visor de eventos del servidor de ADFS para obtener información más detallada. Esto es necesario, en especial, cuando la respuesta SAML del servidor de ADFS tiene un estado de Solicitud rechazada, tal como se muestra a continuación:
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder">
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:RequestDenied" />
</samlp:StatusCode>
</samlp:Status>Nota
Puede usar el complemento SAML Tracer del navegador Firefox para ver la respuesta SAML.
El estado Solicitud denegada en una respuesta normalmente indica que se produjo un problema cuando el IdP (ADFS) intentó comprender la respuesta y procesar el resultado que proporcionó el SP (Blackboard).
Para ver los registros de la aplicación con el visor de eventos:
Abra el visor de eventos en el servidor de ADFS.
En el menú Ver, elija la opción Mostrar los registros de depuración y el análisis.
En el árbol de la consola, vaya a Registros de la aplicación y del servicio > Seguimiento de ADFS > Depurar.
Azure Active Directory
Azure AD es el servicio de administración de identidad y directorio en la nube de Microsoft (MS).
Si una institución usa Azure AD como su IdP y desea que solo se use la primera parte del nombre de usuario de correo electrónico de Azure AD para el nombre de usuario de Blackboard, puede configurar su IdP de Azure AD para usar la función especial ExtractMailPrefix() para quitar el sufijo de dominio del correo electrónico o del nombre principal de usuario, lo que da como resultado que solo se pase la primera parte del nombre de usuario (por ejemplo, "joesmith" en lugar de joesmith@example.com).
Si el ID de usuario remoto de Blackboard es urn:oid:1.3.6.1.4.1.5923.1.1.1.6, la configuración Atributo para el IdP de Azure tendría el siguiente aspecto:
Attribute Name: urn:oid:1.3.6.1.4.1.5923.1.1.1.6 Attribute Value: ExtractMailPrefix() Mail: user.userprincipalname
Entonces, con el ejemplo joesmith@example.com nombre de usuario de correo electrónico, se pasaría así en la aserción SAML del IdP de Azure a Blackboard:
<Attribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6">
<AttributeValue>joesmith</AttributeValue>Hay información adicional disponible sobre el uso de la función ExtractMailPrefix() en la página de documentación de MS Azure.
Después de ingresar las credenciales de inicio de sesión en la página de inicio de sesión de MS Azure AD, aparece un error Sign On! pueden mostrarse después de ser redirigidos a la GUI de Blackboard.
Se mostrará la excepción siguiente en el registro bb-services:
2016-10-13 12:03:23 +0800 - unsuccessfulAuthentication - org.springframework.security.authentication.AuthenticationServiceException: Error validating SAML message at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:100) at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167) at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:87) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) at sun.reflect.GeneratedMethodAccessor854.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:282) at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:279) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAsPrivileged(Subject.java:549) at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:314) at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:253) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:46) at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:148) at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:144) at java.security.AccessController.doPrivileged(Native Method) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:143) at blackboard.auth.provider.saml.customization.filter.BbSAMLExceptionHandleFilter.doFilterInternal(BbSAMLExceptionHandleFilter.java:30) [SNIP] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) Caused by: org.opensaml.common.SAMLException: Response doesn't have any valid assertion which would pass subject validation at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:229) at blackboard.auth.provider.saml.customization.consumer.BbSAMLWebSSOProfileConsumerImpl.processAuthenticationResponse(BbSAMLWebSSOProfileConsumerImpl.java:40) at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:87) ... 230 more Caused by: org.opensaml.xml.validation.ValidationException: Signature is not trusted or invalid at org.springframework.security.saml.websso.AbstractProfileBase.verifySignature(AbstractProfileBase.java:272) at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.verifyAssertionSignature(WebSSOProfileConsumerImpl.java:419) at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.verifyAssertion(WebSSOProfileConsumerImpl.java:292) at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:214) ... 232 more
Esto se debe a que el IdP de MS Azure AD actualiza el certificado, pero el XML de metadatos utilizado por Blackboard SP no se ajusta para reflejar el nuevo certificado.
El nuevo archivo XML de metadatos con el nuevo certificado deberá actualizarse en la página Configuración de SAML en la GUI de Blackboard para el proveedor de autenticación.
Luego, el proveedor de autenticación y SAML B2 deberán alternarse entre el estado Inactivo y Disponible, mientras el proveedor de autenticación SAML se encuentra "Activo", para que se apliquen los metadatos actualizados con el certificado nuevo.
Si un sitio de Blackboard tiene varios proveedores de autenticación que comparten el mismo certificado subyacente para el mismo ID de entidad de IdP subyacente, TODOS esos proveedores de autenticación deberán actualizarse.
Inicio se sesión único mediante IdP
Si un usuario inicia sesión primero en su portal de usuario y luego selecciona la aplicación para su sitio de Blackboard, se abre una nueva pestaña del navegador para mostrar un mensaje: No se encontró el recurso especificado o no tiene permiso para acceder a él.
También aparecerán los eventos relacionados de SAML en el registro stdout-stderr.log:
INFO | jvm 1 | 2016/08/16 10:49:22 | - /saml/SSO at position 1 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' INFO | jvm 1 | 2016/08/16 10:49:22 | - HttpSession returned null object for SPRING_SECURITY_CONTEXT INFO | jvm 1 | 2016/08/16 10:49:22 | - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@58c53845. A new one will be created. INFO | jvm 1 | 2016/08/16 10:49:22 | - /saml/SSO at position 2 of 10 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' INFO | jvm 1 | 2016/08/16 10:49:22 | - /saml/SSO at position 3 of 10 in additional filter chain; firing Filter: 'HeaderWriterFilter' INFO | jvm 1 | 2016/08/16 10:49:22 | - /saml/SSO at position 4 of 10 in additional filter chain; firing Filter: 'FilterChainProxy' INFO | jvm 1 | 2016/08/16 10:49:22 | - Checking match of request : '/saml/sso'; against '/saml/login/**' INFO | jvm 1 | 2016/08/16 10:49:22 | - Checking match of request : '/saml/sso'; against '/saml/logout/**' INFO | jvm 1 | 2016/08/16 10:49:22 | - Checking match of request : '/saml/sso'; against '/saml/bbsamllogout/**' INFO | jvm 1 | 2016/08/16 10:49:22 | - Checking match of request : '/saml/sso'; against '/saml/sso/**' INFO | jvm 1 | 2016/08/16 10:49:22 | - /saml/SSO at position 1 of 1 in additional filter chain; firing Filter: 'SAMLProcessingFilter' INFO | jvm 1 | 2016/08/16 10:49:22 | - Forwarding to / INFO | jvm 1 | 2016/08/16 10:49:22 | - DispatcherServlet with name 'saml' processing POST request for [/auth-saml/saml/SSO] INFO | jvm 1 | 2016/08/16 10:49:22 | - No mapping found for HTTP request with URI [/auth-saml/saml/SSO] in DispatcherServlet with name 'saml' INFO | jvm 1 | 2016/08/16 10:49:22 | - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession. INFO | jvm 1 | 2016/08/16 10:49:22 | - Successfully completed request INFO | jvm 1 | 2016/08/16 10:49:22 | - Skip invoking on INFO | jvm 1 | 2016/08/16 10:49:22 | - SecurityContextHolder now cleared, as request processing completed
La sección Configuración del proveedor de servicios de la página Configuración de autenticación SAML ha cambiado y la opción Habilitar inicio de sesión único automático debe estar marcada para permitir que un usuario acceda a Blackboard desde su portal. Si la opción no está activada, la URL de ACS también se modificará para incluir un alias.
Error de documento incorrecto
Después de ingresar las credenciales de inicio de sesión en la página de inicio de sesión del proveedor de autenticación SAML, aparece un error Sign On! pueden mostrarse después de ser redirigidos a la GUI de Blackboard.
Se mostrará los siguientes elementos DOMException y WRONG_DOCUMENT_ERR en el registro bb-services:
2016-11-18 12:27:31 -0600 - WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it.<P><span class="captionText">For reference, the Error ID is 86ebb81d-d3a3-4da5-95ab-1c94505f4281.</span> - org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it.
at org.apache.xerces.dom.ParentNode.internalInsertBefore(Unknown Source)
at org.apache.xerces.dom.ParentNode.insertBefore(Unknown Source)
at org.apache.xerces.dom.NodeImpl.appendChild(Unknown Source)
at org.opensaml.xml.encryption.Decrypter.parseInputStream(Decrypter.java:832)
at org.opensaml.xml.encryption.Decrypter.decryptDataToDOM(Decrypter.java:610)
at org.opensaml.xml.encryption.Decrypter.decryptUsingResolvedEncryptedKey(Decrypter.java:795)
at org.opensaml.xml.encryption.Decrypter.decryptDataToDOM(Decrypter.java:535)
at org.opensaml.xml.encryption.Decrypter.decryptDataToList(Decrypter.java:453)
at org.opensaml.xml.encryption.Decrypter.decryptData(Decrypter.java:414)
at org.opensaml.saml2.encryption.Decrypter.decryptData(Decrypter.java:141)
at org.opensaml.saml2.encryption.Decrypter.decrypt(Decrypter.java:69)
at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:199)
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:82)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167)
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:87)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at sun.reflect.GeneratedMethodAccessor1209.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:277)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:274)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAsPrivileged(Subject.java:549)
at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:309)
at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:249)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:55)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:191)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:187)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:186)
at blackboard.platform.servlet.DevNonceFilter.doFilter(DevNonceFilter.java:68)
[SNIP]La razón por la que se produce el problema es que otro B2/Project cambió el valor de la propiedad del sistema javax.xml.parsers.DocumentBuilderFactory de org.apache.xerces.jaxp.DocumentBuilderFactoryImpl a com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl.
Hasta que se publique una corrección, estas son las opciones para una solución temporaria:
Reinicie los servicios de Blackboard en cada nodo.
Desactive el cifrado de la respuesta SAML del lado del IdP. Dado que toda la comunicación se realiza a través de SSL, no afectará la seguridad de la autenticación.
No hay una opción para agregar SAML al orden de los proveedores
Al configurar la autenticación SAML, una institución puede notar que no hay una opción para agregar un proveedor de autenticación SAML en la sección Orden del proveedor en la GUI de Blackboard al navegar a Componentes básicos de > de administración del sistema: Autenticación > orden del proveedor.
El motivo por el que no hay una opción para agregar un proveedor de autenticación SAML para el orden de los proveedores es que los proveedores de tipo de redirección, como CAS y SAML, pasan la autenticación a la fuente de autenticación remota. Ese tipo de proveedores no se indican en la opción Orden de los proveedores, ya que se consideran el origen autoritativo de la autenticación y gestionan sus propios errores de autenticación.
Probar la conexión SAML
Hay una opción para probar la conexión de un proveedor SAML en la sección Autenticación de la GUI de Blackboard. Con la prueba de conexión podrá comprobar lo siguiente:
Análisis de los metadatos del IdP
Conexión al IdP
Recepción de la respuesta SAML
Análisis de la respuesta SAML
Coincidencia con la ID del usuario remoto
Inicie sesión en Blackboard
Para probar la conexión a un proveedor de la autenticación SAML:
Inicie sesión en Blackboard como administrador.
Vaya a Componentes básicos de > de administrador del sistema: Autenticación > "Nombre del proveedor SAML" > Examen conexión.
Si se le solicita, escriba las credenciales de inicio de sesión del IdP.
La función Probar conexión se puede utilizar en lugar de habilitar manualmente el registro de depuración SAML en Blackboard por varios motivos.
El valor ID de entidad del proveedor de identidad que se muestra en la página de salida Conexión de examen se extrae del elemento Issuer en el POST de SAML del IdP a Blackboard después de que el usuario se haya autenticado:
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">http://bbpdcsi-adfs1.bbpdcsi.local/a...services/trust</Issuer>
Los valores Atributo SAML que se muestran en la página de salida Conexión de prueba en la sección Respuesta SAML se extraen de los elementos Subject y AttributeStatement en SAML POST del IdP a Blackboard después de que el usuario se haya autenticado:
<Subject>
<NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">luke.skywalker</NameID>
[SNIP]
</Subject>
<AttributeStatement>
<Attribute Name="SamAccountName">
<AttributeValue>luke.skywalker</AttributeValue>
</Attribute>
<Attribute Name="urn:oid:2.5.4.42">
<AttributeValue>Luke</AttributeValue>
</Attribute>
<Attribute Name="urn:oid:2.5.4.4">
<AttributeValue>Skywalker</AttributeValue>
</Attribute>
</AttributeStatement>Crear un proveedor de la autenticación SAML y un IdP para pruebas
Siga los pasos a continuación para crear un Proveedor de identidad (IdP) con la solución de autenticación SSO gratuita de Centrify.
Ese IdP se puede configurar como proveedor de autenticación SAML en un proveedor de servicio (SP) de Blackboard:
Inicie sesión en la GUI de Blackboard como administrador y navegue hasta Administrador del sistema > Autenticación.
Elija la opción Crear proveedor > SAML.
Introduzca los siguientes ajustes:
Nombre > SAML o el que desee.
Proveedor de autenticación > Inactivo (por el momento).
Método de búsqueda de usuario > Nombre de usuario
Restringir por nombre de host > Utilizar este proveedor para cualquier nombre de host
Texto del enlace > Inicio de sesión de SAML Centrify
Seleccione Guardar y configurar.
En el campo ID de la identidad, establezca la opción que desee (pero si la modifica, deberá proporcionar los metadatos del proveedor de servicios actualizados al proveedor de identidades). Copie y pegue la URL de ACS.
En metadatos del proveedor de servicios, elija la opción Generar y guarde el archivo en el escritorio.
En Origen de datos, se recomienda que cree un nuevo Origen de los datos con el nombre CENTRIFY; de lo contrario, use SISTEMA o el nombre que desee.
Marque la casilla de verificación que se encuentra junto a Activar el aprovisionamiento JIT. De este modo, se creará automáticamente una cuenta cuando intente iniciar sesión mediante este proveedor de la autenticación SAML si el usuario no existe. Si no se selecciona el aprovisionamiento JIT, se deberá crear el usuario de forma manual en Blackboard.
En la lista Orígenes de datos compatibles, asegúrese de seleccionar los orígenes de datos con los que este proveedor de la autenticación debe ser compatible.
Seleccione Señalar el proveedor de identidades para el Tipo de proveedor de identidades.
Por el momento, omita el paso de los Metadatos del proveedor de identidades; más adelante, cargará el archivo que ha creado en la sección IdP de Centrify.
Para la sección Asignar los atributos de SAML, use NameID para la ID del usuario remoto.
Seleccione Enviar.
Vaya al sitio web de Centrify y seleccione Comenzar ahora.
Regístrese con su información y seleccione Comenzar ahora.
Recibirá un mensaje de bienvenida por correo electrónico con las credenciales de administrador. Úselas para iniciar sesión en https://cloud.centrify.com.
En la ventana Bienvenido al servicio de identidad de Centrify, seleccione Omitir.
En la ficha Aplicaciones, en la parte superior de la página, haga clic en el botón Agregar aplicaciones web.
En la ficha Personalizar, desplácese hasta la parte inferior y presione el botón Agregar para SAML. Seleccione Sí.
Elija Cerrar en la parte inferior de la ventana Agregar aplicaciones web.
Vaya a la ficha Aplicaciones. En la sección Configuración de la aplicación seleccione el botón Carga de metadatos de SP y cargue el archivo que se creó en el paso 6 de la sección Blackboard SP.
La URL del Servicio de consumidor de aserciones debería completarse automáticamente después de cargar los metadatos del SP.
Desmarque Cifrar aserción. Esto permite que los atributos que se liberan del IdP y se envían a Blackboard se vean mediante el complemento de seguimiento SAML del navegador Firefox o el decodificador de mensajes SAML de Chrome. Dado que toda la comunicación se realiza a través de SSL, no afectará la seguridad de la autenticación.
Desplácese hacia abajo y seleccione Descargar los metadatos del proveedor de identidades SAML. Guarde el archivo en el escritorio.
Seleccione Guardar y vaya a la sección siguiente.
Introduzca un nombre para la sección Descripción. Seleccione Guardar y vaya a la sección siguiente.
En la sección Acceso del usuario, elija la opción Todos y Administrador del sistema. Seleccione Guardar.
No seleccione ninguna opción en la sección Política.
En la sección Asignación de cuentas confirme que se ha especificado
userprincipalnamepara el nombre de campo Servicio de directorio.En la sección Opciones avanzadas, agregue la línea siguiente en la parte inferior del script utilizado para generar una aserción SAML para la aplicación:
Este será el script completo:
setIssuer(Issuer); setSubjectName(UserIdentifier); setAudience('https://YourLearnServer.blackboard.c...saml/saml/SSO'); setRecipient(ServiceUrl); setHttpDestination(ServiceUrl); setSignatureType('Assertion'); setNameFormat('emailaddress'); setAttribute("NameID", LoginUser.Get("userprincipalname"));Esto permitirá que el IdP de Centrify publique un elemento AttributeStatement con la ID del usuario en SAML POST.
Ejemplo:
<AttributeStatement> <Attribute Name="NameID" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" > <AttributeValue>luke.skywalker@blackboard.com.47</AttributeValue> </Attribute> </AttributeStatement>Seleccione Guardar.
El resto de las secciones (Puerta de enlace de la aplicación, Registro de cambios y Flujo de trabajo) no necesitan cambios.
En la ficha Aplicaciones, confirme que la aplicación SAML se haya implementado de forma automática.
En la pestaña Usuarios, elija la opción Agregar usuarios, escriba la información de la cuenta de un usuario y seleccione Crear un usuario.
Vuelva a iniciar sesión en la GUI de Blackboard como administrador, vaya a Autenticación de > de administrador del sistema > Nombre del proveedor de autenticación SAML > Configuración de SAML > Configuración del proveedor de identidad, carga el archivo de metadatos del IdP que se guardó en su escritorio en el paso 13 y seleccione Enviar.
El usuario Centrify IdP que se creó ahora puede iniciar sesión en Blackboard a través de SAML seleccionando ese proveedor de autenticación en la página de inicio de sesión y cerrar sesión en Blackboard con el botón de cierre de sesión adicional Finalizar sesión de SSO o inicio de sesión único en el Finalizar todas las sesiones? página que se muestra después de seleccionar el botón de cierre de sesión en la parte superior derecha de Blackboard.
Cambiar el texto de la página de cierre Finalizar la sesión SSO
Puede que una institución se pregunte si es posible cambiar el texto de la página de cierre Finalizar la sesión SSO. Esto es posible si se edita el paquete de idiomas:
Abra el archivo del paquete de idiomas.
Vaya a
auth-provider-saml/src/main/webapp/WEB-INF/bundles/bb-manifest-en_US.properties.Actualice las claves del mensaje:
saml.single.logout.warning.conent.description // the first line saml.single.logout.warning.conent.recommend // second line saml.single.logout.warning.endsso.title // third line saml.single.logout.warning.endsso.button // the button saml.single.logout.warning.backtolearn // the cancel button
Redirigir a los usuarios a la página de inicio de sesión del IdP
La página de inicio de sesión estándar de Blackboard presenta campos de nombre de usuario y contraseña para el proveedor predeterminado de autenticación interno de aprendizaje. Cuando habilita la autenticación SAML, aparece un pequeño mensaje de "Iniciar sesión con..." en la parte inferior de esta página, por lo que es posible que desee redirigir a los usuarios al servidor de autenticación del IdP automáticamente cuando accedan a la página de inicio de sesión de Blackboard.
Una opción para lograr esto es navegar a Autenticación de > de administrador del sistema y establecer la autenticación interna de aprendizaje predeterminada en Inactivo, lo que significa que ya no se muestra una página de inicio de sesión e inmediatamente el usuario es redirigido al inicio de sesión de SAML. El problema que presenta esta opción es que reemplaza la URL de inicio de sesión predeterminada e impide que un usuario que no utiliza SAML pueda acceder.
Para evitar este inconveniente y proporcionar prácticamente el mismo resultado, use una página de inicio de sesión personalizada. Se redirigirá a los usuarios a la página de inicio de sesión del IdP de la autenticación SAML, pero también se podrá utilizar el enlace a la página predeterminada.
Asegúrese de que la autenticación interna de Learn predeterminada esté activa.
En la página de inicio de sesión predeterminada, copie la ubicación del redireccionamiento del proveedor, p. ej., Iniciar sesión con… SAML. Haga clic con el botón derecho en el enlace y seleccione Copiar la ubicación del enlace.
Vaya a Administrador del sistema > Comunidades > Marcas y temas > Personalizar página de inicio de sesión.
Seleccione Descargar junto a la opción Página de inicio de sesión predeterminada para descargar el archivo JSP.
Abra el archivo JSP con un editor de texto. Agregue el siguiente HTML de ejemplo al archivo JSP de inicio de sesión y reemplace el texto de URL por el URL que se copió en el paso 2.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Blackboard Learn - Redirect</title> <meta http-equiv="REFRESH" content="0;url=https://URL_Goes_Here"></HEAD> <BODY style="font-family: arial,sans-serif;font-size: small; color: grey; padding: 1em; "> Redirecting... <a style="color:grey" href="https://URL_Goes_Here">Go to login page</a> if you are not automatically redirected. </BODY> </HTML>
Nuevamente, vaya a la opción Página de inicio de sesión personalizada en Learn. Seleccione Usar la página personalizada y cargue el archivo JSP de inicio de sesión actualizado.
Después de efectuar los cambios, elija la opción Vista previa en la Página de inicio de sesión personalizada para verificar que el redireccionamiento funcione correctamente.
Ahora, los usuarios que vayan a la URL principal serán redirigidos a la página de inicio de sesión del proveedor de la autenticación SAML. Los administradores aún pueden iniciar sesión con la autenticación interna de Learn a través de la página de inicio de sesión predeterminada: /webapps/login/?action=default_login o/webapps/login/login.jsp).