Reputation: 53
I am trying to port an Oauth2 client based on Oauth for Spring Security from plain Java/Spring to Grails, and have run into a problem. The crux of the issue appears to be the fact that the design of the Spring Oauth client implementation relies on the assumption that an exception thrown from the Oauth2RestTemplate will be caught in a catch block of the OAuth2ClientContextFilter, thus allowing the filter to issue a redirect response (to send an authorization request to the oath provider).
This works fine in plain Java/Spring but in Grails, the GrailsDispatcherServlet is configured to handle all exceptions via HandlerExceptionResolvers. Thus the exception thrown in the Oauth2RestTemplate (invoked inside a Grails controller) is caught by the GrailsExceptionResolver and is never seen by the OAuth2ClientContextFilter, thus defeating the desired redirect behavior.
All discussions I have found of customizing Grails exception handling all seem to assume that the purpose of the customization is to map the exception to an HTTP error code or to a error page view. But is there some way to tell Grails to simply allow a particular exception to flow through unhandled, so that it can be caught by the servlet filter? Or is it possible to insert a custom HandlerExceptionResolver that re-throws the exception rather than returning a ModelAndView (as is the standard expectation for a HandlerExceptionResolver)? Or is there some other better way to get the Oauth for Spring Security client working inside Grails?
Upvotes: 3
Views: 1413
Reputation: 2479
I think you can declare exceptionHandler
in resources.groovy
by defining your custom exception resolver. This custom exception resolver can (optionally) override GrailsExceptionResolver
exceptionHandler(MyExceptionResolver) {
exceptionMappings = ['java.lang.Exception': '/error']
}
class MyExceptionResolver extends GrailsExceptionResolver {
@Override
ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
//your custom code
return super.resolveException(request, response, handler, ex)
}
}
Upvotes: 1
Reputation: 53
Here's what I eventually came up with. Not sure if it is the best solution but it seems to work:
Create a new MyDispatcherServlet.groovy:
package org.example.com
import org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import org.springframework.web.servlet.ModelAndView
import org.springframework.security.oauth2.client.UserRedirectRequiredException
class MyDispatcherServlet extends GrailsDispatcherServlet {
@Override
protected ModelAndView processHandlerException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) throws Exception {
def e = ex
while (e) {
if (e instanceof UserRedirectRequiredException) {
throw ex
}
e = e.cause
}
return super.processHandlerException(request, response, handler, ex)
}
}
The result is that MyDispatcherServlet will re-throw an exception that contains a UserRedirectRequiredException so that it can be caught by the OAuth2ClientContextFilter, but other exceptions will be passed on and handled as before by the GrailsExceptionResolver.
Upvotes: 1