1

I'm trying to use a rails api-ony app as back-end and React js as front-end. I'm using axios to send/ receive requests. Initially I wasn't able to even login then after much googling I came across this gem it was regarding CORS, it solved my POST request error.
I am able to successfully login when I do POST request in the rails app and I am getting token in return (Which works fine with POSTMAN app). Now, when I do GET request and pass that token as Header using react app it keeps on giving me 401 Unauthorized error, then again after much googling I saw this SO post. It didn't solved the issue. What am I missing? Kindly shed some light about the cause of this issue.
This is application_controller.rb:

class ApplicationController < ActionController::API
    include ActionController::MimeResponds

    before_action :authenticate_request, :current_user, :cors_preflight_check
    attr_reader :current_user

    #before_filter :current_user, :cors_preflight_check
  after_action :cors_set_access_control_headers

# For all responses in this controller, return the CORS access control headers.

def cors_set_access_control_headers
    headers['Access-Control-Allow-Origin'] = '*'
    headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
    headers['Access-Control-Request-Method'] = '*'
    headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
  headers['Access-Control-Max-Age'] = "1728000"
end

# If this is a preflight OPTIONS request, then short-circuit the
# request, return only the necessary headers and return an empty
# text/plain.

def cors_preflight_check
  if request.method == :options
        headers['Access-Control-Allow-Origin'] = '*'
        headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
        headers['Access-Control-Request-Method'] = '*'
        headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
    headers['Access-Control-Max-Age'] = '1728000'
    render :text => '', :content_type => 'text/plain'
  end
end

    require 'date'
            require 'json'
            require 'groupdate'

    @@PRESENT_DATE=Date.parse('2016-12-31T00:00:00.000Z')
    @@MONTHLY_SELECTOR="SELECT CONCAT(MONTHNAME(invoiceDate),' - ',YEAR(invoiceDate)), SUM(invoiceAmt) FROM invoices GROUP BY YEAR(invoiceDate), MONTH(invoiceDate)"
    @@QUARTERLY_SELECTOR="SELECT SUM(invoiceAmt) AS invoiceTotal, CONCAT('Q',QUARTER(invoiceDate), '(', YEAR(invoiceDate), ')') FROM invoices GROUP BY YEAR(invoiceDate), QUARTER(invoiceDate) ORDER BY YEAR(invoiceDate), QUARTER(invoiceDate)"
    @@YEARLY_SELECTOR="SELECT SUM(invoiceAmt) AS invoiceTotal, YEAR(invoiceDate) AS Year FROM invoices GROUP BY YEAR(invoiceDate) ORDER BY YEAR(invoiceDate)"

    private

    def authenticate_request
        @current_user = AuthorizeApiRequest.call(request.headers).result
        render json: { error: 'Not Authorized' }, status: 401 unless @current_user
    end
end

In my react app I have this:

import React, { Component } from 'react';
import '../App.css';
var axios = require('axios');

class Login extends Component {
  constructor(props){
    super(props);
    //this.state = {isToggleOn: true};
    this.loadDashboard = this.loadDashboard.bind(this);
    this.handleOnSubmit = this.handleOnSubmit.bind(this);
  }

  loadDashboard(token){
    axios({
      method:'get',
      url:'http://localhost:3000/api/dashboard',
      Authorization: {
        Authorization: token,
      },
    })
     .then(function (response) {
       console.log(response);
     })
     .catch(function (error) {
       console.log("Error in loading Dashboard "+error.response.status);
     });
  }

  handleOnSubmit = () => {
     console.log("submittwed");
     axios({
       method:'post',
       url:'http://localhost:3000/authenticate',
       data: {
         email: 'test@mail.com',
         password: 'apple'
       },
     })
      .then((response) => {
        var token = response.data.auth_token;
        console.log(token);
        this.loadDashboard(token);
      })
      .catch(function (error) {
        console.log("Error in login "+error);
      });
   }

  render() {
    return (
      <div>
         Username: <input type="email" name="fname" /><br />
         Password: <input type="password" name="lname" /><br />
         <button onClick={this.handleOnSubmit}>LOG IN</button>
      </div>
    );
  }
}

export default Login;      

Full header Response:

Request URL:http://localhost:3000/api/dashboard
Request Method:GET
Status Code:401 Unauthorized
Remote Address:127.0.0.1:3000
Referrer Policy:no-referrer-when-downgrade
Response Headers
view source
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:
Access-Control-Max-Age:1728000
Cache-Control:no-cache
Content-Type:application/json; charset=utf-8
Transfer-Encoding:chunked
Vary:Origin
X-Request-Id:f78a4c29-ef9a-446c-8771-9e2b70d41757
X-Runtime:0.045998
Request Headers
view source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Host:localhost:3000
Origin:http://localhost:3001
Referer:http://localhost:3001/
User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36

Rails version: Rails 5.1.3

  • Did any one else faced something similar??
  • How do I solve this?
  • Is there any less messy/better approach?

Please help me to solve this.

noobie
  • 751
  • 4
  • 13
  • 33
  • Don't you have to add the `Authorization` header in the `headers` key instead of `data`? – Hemerson Carlin Sep 11 '17 at 14:02
  • @HemersonCarlin I just did. It didn't worked though. Also updated my question – noobie Sep 11 '17 at 14:09
  • Please show the full error response. 401 could be various things, but the content body and headers will normally make it obvious. And please be sure to tag the correct Rails version. Are you really using Rails 3.x? – Fire Lancer Sep 11 '17 at 14:10

1 Answers1

2

You are missing the headers key to send to your api call.

axios({
  method:'get',
  url:'http://localhost:3000/api/dashboard',
  headers: {
    Authorization: `Bearer ${token}`,
  },
})
  .then(function (response) {
    console.log(response)
  })
  .catch(function (error) {
    console.log("Error in loading Dashboard "+error.response.status)
  })
Hemerson Carlin
  • 7,354
  • 1
  • 27
  • 38