jeffwils / grails-spring-security-saml

Grails Spring Security SAML2.0 Plugin for Grails 3
8 stars 24 forks source link

Plugin not allowing for me to grab user information. The user is always shown as an anonymous user #77

Open RogelioCodes opened 1 year ago

RogelioCodes commented 1 year ago

Hello. I am trying to get the user information to print but I am not sure if the users are just being logged in as an anonymous user. In the logs we see that authentication is successful, but cannot get the user information to print. Here is my secureController:

| Grails Version: 4.0.3 | JVM Version: 1.8.0_292 `

  class SecureController {
  static allowedMethods = [saml_grails_4: 'POST']
      SpringSecurityService springSecurityService
@Secured("hasAnyRole('ROLE_ADMIN', 'ROLE_ANONYMOUS')")
def index() {
    println "SECURE ACCESS ONLY"
    //springSecurityService.principal
    println "INSIDE SOMEMETHOD"
    println(springSecurityService.principal)
    def username_test = springSecurityService.principal.getUsername()
    println "INSIDE SOMEMETHOD2"
    println(username_test)
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (!(authentication instanceof AnonymousAuthenticationToken)) {
        String currentUserName = authentication.getName();
        render "Secure access only... you are authenticated: ${currentUsername}"
    }else{
        render "THERE IS NO USER"
    }

    render "Secure access only: ${springSecurityService.principal}"
}

@Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
def startSAML() {
    println "INSIDE START SAML"
    session["sessid"] = params["sessid"]
    session["templateid"] = params["temid"]
    redirect(actionName: "index")
}

@Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
def saml_grails_4(){
    def samlResponse = params["SAMLResponse"]
    def sess = ""
    def token = ""
    println "SAMLRESPONSE:"
    println samlResponse
    println "BASEURL:"
    def baseurl = grailsApplication.config.getProperty('grails.prodServerURL')
    println baseurl
}
}

`

And here are some logs:

