Skip to content

wrap-authorization ignores 'raised' unauthorized exceptions in async mode #88

@mszajna

Description

@mszajna

With Ring 3-arity contract, exceptions thrown in the same thread bubble back to the middleware. However, if any non-blocking IO was to happen between wrap-authorization and throw-unauthorized, those exceptions would arrive via raise callback. One such instance could be a OAuth2 authorization backend calling the token endpoint. A simplified example:

(defn handler [request respond raise]
  (future ; simulates non-blocking IO switching threads
    (try
      (throw-unauthorized) ; simplified example
      (catch Throwable t (raise t))))) ; raise any handler exceptions per Ring spec

(-> handler
    (wrap-authorization nil) ; backend doesn't get called anyway
    (apply {:request-method :get} println println nil)) ; run it
; => #ExceptionInfo
; expected: wrap-authorization to catch the raised exception
; and handle it with the backend

Possible fix

(defn wrap-authorization
  (fn
    ; [...]
    ([request respond raise]
     (try (handler request respond
           (fn [e] (try (respond (authorization-error request e backend))
                     (catch Throwable t (raise t))))
          (catch Exception e
            (respond (authorization-error request e backend)))))))

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions