0
votes

I am trying to use the friend-json-auth library with my app in tandem with compojure instead immutant as they have listed in their example app.

https://github.com/marianoguerra/immutant-recipes/tree/master/friend-json-auth

I am using angular as my client and I make this post request:

this.login = function ( username, password ) { return $http({
        method: 'POST',
        url: 'http://localhost:3000/api/session',
        headers: {
            'Content-Type': 'application/json',
            'Data-Type': 'json'
        },
        data: { username : "jane", password : "user_password" }
    }) };

but the reponse I get back is

POST http://localhost:3000/api/session 401 (Unauthorized)

Here is my POST endpoint for /api/session:

controller.clj

(ns recursiftion.controller
  (:use [ring.adapter.jetty :only [run-jetty]]
        [recursiftion.websocket :only [wamp-handler]]
        [recursiftion.config :only [conf]]
        [ring.middleware params keyword-params nested-params]
        [ring.util.response :only (redirect)]
        [cemerick.friend.util :only (gets)]
        [clojure.data.json :only (read-json json-str)]
        )
  (:require [compojure.core :refer :all]
            [compojure.handler :as handler]
            [compojure.route :as route]
            [clojure.java.io :as io]
            [ring.util.io :refer [string-input-stream]]
            [ring.util.response :as resp]
            [ring.util.response :refer [response]]
            [ring.middleware.json :as middleware]
            [ring.middleware.cors :refer [wrap-cors]]
            [environ.core :refer [env]]
            [cheshire.core :refer :all]
            [recursiftion.model :as model]
            [clojure.pprint :refer [pprint]]
            [cemerick.friend :as friend]
            (cemerick.friend [workflows :as workflows]
                             [credentials :as creds])
            [ring.middleware.session :as ring-session]
            [marianoguerra.friend-json-workflow :as json-auth]
            [ring.middleware.file :as ring-file]
            [ring.middleware.file-info :as ring-file-info]))


(defroutes app-routes

  (POST "/api/session" request 

      (let [node_object (or (get-in request [:params :data])
                            (get-in request [:body :data])
                            "ROUTER_ERROR")]

        (json-auth/handle-session request)))

)

(def app 
  (-> (handler/api app-routes)
      (middleware/wrap-json-body {:keywords? true})
      (middleware/wrap-json-response)
      (wrap-cors routes #"^http://localhost:9000$")))

(def users {"root" {:username "root"
                    :password (creds/hash-bcrypt "admin_password")
                    :roles #{::admin}}
            "jane" {:username "jane"
                    :password (creds/hash-bcrypt "user_password")
                    :roles #{::user}}})

(def secure-app
  (-> app
      (friend/authenticate
        {:login-uri "/friend-json-auth/api/session"
         :unauthorized-handler json-auth/unauthorized-handler
         :workflows [(json-auth/json-login
                       :login-uri "/friend-json-auth/api/session"
                       :login-failure-handler json-auth/login-failed
                       :credential-fn (partial creds/bcrypt-credential-fn users))]})
      (ring-session/wrap-session)))


(defn -main []
  (run-jetty app {:port (if (nil? (System/getenv "PORT"))
                          8000 ; localhost or heroku?
                          (Integer/parseInt (System/getenv "PORT")))}) )

project.clj

(defproject helloworld "1.0.0-SNAPSHOT"
  :description "csc358 final project"
  :url "http://localhost:9000/"
  :license {:name "FIXME: choose"
            :url "http://example.com/FIXME"}
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [compojure "1.1.8"]
                 [ring/ring-json "0.3.1"]
                 [ring/ring-core "1.4.0"]
                 [ring-router "0.2-SNAPSHOT"]
                 [ring/ring-jetty-adapter "1.3.2"]
                 [jumblerg/ring.middleware.cors "1.0.1"]
                 [c3p0/c3p0 "0.9.1.2"]
                 [org.clojure/java.jdbc "0.2.3"]
                 [cheshire "5.4.0"]
                 [environ "0.2.1"]
                 [hiccup "1.0.0"]
                 [clojurewerkz/neocons "3.1.0-rc1"]
                 [org.clojure/data.json "0.2.5"]
                 [clj-wamp "1.0.2"]
                 [clj-http "2.0.0"]
                 [com.cemerick/friend "0.2.1"]
                 [org.marianoguerra/friend-json-workflow "0.2.1"]]
  :min-lein-version "2.0.0"
  :plugins [[environ/environ.lein "0.2.1"]
            [lein-ring "0.7.3"]]
  :hooks [environ.leiningen.hooks]
  :profiles {:dev {:dependencies [[ring-mock "0.1.3"]]}}
  :ring {:handler recursiftion.controller/app})

I am very grateful for help you might be able to offer.

1

1 Answers

0
votes

On his example client he uses JSON.stringify to pass a JSON string as a map to the AJAX request. In your request you're passing a js object instead of a JSON string as the value of data:

https://github.com/marianoguerra/immutant-recipes/blob/master/friend-json-auth/resources/s/js/app.js

function login(username, password) {
        var data = JSON.stringify({"username": username, "password": password});

        return $.ajax({
            type: "POST",
            url: "api/session",
            dataType: "json",
            contentType: "application/json",
            data: data
        });
}