pierre_web_dev
pierre_web_dev

Reputation: 23

401 Unauthorized error when making requests to rails api on heroku

I just deployed my first app to heroku and it used a Rails API (backend) and a React frontend. When I deployed my app I get 401 unauthorized errors whenever I try to make a request that involves the use of a JSON Web Token(JWT). I am sending the token from localstorage in my app and everything worked fine when I was sending it in my development environment. I only have this issue in production.

When I make the fetch request from my frontend and send over my JWT to my backend, I get the following messages in my heroku server logs:

2020-11-29T04:45:31.742735+00:00 app[web.1]: I, [2020-11-29T04:45:31.742670 #4]  INFO -- : [f3c19eae-e431-4c9f-b93b-7499797f2c03] [active_model_serializers] Rendered ActiveModel::Serializer::Null with Hash (0.13ms)
2020-11-29T04:45:31.742984+00:00 app[web.1]: I, [2020-11-29T04:45:31.742919 #4]  INFO -- : [f3c19eae-e431-4c9f-b93b-7499797f2c03] Filter chain halted as :authorized rendered or redirected
2020-11-29T04:45:31.744091+00:00 app[web.1]: I, [2020-11-29T04:45:31.744019 #4]  INFO -- : [f3c19eae-e431-4c9f-b93b-7499797f2c03] Completed 401 Unauthorized in 2ms (Views: 0.7ms | Allocations: 218)

Another strange thing about this is that I get an error message along with the 401 status error in my React frontend that tells me to Please Log in even though I logged into my app to receive a token from my backend before I even attempted to make another fetch request

Below I will post other relevant code snippets so that you can see what I was trying to do

Here is the Code in my frontend that sends the request

 addToCart = () =>{
      //make a fetch request to add the item in the customer's current cart
      fetch("https://health-and-fit-store-api.herokuapp.com/cart_products",{
          method:"POST",
          headers:{
            "Authorization": localStorage.token,
            "Content-Type":"application/json",
            Accept:"application/json"
          },
          body:JSON.stringify({
            productId :this.props.id
          })
      })
      .then(res => res.json())
      .then(data => {
        this.props.addToCart(data)
        toast.dark(`Added ${data.product.name.toLowerCase()} to your cart`)
      })
  }

Here is the code in my Rails API that receives the request

before_action :authorized, only: [:create,:delete]
    def create
       #will be receiving token in fetch request
        #use the of the current cart and the product id passed in by the post request
        current_cart = @customer.carts.find_by(checked_out:false)
        product = Product.find(params[:productId])

        new_cart_product = CartProduct.create(cart:current_cart,product:product, quantity:1)
        render json: new_cart_product
    end

Here is the code from my application controller that I used to set up JWT

class ApplicationController < ActionController::API
    def encode_token(payload)
        # should store secret in env variable
        JWT.encode(payload, ENV['jwt_encode_string'])
        #byebug
      end
     
      def auth_header
        # { Authorization: 'Bearer <token>' }
        request.headers['Authorization']
      end
     
      def decoded_token
        if auth_header
          token = auth_header
          # header: { 'Authorization': '<token>' }
          begin
            JWT.decode(token, ENV['jwt_encode_string'], true, algorithm: 'HS256')
          rescue JWT::DecodeError
            nil
          end
        end
      end
     
      def logged_in_customer
        if decoded_token
          customer_id = decoded_token[0]['customer_id']
          @customer = Customer.find_by(id: customer_id)
        end
      end
     
      def logged_in?
        !!logged_in_customer
      end
     
      def authorized
        render json: { error_message: 'Please log in' }, status: :unauthorized unless logged_in?
      end
end

If anyone can help me out with this, I would really appreciate it, I've been stuck on this for days. Also please note that I have checked out every other post involving this issue on StackOverflow and have exhausted every kind of search on Google that I could think of.

Upvotes: 0

Views: 1900

Answers (1)

pierre_web_dev
pierre_web_dev

Reputation: 23

thanks to @snake, I actually ended up solving this issue. The problem wasn't with the token I was using, but their suggestion led me to go back and check out my fetch requests to the api endpoint and I had an extra comma at the end of the request that was causing the 401 status code error.

Once I fixed that, everything worked beautifully.

Upvotes: 1

Related Questions