   (error-page
     {:status 403
      :title (str "Access to " (:uri request) " is not authorized")}))
+
+;; https://learning.oreilly.com/library/view/web-development-with/9781680508833/f_0048.xhtml#:-:text=get-roles-from-match
+(defn get-roles-from-match [request]
+  (let [request-method (:request-method request)]
+    (-> request (ring/get-match) (get-in [:data request-method :authorized] #{}))))
+
+(defn- get-roles-from-identity [request]
+  (->> (get-in request [:identity :user :roles])
+       ;; unfortunately the jws-backend parses the token as json and
+       ;; hence ignores keywords and sets. So we have to reconstruct
+       ;; those here
+       (map keyword)
+       set))
+
+(defn authorized?
+  "Return true if the roles of the identity in `request` intersect with
+  the `roles` defined in the router. So if an identity has no roles it
+  will never be authorized."
+  [request]
+  (let [route-roles (get-roles-from-match request)
+        request-roles (get-roles-from-identity request)]
+    (some? (seq (intersection route-roles request-roles)))))
+
+(defn wrap-authorized [handler]
+  (restrict handler {:handler authorized?
+                     :on-error on-error})  )
 
 (defn wrap-restricted [handler]
   (restrict handler {:handler authenticated?

       {:status 403
        :title "Invalid anti-forgery token"})}))


(defn wrap-formats [handler]
  (let [wrapped (-> handler wrap-params (wrap-format formats/instance))]
    (fn [request]

    [buddy.auth.middleware :refer [wrap-authentication wrap-authorization]]
    [buddy.auth.accessrules :refer [restrict]]
    [buddy.auth :refer [authenticated?]]
    [buddy.auth.backends.token :refer [jws-backend]]
    [clojure.set :refer [intersection]]
    [reitit.ring :as ring])
  )

(defn wrap-internal-error [handler]