`

  SECURE ACCESS ONLY
  INSIDE SOMEMETHOD
  org.springframework.security.core.userdetails.User@dc730200: Username: __grails.anonymous.user__; Password: [PROTECTED]; Enabled: false; AccountNonExpired: false; credentialsNonExpired: false; AccountNonLocked: false; Granted Authorities: ROLE_ANONYMOUS

  INSIDE SOMEMETHOD2
  __grails.anonymous.user__
  SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
  Closing Hibernate Session in OpenSessionInViewInterceptor
  Completed 200 OK
  Publishing event: ServletRequestHandledEvent: url=[/saml_grails_4/secure/index]; client=[HIDDEN_IP]; method=[GET]; servlet=[grailsDispatcherServlet]; session=[75CB0DF82453251949A274B06EC989AF]; user=[null]; time=[3ms]; status=[OK]

2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request '/login/index' matched by universal pattern '/**'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 1 of 15 in additional filter chain; firing Filter: 'SecurityRequestHolderFilter'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 2 of 15 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@798a541. A new one will be created.
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 3 of 15 in additional filter chain; firing Filter: 'SAMLEntryPoint'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 4 of 15 in additional filter chain; firing Filter: 'MetadataDisplayFilterUTF8'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 5 of 15 in additional filter chain; firing Filter: 'SAMLProcessingFilter'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 6 of 15 in additional filter chain; firing Filter: 'SAMLLogoutFilter'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 7 of 15 in additional filter chain; firing Filter: 'SAMLLogoutProcessingFilter'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 8 of 15 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/login/index'; against '/logoff'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 9 of 15 in additional filter chain; firing Filter: 'GrailsUsernamePasswordAuthenticationFilter'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 10 of 15 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 11 of 15 in additional filter chain; firing Filter: 'GrailsRememberMeAuthenticationFilter'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 12 of 15 in additional filter chain; firing Filter: 'GrailsAnonymousAuthenticationFilter'
2022-11-15 19:30:49,862 DEBUG grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'grails.plugin.springsecurity.authentication.GrailsAnonymousAuthenticationToken@aad1a6c6: Principal: org.springframework.security.core.userdetails.User@dc730200: Username: __grails.anonymous.user__; Password: [PROTECTED]; Enabled: false; AccountNonExpired: false; credentialsNonExpired: false; AccountNonLocked: false; Granted Authorities: ROLE_ANONYMOUS; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: HIDDEN_IP; SessionId: D105FF51C2EDE1E606B916298F7AC376; Granted Authorities: ROLE_ANONYMOUS'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 13 of 15 in additional filter chain; firing Filter: 'FormContentFilter'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 14 of 15 in additional filter chain; firing Filter: 'UpdateRequestContextHolderExceptionTranslationFilter'
2022-11-15 19:30:49,862 DEBUG org.springframework.security.web.FilterChainProxy - /login/index at position 15 of 15 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2022-11-15 19:30:49,863 DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /login/index; Attributes: [permitAll]
2022-11-15 19:30:49,863 DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Previously Authenticated: grails.plugin.springsecurity.authentication.GrailsAnonymousAuthenticationToken@aad1a6c6: Principal: org.springframework.security.core.userdetails.User@dc730200: Username: __grails.anonymous.user__; Password: [PROTECTED]; Enabled: false; AccountNonExpired: false; credentialsNonExpired: false; AccountNonLocked: false; Granted Authorities: ROLE_ANONYMOUS; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: HIDDEN_IP; SessionId: D105FF51C2EDE1E606B916298F7AC376; Granted Authorities: ROLE_ANONYMOUS
2022-11-15 19:30:49,863 DEBUG org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl - getReachableGrantedAuthorities() - From the roles [ROLE_ANONYMOUS] one can reach [ROLE_ANONYMOUS] in zero or more steps.
2022-11-15 19:30:49,864 DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Authorization successful
2022-11-15 19:30:49,864 DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - RunAsManager did not change Authentication object
2022-11-15 19:30:49,864 DEBUG org.springframework.security.web.FilterChainProxy - /login/index reached end of additional filter chain; proceeding with original chain
2022-11-15 19:30:49,864 DEBUG org.grails.web.servlet.mvc.GrailsDispatcherServlet - GET "/saml_grails_4/login/index", parameters={}
2022-11-15 19:30:49,865 DEBUG org.grails.web.mapping.mvc.UrlMappingsHandlerMapping - Mapped to org.grails.web.mapping.mvc.GrailsControllerUrlMappingInfo@13627757
2022-11-15 19:30:49,865 DEBUG org.grails.plugin.hibernate.support.GrailsOpenSessionInViewInterceptor - Opening Hibernate Session in OpenSessionInViewInterceptor
2022-11-15 19:30:49,866 DEBUG grails.web.mapping.ResponseRedirector - Method [redirect] forwarding request to [/login/auth]
2022-11-15 19:30:49,866 DEBUG grails.web.mapping.ResponseRedirector - Executing redirect with response [org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper@5660eb5f]
2022-11-15 19:30:49,866 DEBUG org.grails.plugin.hibernate.support.GrailsOpenSessionInViewInterceptor - Closing Hibernate Session in OpenSessionInViewInterceptor
2022-11-15 19:30:49,866 DEBUG org.grails.web.servlet.mvc.GrailsDispatcherServlet - Completed 302 FOUND
2022-11-15 19:30:49,866 DEBUG io.micronaut.context.event.ApplicationEventPublisher - Publishing event: ServletRequestHandledEvent: url=[/saml_grails_4/login/index]; client=[HIDDEN_IP]; method=[GET]; servlet=[grailsDispatcherServlet]; session=[D105FF51C2EDE1E606B916298F7AC376]; user=[null]; time=[2ms]; status=[OK]
2022-11-15 19:30:49,866 DEBUG io.micronaut.context.DefaultBeanContext - Resolving beans for type: <ServletRequestHandledEvent> io.micronaut.context.event.ApplicationEventListener
2022-11-15 19:30:49,866 DEBUG grails.plugin.springsecurity.web.UpdateRequestContextHolderExceptionTranslationFilter - Chain processed normally
2022-11-15 19:30:49,866 DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2022-11-15 19:30:49,866 DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
2022-11-15 19:30:49,866 DEBUG org.grails.web.servlet.mvc.GrailsWebRequestFilter - Cleared Grails thread-bound request context: org.apache.catalina.connector.RequestFacade@74ed49f0
2022-11-15 19:30:49,944 DEBUG org.grails.web.servlet.mvc.GrailsWebRequestFilter - Bound Grails request context to thread: org.apache.catalina.connector.RequestFacade@74ed49f0
2022-11-15 19:30:49,945 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/login/auth'; against '/assets/**'
2022-11-15 19:30:49,945 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/login/auth'; against '/**/js/**'
2022-11-15 19:30:49,945 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/login/auth'; against '/**/css/**'
2022-11-15 19:30:49,945 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/login/auth'; against '/**/images/**'
2022-11-15 19:30:49,945 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/login/auth'; against '/**/favicon.ico'
2022-11-15 19:30:49,945 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request '/login/auth' matched by universal pattern '/**'
2022-11-15 19:30:49,945 DEBUG org.springframework.security.web.FilterChainProxy - /login/auth at position 1 of 15 in additional filter chain; firing Filter: 'SecurityRequestHolderFilter'
2022-11-15 19:30:49,945 DEBUG org.springframework.security.web.FilterChainProxy - /login/auth at position 2 of 15 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2022-11-15 19:30:49,945 DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
2022-11-15 19:30:49,945 DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@798a541. A new one will be created.
2022-11-15 19:30:49,945 DEBUG org.springframework.security.web.FilterChainProxy - /login/auth at position 3 of 15 in additional filter chain; firing Filter: 'SAMLEntryPoint'
2022-11-15 19:30:49,945 DEBUG org.opensaml.saml2.metadata.provider.ChainingMetadataProvider - Checking child metadata provider for entity descriptor with entity ID: https://itdmportal01.itdm.az.MYCOMP.com:8443/saml_grails_4
2022-11-15 19:30:49,945 DEBUG org.opensaml.saml2.metadata.provider.AbstractMetadataProvider - Searching for entity descriptor with an entity ID of https://itdmportal01.itdm.az.MYCOMP.com:8443/saml_grails_4
2022-11-15 19:30:49,945 DEBUG org.opensaml.saml2.metadata.provider.AbstractMetadataProvider - Metadata document did not contain a descriptor for entity https://itdmportal01.itdm.az.MYCOMP.com:8443/saml_grails_4
2022-11-15 19:30:49,945 DEBUG org.opensaml.saml2.metadata.provider.AbstractMetadataProvider - Metadata document did not contain any role descriptors of type {urn:oasis:names:tc:SAML:2.0:metadata}SPSSODescriptor for entity https://itdmportal01.itdm.az.MYCOMP.com:8443/saml_grails_4
2022-11-15 19:30:49,945 DEBUG org.opensaml.saml2.metadata.provider.AbstractMetadataProvider - Metadata document does not contain a role of type {urn:oasis:names:tc:SAML:2.0:metadata}SPSSODescriptor supporting protocol urn:oasis:names:tc:SAML:2.0:protocol for entity https://itdmportal01.itdm.az.MYCOMP.com:8443/saml_grails_4
2022-11-15 19:30:49,945 DEBUG org.opensaml.saml2.metadata.provider.ChainingMetadataProvider - Checking child metadata provider for entity descriptor with entity ID: https://itdmportal01.itdm.az.MYCOMP.com:8443/saml_grails_4
2022-11-15 19:30:49,945 DEBUG org.opensaml.saml2.metadata.provider.AbstractMetadataProvider - Searching for entity descriptor with an entity ID of https://itdmportal01.itdm.az.MYCOMP.com:8443/saml_grails_4
2022-11-15 19:30:49,945 DEBUG org.opensaml.xml.security.credential.KeyStoreCredentialResolver - Building credential from keystore entry for entityID itdmportal01, usage type UNSPECIFIED
2022-11-15 19:30:49,945 DEBUG org.opensaml.xml.security.credential.KeyStoreCredentialResolver - Processing PrivateKeyEntry from keystore
2022-11-15 19:30:49,945 DEBUG org.opensaml.xml.security.credential.criteria.EvaluableCredentialCriteriaRegistry - Registry located evaluable criteria class org.opensaml.xml.security.credential.criteria.EvaluableEntityIDCredentialCriteria for criteria class org.opensaml.xml.security.criteria.EntityIDCriteria
2022-11-15 19:30:49,946 DEBUG org.opensaml.xml.security.credential.KeyStoreCredentialResolver - Building credential from keystore entry for entityID itdmportal01, usage type UNSPECIFIED
2022-11-15 19:30:49,946 DEBUG org.opensaml.xml.security.credential.KeyStoreCredentialResolver - Processing PrivateKeyEntry from keystore
2022-11-15 19:30:49,946 DEBUG org.opensaml.xml.security.credential.criteria.EvaluableCredentialCriteriaRegistry - Registry located evaluable criteria class org.opensaml.xml.security.credential.criteria.EvaluableEntityIDCredentialCriteria for criteria class org.opensaml.xml.security.criteria.EntityIDCriteria
2022-11-15 19:30:49,958 DEBUG org.opensaml.xml.parse.StaticBasicParserPool - Setting DocumentBuilderFactory attribute 'http://javax.xml.XMLConstants/feature/secure-processing'
2022-11-15 19:30:49,958 DEBUG org.opensaml.xml.parse.StaticBasicParserPool - Setting DocumentBuilderFactory attribute 'http://apache.org/xml/features/dom/defer-node-expansion'
2022-11-15 19:30:49,959 DEBUG org.opensaml.xml.parse.StaticBasicParserPool - Setting DocumentBuilderFactory attribute 'http://apache.org/xml/features/disallow-doctype-decl'
2022-11-15 19:30:49,959 DEBUG org.opensaml.xml.security.credential.KeyStoreCredentialResolver - Building credential from keystore entry for entityID itdmportal01, usage type UNSPECIFIED
2022-11-15 19:30:49,959 DEBUG org.opensaml.xml.security.credential.KeyStoreCredentialResolver - Processing PrivateKeyEntry from keystore
2022-11-15 19:30:49,959 DEBUG org.opensaml.xml.security.credential.criteria.EvaluableCredentialCriteriaRegistry - Registry located evaluable criteria class org.opensaml.xml.security.credential.criteria.EvaluableEntityIDCredentialCriteria for criteria class org.opensaml.xml.security.criteria.EntityIDCriteria
2022-11-15 19:30:49,960 DEBUG org.springframework.security.saml.context.SAMLContextProviderImpl - No IDP specified, using default http://signin.MYCOMP.com/exk2rvctc7x88VpZC697
2022-11-15 19:30:49,960 DEBUG org.opensaml.saml2.metadata.provider.ChainingMetadataProvider - Checking child metadata provider for entity descriptor with entity ID: http://signin.MYCOMP.com/exk2rvctc7x88VpZC697
2022-11-15 19:30:49,960 DEBUG org.opensaml.saml2.metadata.provider.AbstractMetadataProvider - Searching for entity descriptor with an entity ID of http://signin.MYCOMP.com/exk2rvctc7x88VpZC697
2022-11-15 19:30:49,960 DEBUG org.springframework.security.saml.util.SAMLUtil - Index for AssertionConsumerService not specified, returning default
2022-11-15 19:30:49,960 DEBUG org.opensaml.saml2.metadata.support.SAML2MetadataHelper - Selecting default IndexedEndpoint
2022-11-15 19:30:49,960 DEBUG org.opensaml.saml2.metadata.support.SAML2MetadataHelper - Selected first IndexedEndpoint with no explicit isDefault
2022-11-15 19:30:49,960 DEBUG org.springframework.security.saml.SAMLEntryPoint - Processing SSO using WebSSO profile
2022-11-15 19:30:49,960 DEBUG org.opensaml.saml2.metadata.support.SAML2MetadataHelper - Selecting default IndexedEndpoint
2022-11-15 19:30:49,960 DEBUG org.opensaml.saml2.metadata.support.SAML2MetadataHelper - Selected first IndexedEndpoint with no explicit isDefault
2022-11-15 19:30:49,960 DEBUG org.opensaml.saml2.metadata.support.SAML2MetadataHelper - Selecting default IndexedEndpoint
2022-11-15 19:30:49,960 DEBUG org.opensaml.saml2.metadata.support.SAML2MetadataHelper - Selected first IndexedEndpoint with no explicit isDefault
2022-11-15 19:30:49,960 DEBUG org.opensaml.saml2.metadata.support.SAML2MetadataHelper - Selecting default IndexedEndpoint
2022-11-15 19:30:49,960 DEBUG org.opensaml.saml2.metadata.support.SAML2MetadataHelper - Selected first IndexedEndpoint with no explicit isDefault
2022-11-15 19:30:49,960 DEBUG org.springframework.security.saml.websso.WebSSOProfileImpl - Using default consumer service with binding urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
2022-11-15 19:30:49,960 DEBUG org.opensaml.ws.message.encoder.BaseMessageEncoder - Beginning encode message to outbound transport of type: org.opensaml.ws.transport.http.HttpServletResponseAdapter
2022-11-15 19:30:49,960 DEBUG org.apache.xml.security.algorithms.JCEMapper - Request for URI http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
2022-11-15 19:30:49,960 DEBUG org.opensaml.common.SAMLObjectHelper - Examing signed object for content references with exclusive canonicalization transform
2022-11-15 19:30:49,960 DEBUG org.opensaml.common.SAMLObjectHelper - Saw exclusive transform, declaring non-visible namespaces on signed object
2022-11-15 19:30:49,961 DEBUG org.opensaml.xml.signature.impl.SignatureMarshaller - Starting to marshall {http://www.w3.org/2000/09/xmldsig#}Signature
2022-11-15 19:30:49,961 DEBUG org.opensaml.xml.signature.impl.SignatureMarshaller - Creating XMLSignature object
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.algorithms.SignatureAlgorithm - Create URI "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" class "class org.apache.xml.security.algorithms.implementations.SignatureBaseRSA$SignatureRSASHA256"
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.algorithms.JCEMapper - Request for URI http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.algorithms.implementations.SignatureBaseRSA - Created SignatureRSA using SHA256withRSA
2022-11-15 19:30:49,961 DEBUG org.opensaml.xml.signature.impl.SignatureMarshaller - Adding content to XMLSignature.
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.transforms.Transforms - Transforms.addTransform(http://www.w3.org/2000/09/xmldsig#enveloped-signature)
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.transforms.Transform - Create URI "http://www.w3.org/2000/09/xmldsig#enveloped-signature" class "class org.apache.xml.security.transforms.implementations.TransformEnvelopedSignature"
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.transforms.Transform - The NodeList is null
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.transforms.Transforms - Transforms.addTransform(http://www.w3.org/2000/09/xmldsig#enveloped-signature)
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.transforms.Transforms - Transforms.addTransform(http://www.w3.org/2001/10/xml-exc-c14n#)
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.transforms.Transform - Create URI "http://www.w3.org/2001/10/xml-exc-c14n#" class "class org.apache.xml.security.transforms.implementations.TransformC14NExclusive"
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.transforms.Transform - The NodeList is null
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.transforms.Transforms - Transforms.addTransform(http://www.w3.org/2001/10/xml-exc-c14n#)
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.utils.ElementProxy - setElement("ds:Transform", "null")
2022-11-15 19:30:49,961 DEBUG org.opensaml.common.impl.SAMLObjectContentReference - Adding list of inclusive namespaces for signature exclusive canonicalization transform
2022-11-15 19:30:49,961 DEBUG org.opensaml.xml.signature.impl.SignatureMarshaller - Creating Signature DOM element
2022-11-15 19:30:49,961 DEBUG org.opensaml.xml.signature.Signer - Computing signature over XMLSignature object
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.utils.resolver.ResourceResolver - I was asked to create a ResourceResolver and got 0
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.utils.resolver.ResourceResolver - check resolvability by class org.apache.xml.security.utils.resolver.ResourceResolver
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.utils.resolver.implementations.ResolverFragment - State I can resolve reference: "#a2d6gabh5ff436bf5bjg05fh1d600fb"
2022-11-15 19:30:49,961 DEBUG org.apache.xml.security.utils.resolver.implementations.ResolverFragment - Try to catch an Element with ID a2d6gabh5ff436bf5bjg05fh1d600fb and Element was [saml2p:AuthnRequest: null]
2022-11-15 19:30:49,962 DEBUG org.apache.xml.security.algorithms.JCEMapper - Request for URI http://www.w3.org/2001/04/xmlenc#sha256
2022-11-15 19:30:49,962 DEBUG org.apache.xml.security.utils.resolver.ResourceResolver - I was asked to create a ResourceResolver and got 0
2022-11-15 19:30:49,962 DEBUG org.apache.xml.security.utils.resolver.ResourceResolver - check resolvability by class org.apache.xml.security.utils.resolver.ResourceResolver
2022-11-15 19:30:49,962 DEBUG org.apache.xml.security.utils.resolver.implementations.ResolverFragment - State I can resolve reference: "#a2d6gabh5ff436bf5bjg05fh1d600fb"
2022-11-15 19:30:49,962 DEBUG org.apache.xml.security.utils.resolver.implementations.ResolverFragment - Try to catch an Element with ID a2d6gabh5ff436bf5bjg05fh1d600fb and Element was [saml2p:AuthnRequest: null]
2022-11-15 19:30:49,962 DEBUG org.apache.xml.security.utils.ElementProxy - setElement("ds:Transform", "null")
2022-11-15 19:30:49,962 DEBUG org.apache.xml.security.transforms.Transforms - Perform the (0)th http://www.w3.org/2000/09/xmldsig#enveloped-signature transform
2022-11-15 19:30:49,962 DEBUG org.apache.xml.security.utils.ElementProxy - setElement("ds:Transform", "null")
2022-11-15 19:30:49,962 DEBUG org.apache.xml.security.transforms.Transforms - Perform the (1)th http://www.w3.org/2001/10/xml-exc-c14n# transform
2022-11-15 19:30:49,962 DEBUG org.apache.xml.security.utils.DigesterOutputStream - Pre-digested input:
2022-11-15 19:30:49,962 DEBUG org.apache.xml.security.utils.DigesterOutputStream - <saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://itdmportal01.itdm.az.MYCOMP.com:8443/saml_grails_4" Destination="https://signin.MYCOMP.com/app/MYCOMP_itdmstestsamlfinal_1/exk2rvctc7x88VpZC697/sso/saml" ForceAuthn="false" ID="a2d6gabh5ff436bf5bjg05fh1d600fb" IsPassive="false" IssueInstant="2022-11-15T19:30:49.960Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://itdmportal01.itdm.az.MYCOMP.com:8443/saml_grails_4</saml2:Issuer></saml2p:AuthnRequest>
2022-11-15 19:30:49,962 DEBUG org.apache.xml.security.utils.SignerOutputStream - Canonicalized SignedInfo:
2022-11-15 19:30:49,962 DEBUG org.apache.xml.security.utils.SignerOutputStream - <ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></ds:SignatureMethod><ds:Reference URI="#a2d6gabh5ff436bf5bjg05fh1d600fb"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></ds:DigestMethod><ds:DigestValue>01kXLhYqsd2YKs4fv1BhLxCpsqFQdeHxn+8Hc/ZZdZU=</ds:DigestValue></ds:Reference></ds:SignedInfo>
2022-11-15 19:30:49,963 DEBUG org.opensaml.saml2.binding.encoding.HTTPPostEncoder - Invoking Velocity template to create POST body
2022-11-15 19:30:49,964 DEBUG org.opensaml.saml2.binding.encoding.HTTPPostEncoder - Encoding action url of 'https://signin.MYCOMP.com/app/vMYCOMP_itdmstestsamlfinal_1/exk2rvctc7x88VpZC697/sso/saml' with encoded value 'https&#x3a;&#x2f;&#x2f;signin.MYCOMP.com&#x2f;app&#x2f;MYCOMP_itdmstestsamlfinal_1&#x2f;exk2rvctc7x88VpZC697&#x2f;sso&#x2f;saml'
2022-11-15 19:30:49,964 DEBUG org.opensaml.saml2.binding.encoding.HTTPPostEncoder - Marshalling and Base64 encoding SAML message
2022-11-15 19:30:49,967 DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2022-11-15 19:30:49,969 DEBUG PROTOCOL_MESSAGE -
<?xml version="1.0" encoding="UTF-8"?><saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://itdmportal01.itdm.az.MYCOMP.com:8443/saml_grails_4" Destination="https://signin.MYCOMP.com/app/MYCOMP_itdmstestsamlfinal_1/exk2rvctc7x88VpZC697/sso/saml" ForceAuthn="false" ID="a2d6gabh5ff436bf5bjg05fh1d600fb" IsPassive="false" IssueInstant="2022-11-15T19:30:49.960Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0">
   <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://itdmportal01.itdm.az.MYCOMP.com:8443/saml_grails_4</saml2:Issuer>
   <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      <ds:SignedInfo>
         <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
         <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
         <ds:Reference URI="#a2d6gabh5ff436bf5bjg05fh1d600fb">
            <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>DIGESTVAL</ds:DigestValue>
         </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue>MYKEY</ds:SignatureValue>
      <ds:KeyInfo>
         <ds:X509Data>
            <ds:X509Certificate>CERTCERTCERT</ds:X509Certificate>
         </ds:X509Data>
      </ds:KeyInfo>
   </ds:Signature>
</saml2p:AuthnRequest>

2022-11-15 19:30:49,969 DEBUG org.opensaml.ws.message.encoder.BaseMessageEncoder - Successfully encoded message.
2022-11-15 19:30:49,969 DEBUG org.springframework.security.saml.storage.HttpSessionStorage - Storing message a2d6gabh5ff436bf5bjg05fh1d600fb to session D105FF51C2EDE1E606B916298F7AC376
2022-11-15 19:30:49,969 INFO org.springframework.security.saml.log.SAMLDefaultLogger - AuthNRequest;SUCCESS;HIDDEN_IP;https://itdmportal01.itdm.az.MYCOMP.com:8443/saml_grails_4;http://signin.MYCOMP.com/exk2rvctc7x88VpZC697;;;
2022-11-15 19:30:49,969 DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
2022-11-15 19:30:49,969 DEBUG org.grails.web.servlet.mvc.GrailsWebRequestFilter - Cleared Grails thread-bound request context: org.apache.catalina.connector.RequestFacade@74ed49f0
2022-11-15 19:30:52,066 DEBUG org.grails.web.servlet.mvc.GrailsWebRequestFilter - Bound Grails request context to thread: org.apache.catalina.connector.RequestFacade@74ed49f0
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/assets/**'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/**/js/**'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/**/css/**'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/**/images/**'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/**/favicon.ico'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request '/' matched by universal pattern '/**'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.FilterChainProxy - / at position 1 of 15 in additional filter chain; firing Filter: 'SecurityRequestHolderFilter'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.FilterChainProxy - / at position 2 of 15 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@798a541. A new one will be created.
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.FilterChainProxy - / at position 3 of 15 in additional filter chain; firing Filter: 'SAMLEntryPoint'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.FilterChainProxy - / at position 4 of 15 in additional filter chain; firing Filter: 'MetadataDisplayFilterUTF8'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.FilterChainProxy - / at position 5 of 15 in additional filter chain; firing Filter: 'SAMLProcessingFilter'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.FilterChainProxy - / at position 6 of 15 in additional filter chain; firing Filter: 'SAMLLogoutFilter'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.FilterChainProxy - / at position 7 of 15 in additional filter chain; firing Filter: 'SAMLLogoutProcessingFilter'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.FilterChainProxy - / at position 8 of 15 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/logoff'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.FilterChainProxy - / at position 9 of 15 in additional filter chain; firing Filter: 'GrailsUsernamePasswordAuthenticationFilter'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.FilterChainProxy - / at position 10 of 15 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2022-11-15 19:30:52,066 DEBUG org.springframework.security.web.FilterChainProxy - / at position 11 of 15 in additional filter chain; firing Filter: 'GrailsRememberMeAuthenticationFilter'
2022-11-15 19:30:52,067 DEBUG org.springframework.security.web.FilterChainProxy - / at position 12 of 15 in additional filter chain; firing Filter: 'GrailsAnonymousAuthenticationFilter'
2022-11-15 19:30:52,067 DEBUG grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'grails.plugin.springsecurity.authentication.GrailsAnonymousAuthenticationToken@aad1a6c6: Principal: org.springframework.security.core.userdetails.User@dc730200: Username: __grails.anonymous.user__; Password: [PROTECTED]; Enabled: false; AccountNonExpired: false; credentialsNonExpired: false; AccountNonLocked: false; Granted Authorities: ROLE_ANONYMOUS; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: HIDDEN_IP; SessionId: D105FF51C2EDE1E606B916298F7AC376; Granted Authorities: ROLE_ANONYMOUS'
2022-11-15 19:30:52,067 DEBUG org.springframework.security.web.FilterChainProxy - / at position 13 of 15 in additional filter chain; firing Filter: 'FormContentFilter'
2022-11-15 19:30:52,067 DEBUG org.springframework.security.web.FilterChainProxy - / at position 14 of 15 in additional filter chain; firing Filter: 'UpdateRequestContextHolderExceptionTranslationFilter'
2022-11-15 19:30:52,067 DEBUG org.springframework.security.web.FilterChainProxy - / at position 15 of 15 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2022-11-15 19:30:52,067 DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /; Attributes: [permitAll]
2022-11-15 19:30:52,067 DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Previously Authenticated: grails.plugin.springsecurity.authentication.GrailsAnonymousAuthenticationToken@aad1a6c6: Principal: org.springframework.security.core.userdetails.User@dc730200: Username: __grails.anonymous.user__; Password: [PROTECTED]; Enabled: false; AccountNonExpired: false; credentialsNonExpired: false; AccountNonLocked: false; Granted Authorities: ROLE_ANONYMOUS; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: HIDDEN_IP; SessionId: D105FF51C2EDE1E606B916298F7AC376; Granted Authorities: ROLE_ANONYMOUS
2022-11-15 19:30:52,068 DEBUG org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl - getReachableGrantedAuthorities() - From the roles [ROLE_ANONYMOUS] one can reach [ROLE_ANONYMOUS] in zero or more steps.
2022-11-15 19:30:52,068 DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Authorization successful
2022-11-15 19:30:52,068 DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - RunAsManager did not change Authentication object
2022-11-15 19:30:52,068 DEBUG org.springframework.security.web.FilterChainProxy - / reached end of additional filter chain; proceeding with original chain
2022-11-15 19:30:52,068 DEBUG org.grails.web.servlet.mvc.GrailsDispatcherServlet - GET "/saml_grails_4/", parameters={}
2022-11-15 19:30:52,069 DEBUG org.grails.web.mapping.mvc.UrlMappingsHandlerMapping - Mapped to /
2022-11-15 19:30:52,069 DEBUG org.grails.plugin.hibernate.support.GrailsOpenSessionInViewInterceptor - Opening Hibernate Session in OpenSessionInViewInterceptor
2022-11-15 19:30:52,069 DEBUG org.grails.web.servlet.view.GrailsLayoutViewResolver - Resolving view for name /index and locale en_US
2022-11-15 19:30:52,069 DEBUG org.grails.web.servlet.view.GrailsLayoutViewResolver - Creating layout view name /index and locale en_US
2022-11-15 19:30:52,069 DEBUG org.grails.web.sitemesh.SitemeshLayoutView - View [SitemeshLayoutView], model {}
2022-11-15 19:30:52,069 DEBUG org.grails.web.sitemesh.GrailsLayoutView - Rendering inner view for layout and model {}
2022-11-15 19:30:52,069 DEBUG org.grails.web.servlet.view.GroovyPageView - View [GroovyPageView], model {}
2022-11-15 19:30:52,069 DEBUG org.grails.gsp.GroovyPageWritable - Writing output with content type: text/html;charset=UTF-8
2022-11-15 19:30:52,070 DEBUG io.micronaut.context.DefaultBeanContext - Resolved existing bean [org.grails.plugins.codecs.DefaultCodecLookup@1c427bd6] for type [interface org.grails.encoder.CodecLookup] and qualifier [@Named('codecLookup')]
2022-11-15 19:30:52,074 DEBUG org.grails.web.sitemesh.GrailsLayoutView - Finding layout for request and content
2022-11-15 19:30:52,074 DEBUG org.grails.web.sitemesh.GrailsLayoutDecoratorMapper - Evaluating layout for request: /saml_grails_4/
2022-11-15 19:30:52,074 DEBUG org.grails.web.sitemesh.GrailsLayoutView - Found layout. Rendering content for layout and model /layouts/main.gsp
2022-11-15 19:30:52,074 DEBUG org.grails.web.servlet.view.GroovyPageView - View [GroovyPageView], model {}
2022-11-15 19:30:52,074 DEBUG io.micronaut.context.DefaultBeanContext - Resolved existing bean [org.grails.plugins.codecs.DefaultCodecLookup@1c427bd6] for type [interface org.grails.encoder.CodecLookup] and qualifier [@Named('codecLookup')]
2022-11-15 19:30:52,079 DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2022-11-15 19:30:52,080 DEBUG org.grails.plugin.hibernate.support.GrailsOpenSessionInViewInterceptor - Closing Hibernate Session in OpenSessionInViewInterceptor
2022-11-15 19:30:52,080 DEBUG org.grails.web.servlet.mvc.GrailsDispatcherServlet - Completed 200 OK
2022-11-15 19:30:52,080 DEBUG io.micronaut.context.event.ApplicationEventPublisher - Publishing event: ServletRequestHandledEvent: url=[/saml_grails_4/]; client=[HIDDEN_IP]; method=[GET]; servlet=[grailsDispatcherServlet]; session=[D105FF51C2EDE1E606B916298F7AC376]; user=[null]; time=[12ms]; status=[OK]
2022-11-15 19:30:52,080 DEBUG io.micronaut.context.DefaultBeanContext - Resolving beans for type: <ServletRequestHandledEvent> io.micronaut.context.event.ApplicationEventListener
2022-11-15 19:30:52,081 DEBUG grails.plugin.springsecurity.web.UpdateRequestContextHolderExceptionTranslationFilter - Chain processed normally
2022-11-15 19:30:52,081 DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
2022-11-15 19:30:52,081 DEBUG org.grails.web.servlet.mvc.GrailsWebRequestFilter - Cleared Grails thread-bound request context: org.apache.catalina.connector.RequestFacade@74ed49f0

` I cannot figure out if the user is actually being authenticated or if I am just getting an anonymous login

