openequella / openEQUELLA

Core openEQUELLA sources
https://openequella.github.io/
Apache License 2.0
41 stars 44 forks source link

LTI launches for unknown users result in a 500 error #1351

Closed cbeach47 closed 4 years ago

cbeach47 commented 4 years ago

Describe the bug Launching an LTI session with an unknown user, and configuring oEQ to present an error message, result in a 500 error instead of the expected 401 error.

Occurs at least with internal and RDS users.

This works in 6.4-QA3.

To Reproduce

  1. Setup an LTI Consumer and configure the 'unknown user' to deny the user and present an error message.
  2. Setup an LTI Launch (such as a Blackboard B2)
  3. Launch an oEQ selection session
  4. Note blank screen and see error in the browser network tab and the oEQ app logs

Expected behavior A 401 error should occur, which will be nicely presented to the user.

Stacktrace The error in 6.4-QA3:

com.dytech.edge.exceptions.WebException: Bad request: User "cbeach@unicon.net" does not exist in EQUELLA
    at com.tle.web.lti.consumers.filter.LtiConsumerUserStateHook.getUserStateResult(LtiConsumerUserStateHook.java:69)
    at com.tle.web.oauth.filter.AbstractOAuthV1UserStateHook.getUserState(AbstractOAuthV1UserStateHook.java:66)
    at com.tle.web.core.filter.TleSessionFilter.getUserState(TleSessionFilter.java:130)
    at com.tle.web.core.filter.TleSessionFilter.doFilterInternal(TleSessionFilter.java:62)
    at com.tle.web.core.filter.OncePerRequestFilter.filterRequest(OncePerRequestFilter.java:28)
    at com.tle.web.dispatcher.RequestDispatchFilter.doFilter(RequestDispatchFilter.java:54)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

In 2019.1 / develop:

11:18:10,067 ERROR [TomcatLog] Servlet.service() for servlet [default] in context with path [/] threw exception
com.dytech.edge.exceptions.WebException: Bad request: User "cbeach@unicon.net" does not exist in openEQUELLA
    at com.tle.web.lti.consumers.filter.LtiConsumerUserStateHook.getUserStateResult(LtiConsumerUserStateHook.java:81)
    at com.tle.web.oauth.filter.AbstractOAuthV1UserStateHook.getUserState(AbstractOAuthV1UserStateHook.java:73)
    at com.tle.web.core.filter.TleSessionFilter.getUserState(TleSessionFilter.java:137)
    at com.tle.web.core.filter.TleSessionFilter.filterRequest(TleSessionFilter.java:81)
    at com.tle.web.dispatcher.RequestDispatchFilter.doFilter(RequestDispatchFilter.java:66)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:528)
    at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:747)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:810)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
11:18:10,076 ERROR [AbstractOAuthV1UserStateHook] context
net.oauth.OAuthProblemException: nonce_used
oauth_problem: nonce_used
    at com.tle.web.oauth.service.OAuthWebServiceImpl.validateNonce(OAuthWebServiceImpl.java:308)
    at com.tle.web.oauth.service.OAuthWebServiceImpl.validateTimestampAndNonce(OAuthWebServiceImpl.java:284)
    at com.tle.web.oauth.service.OAuthWebServiceImpl.validateMessage(OAuthWebServiceImpl.java:206)
    at com.tle.web.oauth.filter.AbstractOAuthV1UserStateHook.getUserState(AbstractOAuthV1UserStateHook.java:69)
    at com.tle.web.core.filter.TleSessionFilter.getUserState(TleSessionFilter.java:137)
    at com.tle.web.core.filter.TleSessionFilter.filterRequest(TleSessionFilter.java:81)
    at com.tle.web.dispatcher.RequestDispatchFilter.doFilter(RequestDispatchFilter.java:66)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:472)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:395)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:316)
    at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:394)
    at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:331)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:173)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:810)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
11:18:10,082 ERROR [TomcatLog] Servlet.service() for servlet [default] threw exception
com.dytech.edge.exceptions.WebException: Unauthorised: OAuth nonce has already been used.
    at com.tle.web.oauth.filter.AbstractOAuthV1UserStateHook.getUserState(AbstractOAuthV1UserStateHook.java:78)
    at com.tle.web.core.filter.TleSessionFilter.getUserState(TleSessionFilter.java:137)
    at com.tle.web.core.filter.TleSessionFilter.filterRequest(TleSessionFilter.java:81)
    at com.tle.web.dispatcher.RequestDispatchFilter.doFilter(RequestDispatchFilter.java:66)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:472)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:395)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:316)
    at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:394)
    at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:331)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:173)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:810)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
11:18:10,083 ERROR [TomcatLog] Exception Processing ErrorPage[exceptionType=java.lang.Throwable, location=/error.do?method=throwable]
com.dytech.edge.exceptions.WebException: Unauthorised: OAuth nonce has already been used.
    at com.tle.web.oauth.filter.AbstractOAuthV1UserStateHook.getUserState(AbstractOAuthV1UserStateHook.java:78)
    at com.tle.web.core.filter.TleSessionFilter.getUserState(TleSessionFilter.java:137)
    at com.tle.web.core.filter.TleSessionFilter.filterRequest(TleSessionFilter.java:81)
    at com.tle.web.dispatcher.RequestDispatchFilter.doFilter(RequestDispatchFilter.java:66)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:472)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:395)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:316)
    at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:394)
    at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:331)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:173)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:810)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
cbeach47 commented 4 years ago

The flow in AbstractOAuthV1UserStateHook helps to identify the issue:

  1. getUserState() L69 - the oauthWebService validates the request and creates a nonce.
  2. getUserState() L73 - getUserStateResult() throws a WebException that the user does not exist.
  3. That exception bubbles up to TleSessionFilter L108 and userService.logoutToGuest() is called. This second logout/login in turn calls getUserState() L69, and the previous nonce is cached, thus both exceptions in the logs.

@edalex-ian - do you know if there was a decision to change this auth flow in recent years?

One thought is before the code logs out to guest, remove the cached/saved nonce value, but that may weaken the OAuth implementation.

edalex-ian commented 4 years ago

Heya @cbeach47

Well more generally on OAuth changes were made (to classes in your above stack - especially OAuthWebServiceImpl) as part of the work for Cloud Providers in 2019.1 and also some of the Bb work. Not to mention the mega merging of plugins.

See a list of changes just on OAuthWebServiceImpl at https://github.com/openequella/openEQUELLA/commits/develop/Source/Plugins/Core/com.equella.core/src/com/tle/web/oauth/service/OAuthWebServiceImpl.java

Definitely a bit of work.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.