2

I am pretty new to ReactJS.

I am using Chrome browser.

I am trying to create the sign in page using ReactJS. The page is simple with user id and password. Authentication happens on our SSO server, means I have to post data on the server using fetch call and get access_token as a response.

The problem is as below:

I am not getting response in the console. However, when I look at the Network tab on developer tools, I can see that there is a valid response with all required field including access_token in it. Now sure how should I parse this.

Is this because fetch is async call?

Here is my entire page code.

P.S: some of the code is not getting formatted.

import React, {Component} from 'react';
import '../App/App.css';
import {FormGroup, FormControl, InputGroup} from 'react-bootstrap';

class Auth extends Component {


    constructor(props) {
        super(props);
        this.state = {
            userid: '',
            password: '',
            accessToken: ''
        }
    }

    submit() {
        console.log('state', this.state);
        const BASE_URL = 'MY SSO URL';
        const params = {
            'grant_type': 'password',
            'username': this.state.userid,
            'password': this.state.password,
            'client_secret': 'secred',
            'client_id': 'client_id',
        };
        const formData = new FormData();
        for (let p in params) {
            formData.append(p, params[p]);
        }
        const headers = {
            'Access-Control-Allow-Origin': '*'
        };
        const request = {
            method: 'POST',
            headers: headers,
            body: formData,
            mode: 'no-cors'
        };

        fetch(BASE_URL, request)
            .then((response) => response.text())
            .then((responseText) => {
                console.log('text',responseText);
            })
            .catch((error) => {
                console.warn(error);
            });
        console.log('all done');
    }

    render() {
        return (
            <div className="login">
                <div className="legend">Signin</div>
                <FormGroup>
                    <InputGroup>
                        <div className="input">
                            <FormControl
                                type="text"
                                placeholder="Enter User Id or email"
                                onChange={event => this.setState({userid: event.target.value})}
                                onKeyPress={
                                    event => {
                                        if (event.key === 'Enter') {
                                            this.submit()
                                        }
                                    }}
                            />
                        </div>
                        <div className="input">
                            <FormControl
                                type="password"
                                placeholder="enter password"
                                onChange={event => {
                                    console.log(event.target.value)
                                    this.setState({password: event.target.value})
                                }}
                                onKeyPress={
                                    event => {
                                        if (event.key === 'Enter') {
                                            this.submit()
                                        }
                                    }}
                            />
                        </div>
                        <FormControl
                            type="submit"
                            onClick={() => this.submit()}
                        />
                    </InputGroup>
                </FormGroup>
            </div>
        )
    }
}
export default Auth;

I tried response.json() this gives error as: Unexpected end of input.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
artofabhishek
  • 275
  • 1
  • 4
  • 9

1 Answers1

4

As far are your frontend JavaScript code for the fetch(…) request:

mode: 'no-cors'

Remove that. That’s the exact reason your code can’t access the response.

You never, ever want to do mode: "no-cors". The only thing that actually does is to tell the browser, Never let my frontend JavaScript code access the response from this request.

const headers = {
    'Access-Control-Allow-Origin': '*'
};

Remove those lines too. Access-Control-Allow-Origin is a response header. You never want to send it in a request. The only effect that’ll have is to trigger a browser to do a preflight.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests

I’m guessing that the reason you’re trying mode: 'no-cors' and sending Access-Control-Allow-Origin in the request is that you earlier tried the request without those and you got an error message in the browser console saying that the response lacked Access-Control-Allow-Origin.

If so, there’s no way you can get around that by making changes to your frontend JavaScript code—except by changing your code to instead make the request through a proxy, as outlined in the answer at "No 'Access-Control-Allow-Origin' header is present on the requested resource".

Either that or you need to get the owner of the server at your BASE_URL address to configure the server to send the Access-Control-Allow-Origin in its responses.


Here’s a longer explanation:

Your browser will only let your frontend JavaScript code access responses from cross-origin requests when the servers you’re making the requests to explicitly indicate they’re opting in to receiving cross-origin requests, which they do by sending the Access-Control-Allow-Origin response header in their responses.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS has more details.

Browsers are the only clients that enforce restrictions on cross-origin requests, and they only enforce them on web applications.

That’s why even when you see a No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin … is therefore not allowed access message in your devtools console, you’ll still be able to go to the Network tab in devtools and view the response there.

That’s because the server has sent the response and the browser has received it, but the browser is just refusing to allow your frontend JavaScript code to access the response due to the fact the server sending the response hasn‘t opted into to cross-origin requests by sending the Access-Control-Allow-Origin response header.

The reason you can get the response just fine when you make the request from curl, etc., is that no client other than browsers will refuse to allow your code to access the response if it lacks the Access-Control-Allow-Origin response header. But browsers always will.

And note that in none of this is the server doing any blocking or refusing to respond to any requests. The server always continues to just receive requests and send responses. The only difference is in whether the server sends the Access-Control-Allow-Origin header in the response, or not.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
  • Thanks and you are spot on in terms of use of no-cors and header 'Access-Control-Allow-Origin': '*' and if I dont use these I am getting error. But my curl command is working fine no issues there hence I am bit puzzled whats missing in my front end code. – artofabhishek May 10 '17 at 05:09
  • This is what I get if I remove header and no-cors "No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. But curl is all good, no issues there. – artofabhishek May 10 '17 at 05:21
  • So yeah the problem is that the BASE_URL server isn’t sending the Access-Control-Allow-Origin response header. I updated the answer above to add a longer explanation. The reason it works in curl is that curl doesn’t doesn’t change its behavior based on whether or not it finds the the Access-Control-Allow-Origin response header. But browsers do. – sideshowbarker May 10 '17 at 05:35