RogelioCodes commented 1 year ago

Another thing I noticed was I will get a log that says I am authenticated even when I am not. I tested using an incognito tab. You can see "Authenticated: true;" towards the end of the line. 2022-11-15 20:11:38,904 DEBUG grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'grails.plugin.springsecurity.authentication.GrailsAnonymousAuthenticationToken@aad1a6c6: Principal: org.springframework.security.core.userdetails.User@dc730200: Username: __grails.anonymous.user__; Password: [PROTECTED]; Enabled: false; AccountNonExpired: false; credentialsNonExpired: false; AccountNonLocked: false; Granted Authorities: ROLE_ANONYMOUS; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: [REDACTED]; SessionId: 80ADD5CF5548217D9EA0858DBD4C40B8; Granted Authorities: ROLE_ANONYMOUS'

valentingoebel commented 1 year ago

I don't really see a opensaml related error, you can turn that package off (org.opensaml.saml2) in the logback settings.

Your problem is very strange. It looks like the SAML login worked successfully but you are still not logged in. This either means the error is not being shown in the logs (are you sure you enabled the package 'org.grails.plugin.springsecurity.saml' and set it to debug level in your logback settings?) or there is some strange redirection happening or wrong URL that prevents you from logging in via the /saml/SSO Filter which should execute the SpringSamlUserDetailsService.

