Uploaded image for project: 'OpenAM'
  1. OpenAM
  2. OPENAM-6708

Cannot set stateless session properties in PAP

    Details

    • Support Ticket IDs:

      Description

      It should be possible to set properties on a stateless session ssotoken in a post-authentication plugin. Currently this fails due to the StatelessOperations.setProperty method being incorrectly implemented in terms of stateful sessions.

      Example of error:

      SamplePAP:08/27/2015 02:53:11:511 PM BST: Thread[http-bio-8080-exec-1,5,main]: TransactionId[75dc462f-7f05-4a00-8a61-82f20243bcb7]
      ERROR: Unable to set property
      com.iplanet.sso.SSOException: Invalid session ID.AQIC5wM2LY4Sfcy8MjOZBjgneqpcsoBEGd-u2jCk2xIl780.*AAJTSQACMDEAAlNLABMyODYzNjkxNTgwNDQyMzIzMTI0*eyAidHlwIjogIkpXVCIsICJhbGciOiAiTk9ORSIgfQ.eyAic2VyaWFsaXplZF9zZXNzaW9uIjogIntcInNlY3JldFwiOlwiZjVhMWIzYWEtNDVjMi00MmZiLWJiM2YtMzMyZGYwY2FjMzU5XCIsXCJleHBpcnlUaW1lXCI6MTQ0MDY5MDc5MTQzMCxcImxhc3RBY3Rpdml0eVRpbWVcIjoxNDQwNjgzNTkxNDMwLFwic3RhdGVcIjpcInZhbGlkXCIsXCJwcm9wZXJ0aWVzXCI6e1wiQ2hhclNldFwiOlwiVVRGLThcIixcIlVzZXJJZFwiOlwiSW9URGV2aWNlXCIsXCJGdWxsTG9naW5VUkxcIjpcIi9vcGVuYW0vVUkvTG9naW4_YXV0aEluZGV4VmFsdWU9Y2VydFNlcnZpY2UmYXV0aEluZGV4VHlwZT1zZXJ2aWNlJnJlYWxtPSUyRlwiLFwic3VjY2Vzc1VSTFwiOlwiL29wZW5hbS9jb25zb2xlXCIsXCJjb29raWVTdXBwb3J0XCI6XCJ0cnVlXCIsXCJBdXRoTGV2ZWxcIjpcIjBcIixcIlNlc3Npb25IYW5kbGVcIjpcInNoYW5kbGU6QVFJQzV3TTJMWTRTZmN6eHU3TFozNWlzUHh6Vi1Pak9weDBsSktQVHNVOXRaN3cuKkFBSlRTUUFDTURFQUFsTkxBQk01TURZeE1UTTFOek0zTnpJeE5UQTBNak00KlwiLFwiVXNlclRva2VuXCI6XCJJb1REZXZpY2VcIixcImxvZ2luVVJMXCI6XCIvb3BlbmFtL1VJL0xvZ2luXCIsXCJJbmRleFR5cGVcIjpcInNlcnZpY2VcIixcIlByaW5jaXBhbHNcIjpcIklvVERldmljZVwiLFwiU2VydmljZVwiOlwiY2VydFNlcnZpY2VcIixcInN1bi5hbS5Vbml2ZXJzYWxJZGVudGlmaWVyXCI6XCJpZD1Jb1REZXZpY2Usb3U9dXNlcixkYz1vcGVuYW0sZGM9Zm9yZ2Vyb2NrLGRjPW9yZ1wiLFwiYW1sYmNvb2tpZVwiOlwiMDFcIixcIk9yZ2FuaXphdGlvblwiOlwiZGM9b3BlbmFtLGRjPWZvcmdlcm9jayxkYz1vcmdcIixcIkxvY2FsZVwiOlwiZW5fVVNcIixcIkhvc3ROYW1lXCI6XCIxMjcuMC4wLjFcIixcIkF1dGhUeXBlXCI6XCJDZXJ0aWZpY2F0ZVwiLFwiSG9zdFwiOlwiMTI3LjAuMC4xXCIsXCJVc2VyUHJvZmlsZVwiOlwiQ3JlYXRlXCIsXCJBTUN0eElkXCI6XCI0MzNmMmJiMGM0ZTdjNDMwMDFcIixcImNsaWVudFR5cGVcIjpcImdlbmVyaWNIVE1MXCIsXCJhdXRoSW5zdGFudFwiOlwiMjAxNS0wOC0yN1QxMzo1MzoxMVpcIixcIlByaW5jaXBhbFwiOlwiaWQ9SW9URGV2aWNlLG91PXVzZXIsZGM9b3BlbmFtLGRjPWZvcmdlcm9jayxkYz1vcmdcIn0sXCJjbGllbnRJRFwiOlwiaWQ9SW9URGV2aWNlLG91PXVzZXIsZGM9b3BlbmFtLGRjPWZvcmdlcm9jayxkYz1vcmdcIixcImNsaWVudERvbWFpblwiOlwiZGM9b3BlbmFtLGRjPWZvcmdlcm9jayxkYz1vcmdcIixcInNlc3Npb25JRFwiOm51bGwsXCJzZXNzaW9uVHlwZVwiOlwidXNlclwiLFwibWF4SWRsZVwiOjMwLFwibWF4Q2FjaGluZ1wiOjMsXCJuZXZlckV4cGlyaW5nXCI6ZmFsc2UsXCJtYXhUaW1lXCI6MTIwfSIgfQ.
      at org.forgerock.openam.sso.providers.stateless.StatelessSSOToken.setProperty(StatelessSSOToken.java:190)
      at com.forgerock.openam.examples.SamplePAP.onLoginSuccess(SamplePAP.java:58)
      at com.sun.identity.authentication.service.LoginState.executePostProcessSPI(LoginState.java:4852)
      at com.sun.identity.authentication.service.LoginState.postProcess(LoginState.java:4822)
      at com.sun.identity.authentication.service.AMLoginContext.postProcessOnSuccess(AMLoginContext.java:1909)
      at com.sun.identity.authentication.service.AMLoginContext.getStatus(AMLoginContext.java:1031)
      at com.sun.identity.authentication.server.AuthContextLocal.login(AuthContextLocal.java:464)
      at com.sun.identity.authentication.server.AuthContextLocal.login(AuthContextLocal.java:359)
      at com.sun.identity.authentication.server.AuthContextLocal.login(AuthContextLocal.java:270)
      at org.forgerock.openam.forgerockrest.authn.core.wrappers.AuthContextLocalWrapper.login(AuthContextLocalWrapper.java:73)
      at org.forgerock.openam.forgerockrest.authn.core.LoginAuthenticator.startLoginProcess(LoginAuthenticator.java:144)
      at org.forgerock.openam.forgerockrest.authn.core.LoginAuthenticator.getLoginProcess(LoginAuthenticator.java:94)
      at org.forgerock.openam.forgerockrest.authn.RestAuthenticationHandler.authenticate(RestAuthenticationHandler.java:162)
      at org.forgerock.openam.forgerockrest.authn.RestAuthenticationHandler.initiateAuthentication(RestAuthenticationHandler.java:96)
      at org.forgerock.openam.forgerockrest.authn.restlet.AuthenticationServiceV1.authenticate(AuthenticationServiceV1.java:140)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:606)
      at org.restlet.resource.ServerResource.doHandle(ServerResource.java:503)
      at org.restlet.resource.ServerResource.post(ServerResource.java:1216)
      at org.restlet.resource.ServerResource.doHandle(ServerResource.java:592)
      at org.restlet.resource.ServerResource.doNegotiatedHandle(ServerResource.java:649)
      at org.restlet.resource.ServerResource.doConditionalHandle(ServerResource.java:348)
      at org.restlet.resource.ServerResource.handle(ServerResource.java:952)
      at org.restlet.resource.Finder.handle(Finder.java:246)
      at org.restlet.routing.Filter.doHandle(Filter.java:159)
      at org.restlet.routing.Filter.handle(Filter.java:206)
      at org.forgerock.openam.rest.service.VersionRouter.handle(VersionRouter.java:139)
      at org.forgerock.openam.rest.service.ServiceRouter$RestletWrapper.handle(ServiceRouter.java:163)
      at org.restlet.routing.Filter.doHandle(Filter.java:159)
      at org.restlet.routing.Filter.handle(Filter.java:206)
      at org.restlet.routing.Router.doHandle(Router.java:431)
      at org.forgerock.openam.rest.service.RestletRealmRouter.doHandle(RestletRealmRouter.java:106)
      at org.restlet.routing.Router.handle(Router.java:648)
      at org.forgerock.openam.rest.service.ServiceRouter.handle(ServiceRouter.java:144)
      at org.restlet.routing.Filter.doHandle(Filter.java:159)
      at org.restlet.routing.Filter.handle(Filter.java:206)
      at org.restlet.routing.Filter.doHandle(Filter.java:159)
      at org.restlet.routing.Filter.handle(Filter.java:206)
      at org.restlet.routing.Filter.doHandle(Filter.java:159)
      at org.restlet.engine.application.StatusFilter.doHandle(StatusFilter.java:155)
      at org.restlet.routing.Filter.handle(Filter.java:206)
      at org.restlet.routing.Filter.doHandle(Filter.java:159)
      at org.restlet.routing.Filter.handle(Filter.java:206)
      at org.restlet.engine.CompositeHelper.handle(CompositeHelper.java:211)
      at org.restlet.engine.application.ApplicationHelper.handle(ApplicationHelper.java:84)
      at org.restlet.Application.handle(Application.java:381)
      at org.restlet.routing.Filter.doHandle(Filter.java:159)
      at org.restlet.routing.Filter.handle(Filter.java:206)
      at org.restlet.routing.Router.doHandle(Router.java:431)
      at org.restlet.routing.Router.handle(Router.java:648)
      at org.restlet.routing.Filter.doHandle(Filter.java:159)
      at org.restlet.routing.Filter.handle(Filter.java:206)
      at org.restlet.routing.Router.doHandle(Router.java:431)
      at org.restlet.routing.Router.handle(Router.java:648)
      at org.restlet.routing.Filter.doHandle(Filter.java:159)
      at org.restlet.routing.Filter.handle(Filter.java:206)
      at org.restlet.engine.CompositeHelper.handle(CompositeHelper.java:211)
      at org.restlet.Component.handle(Component.java:392)
      at org.restlet.Server.handle(Server.java:516)
      at org.restlet.engine.ServerHelper.handle(ServerHelper.java:72)
      at org.restlet.engine.adapter.HttpServerHelper.handle(HttpServerHelper.java:152)
      at org.restlet.ext.servlet.ServerServlet.service(ServerServlet.java:1089)
      at org.forgerock.openam.rest.RestEndpointServlet.service(RestEndpointServlet.java:142)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.forgerock.jaspi.runtime.JaspiRuntime.processMessage(JaspiRuntime.java:173)
      at org.forgerock.jaspi.JaspiRuntimeFilter.doFilter(JaspiRuntimeFilter.java:131)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.forgerock.openam.validation.ResponseValidationFilter.doFilter(ResponseValidationFilter.java:44)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at com.sun.identity.setup.AMSetupFilter.doFilter(AMSetupFilter.java:90)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.forgerock.openam.audit.context.AuditContextFilter.doFilter(AuditContextFilter.java:47)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
      at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
      at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
      at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
      at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
      at java.lang.Thread.run(Thread.java:745)
      Caused by: com.iplanet.dpro.session.SessionException: Invalid session ID.AQIC5wM2LY4Sfcy8MjOZBjgneqpcsoBEGd-u2jCk2xIl780.*AAJTSQACMDEAAlNLABMyODYzNjkxNTgwNDQyMzIzMTI0*eyAidHlwIjogIkpXVCIsICJhbGciOiAiTk9ORSIgfQ.eyAic2VyaWFsaXplZF9zZXNzaW9uIjogIntcInNlY3JldFwiOlwiZjVhMWIzYWEtNDVjMi00MmZiLWJiM2YtMzMyZGYwY2FjMzU5XCIsXCJleHBpcnlUaW1lXCI6MTQ0MDY5MDc5MTQzMCxcImxhc3RBY3Rpdml0eVRpbWVcIjoxNDQwNjgzNTkxNDMwLFwic3RhdGVcIjpcInZhbGlkXCIsXCJwcm9wZXJ0aWVzXCI6e1wiQ2hhclNldFwiOlwiVVRGLThcIixcIlVzZXJJZFwiOlwiSW9URGV2aWNlXCIsXCJGdWxsTG9naW5VUkxcIjpcIi9vcGVuYW0vVUkvTG9naW4_YXV0aEluZGV4VmFsdWU9Y2VydFNlcnZpY2UmYXV0aEluZGV4VHlwZT1zZXJ2aWNlJnJlYWxtPSUyRlwiLFwic3VjY2Vzc1VSTFwiOlwiL29wZW5hbS9jb25zb2xlXCIsXCJjb29raWVTdXBwb3J0XCI6XCJ0cnVlXCIsXCJBdXRoTGV2ZWxcIjpcIjBcIixcIlNlc3Npb25IYW5kbGVcIjpcInNoYW5kbGU6QVFJQzV3TTJMWTRTZmN6eHU3TFozNWlzUHh6Vi1Pak9weDBsSktQVHNVOXRaN3cuKkFBSlRTUUFDTURFQUFsTkxBQk01TURZeE1UTTFOek0zTnpJeE5UQTBNak00KlwiLFwiVXNlclRva2VuXCI6XCJJb1REZXZpY2VcIixcImxvZ2luVVJMXCI6XCIvb3BlbmFtL1VJL0xvZ2luXCIsXCJJbmRleFR5cGVcIjpcInNlcnZpY2VcIixcIlByaW5jaXBhbHNcIjpcIklvVERldmljZVwiLFwiU2VydmljZVwiOlwiY2VydFNlcnZpY2VcIixcInN1bi5hbS5Vbml2ZXJzYWxJZGVudGlmaWVyXCI6XCJpZD1Jb1REZXZpY2Usb3U9dXNlcixkYz1vcGVuYW0sZGM9Zm9yZ2Vyb2NrLGRjPW9yZ1wiLFwiYW1sYmNvb2tpZVwiOlwiMDFcIixcIk9yZ2FuaXphdGlvblwiOlwiZGM9b3BlbmFtLGRjPWZvcmdlcm9jayxkYz1vcmdcIixcIkxvY2FsZVwiOlwiZW5fVVNcIixcIkhvc3ROYW1lXCI6XCIxMjcuMC4wLjFcIixcIkF1dGhUeXBlXCI6XCJDZXJ0aWZpY2F0ZVwiLFwiSG9zdFwiOlwiMTI3LjAuMC4xXCIsXCJVc2VyUHJvZmlsZVwiOlwiQ3JlYXRlXCIsXCJBTUN0eElkXCI6XCI0MzNmMmJiMGM0ZTdjNDMwMDFcIixcImNsaWVudFR5cGVcIjpcImdlbmVyaWNIVE1MXCIsXCJhdXRoSW5zdGFudFwiOlwiMjAxNS0wOC0yN1QxMzo1MzoxMVpcIixcIlByaW5jaXBhbFwiOlwiaWQ9SW9URGV2aWNlLG91PXVzZXIsZGM9b3BlbmFtLGRjPWZvcmdlcm9jayxkYz1vcmdcIn0sXCJjbGllbnRJRFwiOlwiaWQ9SW9URGV2aWNlLG91PXVzZXIsZGM9b3BlbmFtLGRjPWZvcmdlcm9jayxkYz1vcmdcIixcImNsaWVudERvbWFpblwiOlwiZGM9b3BlbmFtLGRjPWZvcmdlcm9jayxkYz1vcmdcIixcInNlc3Npb25JRFwiOm51bGwsXCJzZXNzaW9uVHlwZVwiOlwidXNlclwiLFwibWF4SWRsZVwiOjMwLFwibWF4Q2FjaGluZ1wiOjMsXCJuZXZlckV4cGlyaW5nXCI6ZmFsc2UsXCJtYXhUaW1lXCI6MTIwfSIgfQ.
      at com.iplanet.dpro.session.Session.setProperty(Session.java:737)
      at org.forgerock.openam.sso.providers.stateless.StatelessSSOToken.setProperty(StatelessSSOToken.java:188)
      ... 94 more
      Caused by: com.iplanet.dpro.session.SessionException: Invalid session ID.AQIC5wM2LY4Sfcy8MjOZBjgneqpcsoBEGd-u2jCk2xIl780.*AAJTSQACMDEAAlNLABMyODYzNjkxNTgwNDQyMzIzMTI0*eyAidHlwIjogIkpXVCIsICJhbGciOiAiTk9ORSIgfQ.eyAic2VyaWFsaXplZF9zZXNzaW9uIjogIntcInNlY3JldFwiOlwiZjVhMWIzYWEtNDVjMi00MmZiLWJiM2YtMzMyZGYwY2FjMzU5XCIsXCJleHBpcnlUaW1lXCI6MTQ0MDY5MDc5MTQzMCxcImxhc3RBY3Rpdml0eVRpbWVcIjoxNDQwNjgzNTkxNDMwLFwic3RhdGVcIjpcInZhbGlkXCIsXCJwcm9wZXJ0aWVzXCI6e1wiQ2hhclNldFwiOlwiVVRGLThcIixcIlVzZXJJZFwiOlwiSW9URGV2aWNlXCIsXCJGdWxsTG9naW5VUkxcIjpcIi9vcGVuYW0vVUkvTG9naW4_YXV0aEluZGV4VmFsdWU9Y2VydFNlcnZpY2UmYXV0aEluZGV4VHlwZT1zZXJ2aWNlJnJlYWxtPSUyRlwiLFwic3VjY2Vzc1VSTFwiOlwiL29wZW5hbS9jb25zb2xlXCIsXCJjb29raWVTdXBwb3J0XCI6XCJ0cnVlXCIsXCJBdXRoTGV2ZWxcIjpcIjBcIixcIlNlc3Npb25IYW5kbGVcIjpcInNoYW5kbGU6QVFJQzV3TTJMWTRTZmN6eHU3TFozNWlzUHh6Vi1Pak9weDBsSktQVHNVOXRaN3cuKkFBSlRTUUFDTURFQUFsTkxBQk01TURZeE1UTTFOek0zTnpJeE5UQTBNak00KlwiLFwiVXNlclRva2VuXCI6XCJJb1REZXZpY2VcIixcImxvZ2luVVJMXCI6XCIvb3BlbmFtL1VJL0xvZ2luXCIsXCJJbmRleFR5cGVcIjpcInNlcnZpY2VcIixcIlByaW5jaXBhbHNcIjpcIklvVERldmljZVwiLFwiU2VydmljZVwiOlwiY2VydFNlcnZpY2VcIixcInN1bi5hbS5Vbml2ZXJzYWxJZGVudGlmaWVyXCI6XCJpZD1Jb1REZXZpY2Usb3U9dXNlcixkYz1vcGVuYW0sZGM9Zm9yZ2Vyb2NrLGRjPW9yZ1wiLFwiYW1sYmNvb2tpZVwiOlwiMDFcIixcIk9yZ2FuaXphdGlvblwiOlwiZGM9b3BlbmFtLGRjPWZvcmdlcm9jayxkYz1vcmdcIixcIkxvY2FsZVwiOlwiZW5fVVNcIixcIkhvc3ROYW1lXCI6XCIxMjcuMC4wLjFcIixcIkF1dGhUeXBlXCI6XCJDZXJ0aWZpY2F0ZVwiLFwiSG9zdFwiOlwiMTI3LjAuMC4xXCIsXCJVc2VyUHJvZmlsZVwiOlwiQ3JlYXRlXCIsXCJBTUN0eElkXCI6XCI0MzNmMmJiMGM0ZTdjNDMwMDFcIixcImNsaWVudFR5cGVcIjpcImdlbmVyaWNIVE1MXCIsXCJhdXRoSW5zdGFudFwiOlwiMjAxNS0wOC0yN1QxMzo1MzoxMVpcIixcIlByaW5jaXBhbFwiOlwiaWQ9SW9URGV2aWNlLG91PXVzZXIsZGM9b3BlbmFtLGRjPWZvcmdlcm9jayxkYz1vcmdcIn0sXCJjbGllbnRJRFwiOlwiaWQ9SW9URGV2aWNlLG91PXVzZXIsZGM9b3BlbmFtLGRjPWZvcmdlcm9jayxkYz1vcmdcIixcImNsaWVudERvbWFpblwiOlwiZGM9b3BlbmFtLGRjPWZvcmdlcm9jayxkYz1vcmdcIixcInNlc3Npb25JRFwiOm51bGwsXCJzZXNzaW9uVHlwZVwiOlwidXNlclwiLFwibWF4SWRsZVwiOjMwLFwibWF4Q2FjaGluZ1wiOjMsXCJuZXZlckV4cGlyaW5nXCI6ZmFsc2UsXCJtYXhUaW1lXCI6MTIwfSIgfQ.
      at com.iplanet.dpro.session.service.SessionService.resolveToken(SessionService.java:534)
      at com.iplanet.dpro.session.service.SessionService.setProperty(SessionService.java:965)
      at com.iplanet.dpro.session.operations.strategies.LocalOperations.setProperty(LocalOperations.java:114)
      at com.iplanet.dpro.session.operations.strategies.StatelessOperations.setProperty(StatelessOperations.java:69)
      at com.iplanet.dpro.session.monitoring.MonitoredOperations.setProperty(MonitoredOperations.java:90)
      at com.iplanet.dpro.session.Session.setProperty(Session.java:734)
      ... 95 more
      

        Attachments

          Activity

            People

            • Assignee:
              neil.madden Neil Madden
              Reporter:
              neil.madden Neil Madden
              QA Assignee:
              Joanna Wasilewska [X] (Inactive)
            • Votes:
              4 Vote for this issue
              Watchers:
              16 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Time Tracking

                Estimated:
                Original Estimate - 8h
                8h
                Remaining:
                Time Spent - 3h Remaining Estimate - 5h
                5h
                Logged:
                Time Spent - 3h Remaining Estimate - 5h
                3h