Search code examples
clojureclojurescriptre-frame

Implementing a login system with re-frame


I am new to re-frame and not quite sure how to build a user authentication/authorization system with it.

From what I gathered I should create an auth interceptor and place my auth logic inside :before section then inject the interceptor into every events reg-event-db and reg-event-fx that I want to protect.

Am I on the right track?


Solution

  • Not sure if my solution is particularly idiomatic, but I used something like the following in one of my projects. Consider it a Works For Me.

    Create a map for the ajax request with a special value for error cases (ignore the context-uri function):

    (defn xhrio-map [method path format success-event]
      {:method          method
       :uri             (context-uri path)
       :timeout         5000
       :response-format format
       :on-success      [success-event]
       :on-failure      [::ajax-failure]})
    

    Then I use an fx handler for the failure (this is a bit more complicated as it also handles a loading indicator):

    (rf/reg-event-fx
     ::ajax-failure
     (fn [{:keys [db]} [_ http-result]]
       (if (= 403 (:status http-result))
         {:db (assoc db :loading-indicator nil)
          :dispatch [::logout]}
         {:db (assoc db :loading-indicator nil)
          :dispatch
          [::error-msg (str "Error fetching from " (:uri http-result)
                            ": " (:response http-result))]})))
    

    The ::logout events sets the document location. This also triggers the logout in the backend.

    (rf/reg-event-fx
     ::logout
     (fn [coefx [ev]]
       {::location "./logout"}))
    

    Finally, the loading of resources works like this:

     (defn load-with-indicator [db xhrio-data]
      {:db (assoc db :loading-indicator true)
       :http-xhrio xhrio-data})
    
    (rf/reg-event-fx
     ::load-documentation
     (fn [{:keys [db]} _]
       (load-with-indicator
        db
        (xhrio-map :get "documentation/"
                   (ajax/json-response-format {:keywords? true})
                   ::received-documentation))))
    

    The :received-documentation is handled by some code which invokes the correct display functions.

    This uses the day8.re-frame/http-fx and ajax.core

    On the backend, I use something similar to the demo code I published over at https://github.com/ska2342/ring-routes-demo.

    Hope that helps.

    License of the code in this post

    In addition to the default license of the StackOverflow site, I also publish these lines under the Eclipse Public License either version 1.0 or (at your option) any later version.