Error 403 when get request to server. Server contains core header - react-native

I'm running a server with clojure on localhost:3000. The server talks to the client, which is a react native app that's using axios to talk to the server. However the communication with the server is returning a 403 error.
Call to the server:
export const invest = (itemid, amount) => async dispatch => {
console.log("investing in actions")
const domain = 'localhost:3000'
const res = axios.post(domain + '/api/invest', {itemid: itemid, amount: amount});
console.log("response is", res)
dispatch({ type: INVESTED, payload:res.data});
}
Server contains a reitit route called "/api/invest", and this route will call a function called featured/invest. But instead I'm getting a 403 error in the client:
(ns humboiserver.routes.home
(:require
[humboiserver.layout :as layout]
[clojure.java.io :as io]
[humboiserver.middleware :as middleware]
[ring.util.response]
[ring.util.http-response :as response]
[humboiserver.routes.featured :as featured]))
(defn home-page [request]
(layout/render request "home.html" {:docs (-> "docs/docs.md" io/resource slurp)}))
(defn about-page [request]
(layout/render request "about.html"))
(defn home-routes []
[""
{:middleware [middleware/wrap-csrf
middleware/wrap-formats]}
["/" {:get home-page}]
["/api"
["/about" {:get about-page}]
["/featured" featured/get-featured]
["/invest" featured/invest]
]
])
Even the invested prn statement isn't printed in the logs.
;; featured/invest function.
(defn response [data & [status]]
{:status (or status 200)
:headers {"Content-Type" "application/json"
"Access-Control-Allow-Headers" "Content-Type"
"Access-Control-Request-Method" "GET, OPTIONS"
"Access-Control-Allow-Origin" "*"
"Access-Control-Allow-Credentials" true
}
:body (pr-str data)})
(defn invest [req]
(prn "invested")
(response (db/find "featured" {})))
403 error:
[Warning] Possible Unhandled Promise Rejection (id: 0): (AppEntry.bundle, line 42288)
Error: Request failed with status code 403
createError#http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:156390:26
settle#http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:156380:25
handleLoad#http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:156280:15
dispatchEvent#http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:32753:31
setReadyState#http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:31822:27
__didCompleteResponse#http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:31653:29
emit#http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:7566:42
__callFunction#http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:3195:36
http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:2927:31
__guard#http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:3149:15
callFunctionReturnFlushedQueue#http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:2926:21
callFunctionReturnFlushedQueue#[native code]
http://localhost:19000/debugger-ui/debuggerWorker.aca173c4.js:4:907
How to fix this error?

Hi I think you need to send an Anti-forgery token if I'm not mistaken...
https://github.com/ring-clojure/ring-anti-forgery
You can use curl to test accessing your server via the command line

Related

Clojure httpkit spotify request

