Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React JS - How to authenticate credentials via a fetch statement

My goal is to create a React JS login page that runs off a json Rest service. In Postman, when I enter the URL for the service, set it to run as POST and enter the following JSON into the body: {username: "myUserName", password: "myPassword"} ...a token is returned. So in my fetch clause, I'm using JSON.stringify to pass the username and password to the server.

I'm new to using Fetch with react, So my question is, how do I get started in authenticating various users, just using react JS with fetch only? I assume, I'm to write my logic within the second then of my Fetch clause?

Currently, my page accepts any credentials and routes the user to a landing page upon clicking the submit button. I have a function containing fetch and now calling the fetch function once the onSubmit button is clicked, which now grabs the token.

This is my code:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './Login.css';
import { withRouter } from 'react-router-dom';

class Login extends Component {

    constructor() {
        super();
        this.state = {
            data: [],
            username: "",
            password: "",
            token: "",
        };
    } //end constructor

    componentWillMount() {
    }

    componentDidMount() {
        this.fetchData();
    }

    fetchData() {
        fetch('http://theapi/api/auth', {
            method: 'POST',
            headers: {
                'Content-type': 'application/json',
            },
             body: JSON.stringify({
                username: 'myUserName',
                password: 'myPassword',
                Authorization: 'TheReturnedToken',
            })
        }) /*end fetch */
        .then(results => results.json())
        .then(data => this.setState({ data: data })

        )
    }

    //request the token
      requestAccessToken(data) {
        const loginInfo = '${data}&grant_type=password';
        return fetch('${API_URL}Token', {
          method: 'POST',
          headers: new Headers({
            'Content-Type': 'application/json',
          }),
          body: loginInfo,
        })
          .then((response) => response.json());
      }

      //authenticate request
      requestUserInfo(token) {
        return fetch('${API_URL}api/participant/userinfo', {
          method: 'GET',
          headers: new Headers({
            Authorization: 'Bearer ${token}',
          }),
        })
          .then((response) => response.json());
      }

    change = (e) => {
        this.setState({
            [e.target.name]: e.target.value
        });
    }; //end change

    onSubmit = (e) =>{
        this.fetchData();
        e.preventDefault();
        //console.log(this.state);
        this.setState({
             username: "",
             password: "",
            });

        this.props.history.push('/landing');
        };

    render() {
    console.log(this.state.data);
        return (
           <div>
                <div className="loginContainer">
                <h2>Member Login</h2>
                    <form>
                            <input
                            id="username"
                            name="username"
                            placeholder="User Name"
                            value={this.state.username}
                            onChange={e => this.change(e) }
                            className="form-control"
                            />  <br />

                            <input
                            id="password"
                            name="password"
                            type="password"
                            placeholder="Password"
                            value={this.state.password}
                            onChange={e => this.change(e) }
                            className="form-control"
                            />  <br />

                        <button onClick={e => this.onSubmit(e)} className="btn btn-primary">Submit</button>
                        </form>
                    </div>
            </div>
        );
      }
}

export default withRouter(Login);

How do I get started in getting my form to authenticate various users? Basically, I'm attempting to have my page to accept a username and password and if the two match, and then route the user to a landing page.

like image 828
user1724708 Avatar asked May 10 '18 14:05

user1724708


1 Answers

Don't put your authorization token in the body. Put it in the Headers. The first function is going to pass in username, password, and authentication type (ie grant_type=password). Then my second function is going to use that to authenticate the request. There is no longer a need to pass any user information, because my api knows who is requesting based on the token that is passed in. The current documentation for OAuth 2.0 is here, and you can find more information about using headers with fetch at Mozilla's fetch documentation.

// request the token
// subscribe to this event and use the returned json to save your token to state or session storage
export function requestAccessToken(data) {
  const loginInfo = `${data}&grant_type=password`;
  return fetch(`${API_URL}Token`, {
    method: 'POST',
    headers: new Headers({
      'Content-Type': 'application/x-www-form-urlencoded',
    }),
    body: loginInfo,
  })
    .then((response) => response.json());

    // in your case set state to returned token
}

// use said token to authenticate request
export function requestUserInfo(token) {
  return fetch(`${API_URL}api/participant/userinfo`, {
    method: 'GET',
    headers: new Headers({
      Authorization: `Bearer ${token}`,
    }),
  })
    .then((response) => response.json());
}

I would also recommend:

  1. Calling fetch from a thunk or a saga, but this is out of scope of the question.

  2. No need to put your token in a hidden field. Which is still accessible btw. Just keep it in state. There are other things you can do to secure it a little, but this too, is out of scope of the question.

like image 88
Jay Jordan Avatar answered Sep 29 '22 01:09

Jay Jordan