Here is what I expect to see:

2022-11-16 14:42:00.230 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Loading user - org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal@18955352
2022-11-16 14:42:00.240 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : getSamlUsername()
2022-11-16 14:42:00.240 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Username using attribute 'urn:oid:0.9.2342.19200300.100.1.1': <username>
2022-11-16 14:42:00.241 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Username <username>
2022-11-16 14:42:00.241 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Attempting to load UserClass with name: <package>.User
2022-11-16 14:42:00.242 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Loaded UserClass: class <package>.User
2022-11-16 14:42:00.332 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Generated User <username>
2022-11-16 14:42:00.343 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Determining Authorities for User(username:<username>)
2022-11-16 14:42:00.346 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Using role assignments from local database.
2022-11-16 14:42:00.455 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Added 2 role(s) from local database.
2022-11-16 14:42:00.457 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Using samlUserGroupAttribute: urn:oid:1.3.6.1.4.1.5923.1.1.1.1
2022-11-16 14:42:00.457 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Using samlGroups: [employee, member]
2022-11-16 14:42:00.458 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : User samlUserGroupToRoleMapping: [ROLE_EMPLOYEE:employee, ROLE_STUDENT:student]
2022-11-16 14:42:00.460 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Group Name From SAML: employee
2022-11-16 14:42:00.463 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Found Role
2022-11-16 14:42:00.463 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : getRole - param -> ROLE_EMPLOYEE
2022-11-16 14:42:00.487 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Where clause -> [authority:ROLE_EMPLOYEE]
2022-11-16 14:42:00.493 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Return Value from getRole Class-> class <package>.Role  Value -> ROLE_EMPLOYEE
2022-11-16 14:42:00.493 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Found Authority Adding it
2022-11-16 14:42:00.494 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Group Name From SAML: member
2022-11-16 14:42:00.494 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : Returning Authorities with 3 Authorities added.
2022-11-16 14:42:00.494 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : User Class class <package>.User
2022-11-16 14:42:00.495 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : User - username <username>
2022-11-16 14:42:00.495 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : User - id null
2022-11-16 14:42:00.506 DEBUG --- [0.0-8009-exec-8] o.g.p.s.s.SpringSamlUserDetailsService   : User Details org.grails.plugin.springsecurity.saml.SamlUserDetails [Username=<username>, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_ADMIN, ROLE_EMPLOYEE, ROLE_STUKO]]
...
2022-11-16 14:43:07.738 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Loading user - org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal@570bfa36
2022-11-16 14:43:07.738 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : getSamlUsername()
2022-11-16 14:43:07.739 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Username using attribute 'urn:oid:0.9.2342.19200300.100.1.1': <username>
2022-11-16 14:43:07.739 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Username <username>
2022-11-16 14:43:07.739 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Attempting to load UserClass with name: <package>.User
2022-11-16 14:43:07.739 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Loaded UserClass: class <package>.User
2022-11-16 14:43:07.740 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Generated User <username>
2022-11-16 14:43:07.745 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Determining Authorities for User(username:<username>)
2022-11-16 14:43:07.745 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Using role assignments from local database.
2022-11-16 14:43:07.761 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Added 2 role(s) from local database.
2022-11-16 14:43:07.763 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Using samlUserGroupAttribute: urn:oid:1.3.6.1.4.1.5923.1.1.1.1
2022-11-16 14:43:07.763 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Using samlGroups: [employee, member]
2022-11-16 14:43:07.763 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : User samlUserGroupToRoleMapping: [ROLE_EMPLOYEE:employee, ROLE_STUDENT:student]
2022-11-16 14:43:07.763 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Group Name From SAML: employee
2022-11-16 14:43:07.765 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Found Role
2022-11-16 14:43:07.765 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : getRole - param -> ROLE_EMPLOYEE
2022-11-16 14:43:07.766 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Where clause -> [authority:ROLE_EMPLOYEE]
2022-11-16 14:43:07.767 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Return Value from getRole Class-> class <package>.Role  Value -> ROLE_EMPLOYEE
2022-11-16 14:43:07.767 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Found Authority Adding it
2022-11-16 14:43:07.767 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Group Name From SAML: member
2022-11-16 14:43:07.767 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : Returning Authorities with 3 Authorities added.
2022-11-16 14:43:07.767 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : User Class class <package>.User
2022-11-16 14:43:07.767 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : User - username <username>
2022-11-16 14:43:07.767 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : User - id null
2022-11-16 14:43:07.768 DEBUG --- [0.0-8009-exec-4] o.g.p.s.s.SpringSamlUserDetailsService   : User Details org.grails.plugin.springsecurity.saml.SamlUserDetails [Username=<username>, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_ADMIN, ROLE_EMPLOYEE, ROLE_STUKO]]
RogelioCodes commented 1 year ago