Following my last question, but to keep the code homogeneous I want to use httpkit to make requests instead of clj-http as I did before.
I have the following to try and receive my profile from the Spotify API:
(defn get-me [token]
#(client/request
{:url "https://api.spotify.com/v1/me"
:method :get
:headers {"Authorization" token
"Accept" "application/json"
"Content-Type" "application/json"}}))
(defn get-me-handler [req]
(let [res (:token #TOKEN)]
(if (= res "")
{:status 404
:headers {"Content-Type" "text/html"}
:body "Not logged in"}
{:status 200
:headers {"Content-Type" "text/html"}
:body (get-me (get (json/read-str res) "access_token"))})))
a long with a "localhost:{port}/me" route. When I access this route, I get back:
{"status": 400, "message": "Only valid bearer authentication supported" }}"
As the error message. Does anyone know how to fix this in httpkit, as it is not a problem I had in clj-http?

Axios get request works but post request returns callFunctionReturnedFlushedQueue and Network Error

I'm calling a route with axios that I want to really call as a post request. However, when calling with a post request like so:
export const uploadFeatured = (mediaName, youtubeLink, description) => async dispatch => {
console.log("uploading", mediaName, youtubeLink, description);
const res = await axios.post(domain + '/api/uploadFeatured');
}
I'm getting an error:
rror: Request failed with status code 403
createError#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:156601:26
settle#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:156591:25
handleLoad#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:156491:15
dispatchEvent#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:33005:31
setReadyState#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:32074:27
__didCompleteResponse#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:31905:29
emit#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:7758:42
__callFunction#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:3387:36
http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:3119:31
__guard#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:3341:15
callFunctionReturnFlushedQueue#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:3118:21
callFunctionReturnFlushedQueue#[native code]
However, get request works without any error. Here's my clojure code for the routes and the server for request handling:
(ns humboiserver.routes.home
(:require
[humboiserver.layout :as layout]
[clojure.java.io :as io]
[humboiserver.middleware :as middleware]
[ring.util.response]
[ring.util.http-response :as response]
[humboiserver.routes.featured :as featured]))
(defn home-page [request]
(layout/render request "home.html" {:docs (-> "docs/docs.md" io/resource slurp)}))
(defn about-page [request]
(layout/render request "about.html"))
(defn home-routes []
[""
{:middleware [middleware/wrap-csrf
middleware/wrap-formats]}
["/" {:get home-page}]
["/api"
["/about" {:get about-page}]
["/featured" featured/get-featured]
["/invest" featured/invest]
["/connect" featured/connect]
["/uploadFeatured" featured/upload-featured]]])
and
(defn response [data & [status]]
{:status (or status 200)
:headers {"Content-Type" "application/edn"
"Access-Control-Allow-Headers" "Content-Type"
"Access-Control-Request-Method" "GET, OPTIONS, POST"
"Access-Control-Allow-Origin" "*"
"Access-Control-Allow-Credentials" true
}
:body (generate-string data)})
(defn upload-featured [req]
(prn "request is " (:params req))
;;(db/insert "featured" (:params req))
(response "uploaded")
)
How to fix this error and what am I doing wrong?
You seem to be getting a 403 Forbidden response when POST-ing, GET is fine, but POST seems to be forbidden. When the server/client do not run on the same host/origin, some CORS restrictions may apply. Somewhere you define response headers:
"Access-Control-Request-Method" "GET, OPTIONS"
Maybe adding 'POST' to this response header might resolve the situation.

How can I add custom header parameters to a API GET call in clojurescript

I'm building a demo application in clojurescript with KeeFrame and to retrieve a part of the information for this website I need to call an external API which requires a custom HTTP header parameter in the GET requests
I'm using re-frame.core for the API calls, which uses ajax.core.
I also tried to replace this with cljs-http.client. However the result is the same.
I already managed to add custom header parameters to the request header by using clj-http at server site. But this is not a solution I want to implement for this website because that means that I first have to rebuild the API I'm calling. So I can use it from my clojurescript without the parameter.
This code works. A correct GET request is generated
{:http-xhrio {
:method :get
:uri (str transuri "/acquirer/" 673072009 "/acquirerref/" acquirerRefNo)
:headers {"Accept" "application/json"}
:response-format (http/json-response-format {:keywords? true})
:on-failure [:common/set-error]}}
With "Accept: application/json" as a request header
This code does not work. Instead of a GET request an OPTIONS request is generated
{:http-xhrio {
:method :get
:uri (str transuri "/acquirer/" 673072009 "/acquirerref/" acquirerRefNo)
:headers {"Accept" "application/json" "Custom" "Value"}
:response-format (http/json-response-format {:keywords? true})
:on-failure [:common/set-error]}}
And in the request header "Accept: application/json" is not visible but "Access-Control-Request-Headers: custom" is
I expected a GET request with "Accept: application/json" and "Custom: Value" in the request header.
Can someone tell me what I'm doing wrong or provide me with a link with information about this?
Thanks in advance
The Browser will send a "preflight" OPTIONS request to verify that it is allowed to send the "Custom" request header. The server is supposed to approve by replying with "Access-Control-Allow-Headers".
See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
I have not used KeeFrame, but I have a working example using a new re-frame lib I'm working on. It invokes an ajax request using this interceptor:
(def ajax-intc
"Interceptor for performing AJAX requests"
(interceptor
{:id :ajax-intc
:enter identity
:leave (fn [ctx] ; #todo (with-result ctx ...)
(let [ajax (:ajax ctx)]
;(t/spyx :ajax-intc-start ctx)
;(t/spyx :ajax-intc-start ajax)
(when-not (nil? ajax)
(t/spy :awt-ajax-intc--ajax ajax)
(let [method (t/grab :method ajax)
uri (t/grab :uri ajax)
ajax-opts-present (set/intersection (set (keys ajax)) ajax-options-keys)
opts-map (t/submap-by-keys ajax ajax-opts-present)]
;(t/spy :ajax-intc-ready (t/vals->map method uri opts-map))
(condp = method
:get (do
(t/spy :awt-ajax-intc--opts-map opts-map)
(ajax/GET uri opts-map))
:put (ajax/PUT uri opts-map)
:post (ajax/POST uri opts-map)
(throw (ex-info "ajax-intc: unrecognized :method" ajax))))))
ctx)}))
When invoked with this event:
(flame/dispatch-event [:ajax-demo :get "/fox.txt"
{:handler ajax-handler
:error-handler ajax-error-handler
:headers {"custom" "something"}
}])
one can see in the Chrome dev console that the headers come through:
:awt-localstore-load-intc--loaded-value-1 {}
core.cljs:192 :awt-ajax-intc--ajax => {:method :get, :uri "/fox.txt", :handler #object[flintstones$core$ajax_handler], :error-handler #object[flintstones$core$ajax_error_handler], :headers {"custom" "something"}}
core.cljs:192 :awt-ajax-intc--opts-map => {:handler #object[flintstones$core$ajax_handler], :error-handler #object[flintstones$core$ajax_error_handler], :headers {"custom" "something"}}
If you want to try it out, you can clone this repo: git#github.com:cloojure/cljs-enflame.git
and then run:
lein clean
lein figwheel
and see it run in the browser.

Devise Token Auth / Angular2-Token, update password, Completed 401 Unauthorized

I'm having troubles restoring password with devise_token_auth. and Angular2-Token. I'm successfully receiving the email with the link to update my password. But I'm getting an 401 Unauthorized response when submiting the new password.
Front end. I'm getting the token from the URL with urlParams.get('token')
onPasswordUpdate() {
let token = this.urlParams.get('token');
var obj = Object.assign(this._updatePasswordData, { reset_password_token: token })
this._tokenService.patch('auth/password/', obj ).subscribe(
res => res,
error => error
);
}
Back end response.
Started PATCH "/api/auth/password/" for 127.0.0.1 at 2016-12-01 21:17:48 +0100
Processing by DeviseTokenAuth::PasswordsController#update as JSON
Parameters: {"reset_password_token"=>"[FILTERED]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}
Completed 401 Unauthorized in 1ms (Views: 0.4ms | ActiveRecord: 0.0ms)
In the link of the email I get the following token : reset_password_token=HneZDoKTMCLF3_SLfnxy
When I visit the link, the user record gets updated with the following attributes :
reset_password_token: "aa3cba76c7b1d8f78cde6856f43e1cce57f5fc8e5301842733de677eff909bc1"
tokens: {}
Then in the browser URL I get the following token=agejaip2SqOp9nvwE1GAHQ&uid
And then the user record get updated with the following attribues :
...
reset_password_token: "HneZDoKTMCLF3_SLfnxy",
tokens: {"pv9i1BDTM29ezep0KSPzpA"=>{"token"=>"$2a$10$cS9gbe9UBICcgphZHRAENOMS6NlEe0Em1cNufY3LSRTPE.hRMabvi", "expiry"=>1481834221}}
...
It seems to me that the token I get back in URL is not correct.
Those anyone have an idea ?
Sorry It's a bit hard to explain.
Many thanks.
rails (4.2.4)
devise_token_auth (0.1.34)
devise (= 3.5.1)
angular2-token: 0.2.0-beta.1
I faced similar challenges recently, and this was how I solved it.
Expose the 'access-token', 'expiry', 'token-type', 'uid', 'client' for your backend. Check here and here
config.middleware.use Rack::Cors do
allow do
origins '*'
resource '*',
:headers => :any,
:expose => ['access-token', 'expiry', 'token-type', 'uid', 'client'],
:methods => => [:get, :post, :options, :delete, :put, :patch]
end
end
Set your redirect_url of path: /password, method: POST. Check info here
We need to modify the reset_password_instructions.html.erb to point it to the api GET /auth/password/edit. More information provided here.
E.g. if your API is under the api namespaces:
<%= link_to 'Change my password', edit_api_user_password_url(reset_password_token: #token, config: message['client-config'].to_s, redirect_url: message['redirect-url'].to_s) %>

Testing static routes in compojure

I am trying to write a test for the compojure static content route.
I am testing the routes by examining the ring response directly.
A minimal working example is as follows:
;; src/testing-webapps.core.clj
(ns testing-webapps.core
(:use [compojure.core]
[compojure.route :as route]))
(defroutes web-app
(route/resources "/")
(route/not-found "404"))
;; test/testing-webapps.core_test.clj
(ns testing-webapps.core-test
(:require [clojure.test :refer :all]
[testing-webapps.core :refer :all]))
(defn request [resource web-app & params]
(web-app {:request-method :get :uri resource :params (first params)}))
(deftest test-routes
(is (= 404 (:status (request "/flubber" web-app))))
(is (= "404" (:body (request "/flubber" web-app))))
(is (= 200 (:status (request "/test.txt" web-app)))))
Testing the 404 route works fine but calling (request "/test.txt" web-app) leads to an unexpected NullPointerException in ring.middleware.file-info/not-modified-since?.
Here is the top part of the stacktrace:
ERROR in (test-routes) (file_info.clj:27)
Uncaught exception, not in assertion.
expected: nil
actual: java.lang.NullPointerException: null
at ring.middleware.file_info$not_modified_since_QMARK_.invoke (file_info.clj:27)
ring.middleware.file_info$file_info_response.doInvoke (file_info.clj:44)
clojure.lang.RestFn.invoke (RestFn.java:442)
ring.middleware.file_info$wrap_file_info$fn__917.invoke (file_info.clj:64)
[...]
The static route works fine in the browser but not when called through my request function.
Is there an easier way to test a static route in compojure and why do I get a NullPointerException when calling the static route with my own request map?
Looking at the source for not-modified-since?, I think the issue is you have no headers in your request map, so it throws a NPE on this expr: (headers "if-modified-since"). Try changing your request method like so:
(defn request [resource web-app & params]
(web-app {:request-method :get
:headers {"content-type" "text/plain"} ; added a header
:uri resource
:params (first params)}))
You might also consider using ring-mock to create requests for testing. It insulates you a little bit from stuff like this.