I am hosting the backend of my application on Heroku and my frontend on Firebase (subdomain hosted by Firebase).
When I try to log in to my application, I get:
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
In my Heroku logs I am noticing that I also get this error: Filter chain halted as :authorize rendered or redirected
Here is my ApplicationController:
class ApplicationController < ActionController::API
include ActionController::Cookies
rescue_from ActiveRecord::RecordInvalid, with: :render_unprocessable_entity_response
before_action :authorize
private
def authorize
@current_user = User.find_by(id: session[:user_id])
render json: { errors: ['Not authorized'] }, status: :unauthorized unless @current_user
end
def render_unprocessable_entity_response(exception)
render json: { errors: exception.record.errors.full_messages }, status: :unprocessable_entity
end
end
I also have rack CORS installed and configured as such:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins "*"
resource "*",
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
Function to log in:
function handleSubmit(e) {
e.preventDefault();
setIsLoading(true);
fetch("https://safe-depths-80660.herokuapp.com/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
},
body: JSON.stringify({ username, password }),
}).then((r) => {
setIsLoading(false);
if (r.ok) {
r.json().then((user) => onLogin(user));
} else {
r.json().then((err) => setErrors(err.errors));
}
});
}
Login action:
def create
user = User.find_by(username: params[:username])
if user&.authenticate(params[:password])
session[:user_id] = user.id
render json: user
else
render json: { errors: ['Invalid username or password'] }, status: :unauthorized
end
end
I know origins * is bad, but am trying it for testing purposes. Please let me know if you have any ideas!
CodePudding user response:
The second log entry is normal as before filter halts execution in case @current_user is empty which seems to be part of authentication logic.
Double check in which line the JSON parsing is occurring and in which action. That should lead you to the root cause.
CodePudding user response:
It would be helpful to see the full server side error log and the form view. However, my hunch here is actually the error is happening before the login controller is hit. Rather, I think your request may be missing the authenticity token. Because you're posting the form via AJAX instead of the form handler, you'll need to manually add it to the headers of your request. Something like this may work
function handleSubmit(e) {
e.preventDefault();
setIsLoading(true);
fetch("https://safe-depths-80660.herokuapp.com/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content // This is the authenticity token
},
body: JSON.stringify({ username, password }),
}).then((r) => {
setIsLoading(false);
if (r.ok) {
r.json().then((user) => onLogin(user));
} else {
r.json().then((err) => setErrors(err.errors));
}
});
}