Thank for the response. Here is my dependencies section of my build.gradle. @valentingoebel I thought logging was enabled for the plugin but now I am honestly not sure. I have not been working with java too long. How did you turn on logging? We have a logback.groovy, not logback.xml Could you tell me more about this /saml/SSO? Where should I be specifying that. Also how do you yourself handle logging in? Currently our home controller directs us to the default login controller. Should that default login controller work? It seems to be autogenerated by the plugin. We do get redirected to our login provider, and even asked for a 2 factor authentication push. Then we are redirected back to our default index.gsp.

Is there anything else we should be creating on our end? We have a secure controller as well which I will link down below. `

  dependencies {    
      developmentOnly("org.springframework.boot:spring-boot-devtools")
      compile "org.springframework.boot:spring-boot-starter-logging"
      compile "org.springframework.boot:spring-boot-autoconfigure"
      compile "org.grails:grails-core"
      compile "org.springframework.boot:spring-boot-starter-actuator"
      compile "org.springframework.boot:spring-boot-starter-tomcat"
      compile "org.grails:grails-web-boot"
      compile "org.grails:grails-logging"
      compile "org.grails:grails-plugin-rest"
      compile "org.grails:grails-plugin-databinding"
      compile "org.grails:grails-plugin-i18n"
      compile "org.grails:grails-plugin-services"
      compile "org.grails:grails-plugin-url-mappings"
      compile "org.grails:grails-plugin-interceptors"
      compile "org.grails.plugins:cache"
      compile "org.grails.plugins:async"
      compile "org.grails.plugins:scaffolding"
      compile "org.grails.plugins:events"
      compile "org.grails.plugins:hibernate5"
      compile "org.hibernate:hibernate-core:5.4.18.Final"
      compile "org.grails.plugins:gsp"
      compile 'org.grails.plugins:spring-security-core:4.0.3'
      compile 'org.grails.plugins:spring-security-saml:4.0.2'
      compile "org.springframework.boot:spring-boot-starter-security" 
      //compileOnly "io.micronaut:micronaut-inject-groovy"
      console "org.grails:grails-console"
      profile "org.grails.profiles:web"
      runtime "org.glassfish.web:el-impl:2.1.2-b03"
      runtime "com.h2database:h2"
      runtime "org.apache.tomcat:tomcat-jdbc"
      runtime "javax.xml.bind:jaxb-api:2.3.1"
      runtime "com.bertramlabs.plugins:asset-pipeline-grails:3.2.4"
      //testCompile "io.micronaut:micronaut-inject-groovy"
      testCompile "org.grails:grails-gorm-testing-support"
      testCompile "org.mockito:mockito-core"
      testCompile "org.grails:grails-web-testing-support"
      testCompile "org.grails.plugins:geb"
      testCompile "org.seleniumhq.selenium:selenium-remote-driver:3.14.0"
      testCompile "org.seleniumhq.selenium:selenium-api:3.14.0"
      testCompile "org.seleniumhq.selenium:selenium-support:3.14.0"
      testRuntime "org.seleniumhq.selenium:selenium-chrome-driver:3.14.0"
      testRuntime "org.seleniumhq.selenium:selenium-firefox-driver:3.14.0"
      }

`

