Use Friend for authentication and authorisation in a single page Clojure web application

前端 未结 2 405
独厮守ぢ
独厮守ぢ 2021-02-06 01:47

I am trying to integrate Friend authentication and authorisation into a Clojure/Compojure single-page web application.

I have a login form backed by an Angular controlle

2条回答
  •  南方客
    南方客 (楼主)
    2021-02-06 02:43

    I've built a working solution to your issue. The key is to make sure you return a status, body, and merge the the authentication credentials into response. So you want to return

    {:status 200 :body {:message "Hello World"} 
     :session {:cemerick.friend/identity {...}} ...}
    

    The problem with the solution above is that it merges the session results into the body, instead of into ring response itself. Gist

    (defn- form-ajax-response 
      "Creates an Ajax Request.
       Authenticates User by merging authentication
       into response along with status and body allowing
       for ajax response."
      [status body resp auth content-type]
      (let [auth-resp (friend/merge-authentication (dissoc resp :body-params) auth)
            formatter (case content-type 
                        "application/edn" noir.response/edn
                        noir.response/json)]
        (merge auth-resp {:status status} (formatter {:body body}))))
    
    (def not-nil? (complement nil?))
    
    (defn form-or-ajax-login 
      "Friend Workflow for Handling forms or ajax requests posted to 
       '/login'.  When a form is posted, the request will initiate a redirect
       on login When the post is performed via ajax. A response will be sent
       with success and redirect information"
      [& {:keys [login-uri credential-fn login-failure-handler redirect-on-auth?] :as ajax-config
          :or {redirect-on-auth? true}}]
      (fn [{:keys [uri request-method content-type params] :as request}]
        (when (and (= :post request-method)
                   (= uri (gets :login-uri ajax-config (::friend/auth-config request))))
          (let [creds {:username (:username params) 
                       :password (:password params)}
                {:keys [username password]} creds
                ajax? (not-nil? (ajax-request-type content-type))
                cred-fn (gets :credential-fn ajax-config (::friend/auth-config request))]
            (when-let [user-record (and username password (cred-fn creds))]
              (let [user-auth (workflow/make-auth user-record {::friend/workflow :form-or-ajax
                                                               ::friend/redirect-on-auth? false})]
                (case ajax?
                  true (form-ajax-response 202 {:Tom "Peterman"} request user-auth content-type)
                  user-auth)))))))
    

提交回复
热议问题