Here is my logback.groovy `

import grails.util.BuildSettings
import grails.util.Environment
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
import ch.qos.logback.core.ConsoleAppender
import ch.qos.logback.core.FileAppender
import static ch.qos.logback.classic.Level.INFO
import java.io.File

File logLevel = new File("/opt/tomcat/work/LOGLEVEL")
String LEVEL = "INFO"
if (logLevel.exists()) {
    def LL = logLevel.readLines()
    LEVEL = LL[0]
}

def targetDir = System.getProperty("LOG_PATH")
def targetFile = System.getProperty("LOG_FILE")

appender("FILE", FileAppender) {
    file = "${targetDir}/${targetFile}"
    encoder(PatternLayoutEncoder) {
        pattern = "%date %level %logger - %msg%n"
    }
}
appender("STDOUT", ConsoleAppender) {
    encoder(PatternLayoutEncoder) {
        pattern = "%msg%n"
    }
}
//
// always have INFO
//
root(INFO, ["FILE", "STDOUT"])
if (LEVEL.equals("WARN")) {
    root(INFO, ["FILE", "STDOUT"])
    root(WARN, ["FILE", "STDOUT"])
}
if (LEVEL.equals("DEBUG")) {
    root(INFO, ["FILE", "STDOUT"])
    root(WARN, ["FILE", "STDOUT"])
    root(DEBUG, ["FILE", "STDOUT"])
}

`

and my application.groovy

`

  grails.plugin.springsecurity.userLookup.userDomainClassName = 'saml_grails_4.User'
  grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'saml_grails_4.UserRole'
  grails.plugin.springsecurity.authority.className = 'saml_grails_4.Role'
  grails.plugin.springsecurity.controllerAnnotations.staticRules = [
      [pattern: '/',               access: ['permitAll']],
      [pattern: '/home/**',        access: ['permitAll']],
      [pattern: '/secure/**',      access: ['permitAll']],
      [pattern: '/error',          access: ['permitAll']],
      [pattern: '/index',          access: ['permitAll']],
      [pattern: '/index.gsp',      access: ['permitAll']],
      [pattern: '/shutdown',       access: ['permitAll']],
      [pattern: '/assets/**',      access: ['permitAll']],
      [pattern: '/**/js/**',       access: ['permitAll']],
      [pattern: '/**/css/**',      access: ['permitAll']],
      [pattern: '/**/images/**',   access: ['permitAll']],
      [pattern: '/**/favicon.ico', access: ['permitAll']]
  ]

  grails.plugin.springsecurity.filterChain.chainMap = [
      [pattern: '/assets/**',      filters: 'none'],
      [pattern: '/**/js/**',       filters: 'none'],
      [pattern: '/**/css/**',      filters: 'none'],
      [pattern: '/**/images/**',   filters: 'none'],
      [pattern: '/**/favicon.ico', filters: 'none'],
      [pattern: '/**',             filters: 'JOINED_FILTERS']
  ]

  grails.plugin.springsecurity.debug.useFilter = true

  grails.plugins.springsecurity.portMapper.httpsPort=8443
  grails.app.context="/saml_grails_4"
  grails.localServerURL = "https://localhost:8080${grails.app.context}"
  grails.devServerURL = "https://itdmportal01.itdm.az.MYCOMPANY.com:8443/${grails.app.context}"
  grails.prodServerURL = "https://itdmportal01.itdm.az.MYCOMPANY.com:8443/saml_grails_4"

  grails.plugin.springsecurity.providerNames = ['samlAuthenticationProvider', 'daoAuthenticationProvider', 'anonymousAuthenticationProvider']
  grails.plugin.springsecurity.saml.active = true
  //grails.plugin.springsecurity.samluserAttributeMappings = [email: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', username: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress']

  grails.plugin.springsecurity.saml.afterLoginUrl = '/'
  grails.plugin.springsecurity.saml.afterLogoutUrl = '/'
  grails.plugin.springsecurity.saml.responseSkew = 300
  grails.plugin.springsecurity.saml.signatureAlgorithm = 'rsa-sha256'
  grails.plugin.springsecurity.saml.digestAlgorithm = 'sha256'
  grails.plugin.springsecurity.saml.userGroupAttribute = 'roles'
  grails.plugin.springsecurity.saml.autoCreate.active = true //If you want the plugin to generate users in the DB as they are authenticated via SAML
  grails.plugin.springsecurity.saml.autoCreate.key = 'id'
  grails.plugin.springsecurity.saml.autoCreate.assignAuthorities = true //If you want the plugin to assign the authorities that come from the SAML message.
  grails.plugin.springsecurity.saml.metadata.defaultIdp = 'http://signin.<mycompany>.com/exk2rvctc7x88VpZC697'
  grails.plugin.springsecurity.saml.metadata.url = '/saml/metadata'
  grails.plugin.springsecurity.saml.metadata.providers = ['http://signin.MYCOMPANY.com/exk2rvctc7x88VpZC697':'security/Idp_itdmportal01_metadata.xml']
  grails.plugin.springsecurity.saml.metadata.sp.file = "security/sp_metadata.xml"
  grails.plugin.springsecurity.saml.metadata.sp.defaults.local = false;
  grails.plugin.springsecurity.saml.metadata.sp.defaults.entityId = 'https://itdmportal01.itdm.az.MYCOMPANY.com:8443/saml_grails_4'
  grails.plugin.springsecurity.saml.metadata.sp.defaults.alias = 'itdmportal01';
  grails.plugin.springsecurity.saml.metadata.sp.defaults.securityProfile = 'metaiop';
  grails.plugin.springsecurity.saml.metadata.sp.defaults.signingKey = 'itdmportal01';
  grails.plugin.springsecurity.saml.metadata.sp.defaults.encryptionKey = 'itdmportal01';
  grails.plugin.springsecurity.saml.metadata.sp.defaults.tlsKey = 'itdmportal01';
  grails.plugin.springsecurity.saml.metadata.sp.defaults.requireArtifactResolveSigned = true;
  grails.plugin.springsecurity.saml.metadata.sp.defaults.requireLogoutRequestSigned = true;
  grails.plugin.springsecurity.saml.metadata.sp.defaults.requireLogoutResponseSigned = false;
  grails.plugin.springsecurity.saml.keyManager.storeFile = "classpath:security/itdmportal01.jks"
  grails.plugin.springsecurity.saml.keyManager.storePass = '<password>'
  grails.plugin.springsecurity.saml.keyManager.passwords = [itdmportal01:'<password>']
  grails.plugin.springsecurity.saml.keyManager.defaultKey = 'itdmportal01'

`

Secure controller: `

  package saml_grails_4
  import groovy.lang.MissingPropertyException

  import grails.validation.ValidationException
  import static org.springframework.http.HttpStatus.*

  import grails.plugin.springsecurity.annotation.Secured
  import grails.plugin.springsecurity.SpringSecurityUtils
  import grails.plugin.springsecurity.SpringSecurityService

  import org.grails.plugin.springsecurity.saml.SpringSamlUserDetailsService;
  import org.grails.plugin.springsecurity.saml.SamlSecurityService;

  import org.springframework.beans.factory.annotation.Value

  import org.springframework.security.core.GrantedAuthority
  import org.springframework.security.core.authority.SimpleGrantedAuthority
  import org.springframework.security.core.userdetails.UsernameNotFoundException
  import org.springframework.security.core.Authentication;
  import org.springframework.security.core.context.SecurityContextHolder;
  import org.springframework.security.core.userdetails.UserDetails

  import org.springframework.security.saml.SAMLCredential
  import org.springframework.security.saml.userdetails.SAMLUserDetailsService

  import org.springframework.security.authentication.AnonymousAuthenticationProvider;
  import org.springframework.security.authentication.AnonymousAuthenticationToken;

  class SecureController {
      static allowedMethods = [saml_grails_4: 'POST']
      SpringSecurityService springSecurityService
      SamlSecurityService samlSecurityService 
      SpringSamlUserDetailsService springSamlUserDetailsService
      @Secured("hasAnyRole('ROLE_ADMIN', 'ROLE_ANONYMOUS')")
      def index() {
          println "SECURE ACCESS ONLY"
          println "springSecurityService.Authentication: ${springSecurityService.authentication}"
          println "samlSecurityService: ${samlSecurityService.getCurrentUser()}"
          springSecurityService.principal
          println "INSIDE SOMEMETHOD"
          // springSamlUserDetailsService.load
          println(springSecurityService.principal)
          def username_test = springSecurityService.principal.getUsername()
          println "INSIDE SOMEMETHOD2"
          println(username_test)
          Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
          if (!(authentication instanceof AnonymousAuthenticationToken)) {
              String currentUserName = authentication.getName();
              render "Secure access only... you are authenticated: ${currentUsername}"
          } else {
              render "THERE IS NO USER"
          }

          render "Secure access only: ${springSecurityService.principal}"
      }
      @Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
      def startSAML() {
          println "INSIDE START SAML"
          session["sessid"] = params["sessid"]
          session["templateid"] = params["temid"]
          println("session[sessid] ${session["sessid"]} ")
          println("session[templateid] = ${params["temid"]}")
          redirect(actionName: "index")
      }
      @Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
      def saml_grails_4() {
          def samlResponse = params["SAMLResponse"]
          def sess = ""
          def token = ""
          println "SAMLRESPONSE:"
          println samlResponse
          println "BASEURL:"
          def baseurl = grailsApplication.config.getProperty('grails.prodServerURL')
          println baseurl
      }
  }

`

Our index.gsp is the default index.gsp that gets generated when you run grails-create-app. The only difference we made is that we added this line:

< href="https://itdmportal01.itdm.az.mycompany.com:8443/saml_grails_4/secure/startSAML"> <g:message code='register.label'/></A>

Which triggers our startSAML function inside of our secure controller. We have tried logging in using both that link and the link to the login controller. Neither seem to give us any success.

I did add in the SamlSecurityServices.groovy and SpringSamlUserDetails.groovy into our services folder to add in some extra print statements, but I have not been able to decipher what is going on. I definitely do not see anything close to the logs you mentioned.

If you have any other possible pointers please reach out and thanks a ton for taking the time to respond. We have been trying everything to get this to work.

valentingoebel commented 1 year ago

The SAMLEntryPoint Filter uses springsecurity.auth.loginFormUrl=/login/auth. If you go to that path it should initiate SSO Login. If you want to manually specify your own path you can overwrite the bean in resources.groovy. The following configuration lets you use local login in development (optional SAML at /saml/auth) and test but forces SAML in every other environment.

resources.groovy

        samlEntryPoint(SAMLEntryPoint) {
            switch(Environment.current) {
                case Environment.DEVELOPMENT:
                    filterProcessesUrl = '/saml/auth'
                    break
                default:
                    filterProcessesUrl = '/login/auth'
                    break
            }
            defaultProfileOptions = ref('webProfileOptions')
        }

Add this to your logback.groovy

logger 'org.grails.plugin.springsecurity.saml', DEBUG, ['STDOUT'], false
logger 'org.springframework.security.saml', DEBUG, ['STDOUT'], false

If you don't see any logs and never enter SpringSamlUserDetails then I don't know. You would have to use a debugger (in Eclipse or IntelliJ) and step through SamlEntryPoint/SAMLProcessingFilter (set a breakpoint in doFilter) until you find your problem.

Also, it shouldn't make a huge difference but try out version 4.0.3. It has a minor fix if you want to configure autoCreate.active=false.

RogelioCodes commented 1 year ago

We were able to get past many of our issues thanks to your help. One last question - currently we have our user attribute mappings set to grab an email but it seems to not be added to our SamlUserDetails. I am under the impression that setting the grails.plugin.springsecurity.samluserAttributeMappings should allow us to grab an email from the response that we get from our idp. Is there anything else we have to do to get this added to our userDetails? Please let me know, thanks @valentingoebel

grails.plugin.springsecurity.samluserAttributeMappings = [ emailAddress:'urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified' ]

Here is what our saml response looks like `

 <saml2:Assertion  xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="id7428569942196580287769288" IssueInstant="2022-11-17T22:04:39.840Z" Version="2.0">

 <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://signin.mycompany.com/exk2rvctc7x88VpZC697</saml2:Issuer>
    <saml2:Subject>
        <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">rcordova</saml2:NameID>
        <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
            <saml2:SubjectConfirmationData InResponseTo="a4facj1g0adddbaa27eic466jie64ef" NotOnOrAfter="2022-11-17T22:09:39.841Z" Recipient="https://itdmportal01.itdm.az.company.com:8443/saml_grails_4/saml/SSO"></saml2:SubjectConfirmationData>
        </saml2:SubjectConfirmation>
    </saml2:Subject>
    <saml2:Conditions NotBefore="2022-11-17T21:59:39.841Z" NotOnOrAfter="2022-11-17T22:09:39.841Z">
        <saml2:AudienceRestriction>
            <saml2:Audience>https://itdmportal01.itdm.az.mycompany.com:8443/saml_grails_4</saml2:Audience>
        </saml2:AudienceRestriction>
    </saml2:Conditions>
    <saml2:AuthnStatement AuthnInstant="2022-11-17T22:04:39.364Z" SessionIndex="a4facj1g0adddbaa27eic466jie64ef">
        <saml2:AuthnContext>
            <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
        </saml2:AuthnContext>
    </saml2:AuthnStatement>
    <saml2:AttributeStatement>
        <saml2:Attribute Name="emailAddress" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
            <saml2:AttributeValue
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">user@company.com
            </saml2:AttributeValue>
        </saml2:Attribute>
        <saml2:Attribute Name="username" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
            <saml2:AttributeValue
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">sample_username
            </saml2:AttributeValue>
        </saml2:Attribute>
    </saml2:AttributeStatement>
</saml2:Assertion>

`

valentingoebel commented 1 year ago

You have to add the SAML attributes to your User.groovy class (specified in grails.plugin.springsecurity.userLookup.userDomainClassName = 'saml_grails_4.User).

class User implements Serializable{

...

    String username
    String password
    boolean enabled = true
    boolean accountExpired
    boolean accountLocked
    boolean passwordExpired

    String emailAddress
....
}

The plugin will fill those attributes automatically. You can then access it in any controller via principal.emailAddress.

RogelioCodes commented 1 year ago

we have tried defining that @valentingoebel but it seems to always break on insert. One thing we noticed is the samlAttributes always come back as null. Could it be that our samluserAttributeMapping is configured incorrectly?

`

Static SQL for entity: saml_grails_4.User
Version select: select version from user where id =?
Snapshot select: select user_.id, user_.version as version2_2_, user_.password_expired as password3_2_, user_.username as username4_2_, user_.emailaddress as emailadd5_2_, user_.account_locked as account_6_2_, user_.`password` as password7_2_, user_.account_expired as account_8_2_, user_.enabled as enabled9_2_ from user user_ where user_.id=?
Insert 0: insert into user (version, password_expired, username, emailaddress, account_locked, `password`, account_expired, enabled, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
Update 0: update user set version=?, password_expired=?, username=?, emailaddress=?, account_locked=?, `password`=?, account_expired=?, enabled=? where id=? and version=?
Delete 0: delete from user where id=? and version=?
Identity insert: insert into user (version, password_expired, username, emailaddress, account_locked, `password`, account_expired, enabled) values (?, ?, ?, ?, ?, ?, ?, ?)
Adding QuerySpace : uid = <gen:0> -> org.hibernate.loader.plan.build.internal.spaces.EntityQuerySpaceImpl@5bc09b21]
Visiting attribute path : version
Visiting attribute path : passwordExpired
Visiting attribute path : username
Visiting attribute path : emailaddress
Visiting attribute path : accountLocked
Visiting attribute path : password
Visiting attribute path : accountExpired
Visiting attribute path : enabled

`

RogelioCodes commented 1 year ago

also our user.groovy @valentingoebel `

package saml_grails_4

import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import grails.compiler.GrailsCompileStatic

@GrailsCompileStatic
@EqualsAndHashCode(includes='username')
@ToString(includes='username', includeNames=true, includePackage=false)

class User implements Serializable {
private static final long serialVersionUID = 1

String username
String password
String emailaddress //Added by bolo
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired

Set<Role> getAuthorities() {
    (UserRole.findAllByUser(this) as List<UserRole>)*.role as Set<Role>
}

static constraints = {
    password nullable: false, blank: false, password: true
    username nullable: false, blank: false, unique: true
}

static mapping = {
    password column: '`password`'
}

}

`

valentingoebel commented 1 year ago

It took me a long time to notice but did you misspell the configuration setting?

grails.plugin.springsecurity.samluserAttributeMappings is supposed to be grails.plugin.springsecurity.saml.userAttributeMappings (saml DOT userAttributeMappings).

Your saml response looks fine so the IDP is doing everything correctly. The User class is also correct.