6

const form = {
        firstname: "",
        lastname: "",
        email: "",
        password: "",
        gender: "",
        dob: "",
        username: ""
};

export default class Login extends React.Component {
  constructor (props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.state = {
    }
  }

  handleSubmit (event) {
    event.preventDefault();
    api.signin(this.state)
  }

  handleChange (event, type) {
    form[type] = event.target.value;
    this.setState({
      form
    })
  }

  render() {
    return (
      <div>
        <nav className="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
          <a className="navbar-brand" href="#">ChatBox</a>
          <button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault">
            <span className="navbar-toggler-icon"></span>
          </button>

          <div className="collapse navbar-collapse" id="navbarsExampleDefault">
            <ul className="navbar-nav mr-auto">
              <li className="nav-item active">
                <a className="nav-link" href="#">Home <span className="sr-only">(current)</span></a>
              </li>
              <li className="nav-item">
                <a className="nav-link" href="#">Link</a>
              </li>
              <li className="nav-item">
                <a className="nav-link" href="#">Disabled</a>
              </li>
              <li className="nav-item dropdown">
                <a className="nav-link dropdown-toggle" href="http://example.com" id="dropdown01" data-toggle="dropdown">Dropdown</a>
                <div className="dropdown-menu" aria-labelledby="dropdown01">
                  <a className="dropdown-item" href="#">Action</a>
                  <a className="dropdown-item" href="#">Another action</a>
                  <a className="dropdown-item" href="#">Something else here</a>
                </div>
              </li>
            </ul>
          </div>
        </nav>
        <main role="main" className="container">
          <div className="starter-template">
            <h1>Register for ChatBox</h1>
            <form >
              <div className="d-flex justify-content-center bd-highlight mb-3">
                <div className="p-2">
                  <label htmlFor="firstname">First Name</label>
                  <input type="text" className="form-control" id="firstname" placeholder="First Name" onChange={
                    (e)=>{ this.handleChange(e, 'firstname')}
                  }/>
                </div>
                <div className="p-2">
                  <label htmlFor="lastname">Last Name</label>
                  <input type="text" className="form-control" id="lastname" placeholder="Last Name" onChange={
                    (e)=>{ this.handleChange(e, 'lastname')}
                  } />
                </div>
              </div>
              <div className="form-group col-md-6">
                <label htmlFor="inputEmail4">Email</label>
                <input type="email" className="form-control" id="inputEmail4" placeholder="Email" onChange={
                    (e)=>{ this.handleChange(e, 'email')}
                  }/>
              </div>
              <div className="form-group col-md-6">
                <label htmlFor="username">Username</label>
                <input type="text" className="form-control" id="username" placeholder="Username" onChange={
                    (e)=>{ this.handleChange(e, 'username')}
                  }/>
              </div>
              <div className="form-group col-md-6">
                <label htmlFor="inputPassword4">Password</label>
                <input type="password" className="form-control" id="inputPassword4" placeholder="Password" onChange={
                    (e)=>{ this.handleChange(e, 'password')}
                  }/>
              </div>
              <div className="form-group col-md-6">
                <label htmlFor="gender">Gender</label>
                <select id="gender" className="form-control" onChange={ (e)=>{ this.handleChange(e, 'gender')} }>
                  <option >Choose...</option>
                  <option value="male">Male</option>
                  <option value="female">Female</option>
                </select>
              </div>
              <div className="form-group col-md-6 " >
                <label htmlFor="date">D.O.B</label>
                <input type="date" className="form-control" id="date" placeholder="date" onChange={ (e)=>{ this.handleChange(e, 'dob')} }/>
              </div>
              <div className="form-group col-md-2">
                <input type="submit" onClick={this.handleSubmit} className="form-control bg-info text-white" id="submit" placeholder="Password" />
              </div>
            </form>
          </div>
        </main>
      </div>
    )
  }
}

Is it a good practice to store the form data in state like this or is there any better way?

and password entered can be seen as plain text from devtools. how to avoid this i mean any way to encrypt password and send it to backend.

I'm very new to this. Will be helpful if someone check if this is good practice for writing code.

Naveen
  • 295
  • 1
  • 3
  • 12

3 Answers3

12

No need for such encryption. It would be pointless to implement your own encryption since HTTPS was created for that exact reason.

itsundefined
  • 1,409
  • 2
  • 12
  • 32
12

You don't need to encrypt the password in the frontend before sending it to the backend as far as you are using an HTTPS connection and sending it as form parameters. However, you should not store the password in the browser local storage, you could ask your backend a connection token that you will store as the session identifier.

rkouye
  • 493
  • 3
  • 12
  • +1 that's the idea, but "be invalidated when another token is generated for the same user" is a bit strong, normally you'd want to allow a user to have the site open on multiple devices at the same time no problem. – Kos Nov 05 '17 at 15:15
5

As has been said before, you cannot prevent the user from looking at the password in his browser (besides, he's the user, so he knows the password already). It is risky to store the password because it exposes it to local filesystem attacks (against which encryption may be useful, if you use a different key for each user).

You may want to encrypt the password if you don't trust SSL/TLS (for instance, corporate users may be forced to use an insecure HTTP connection to some HTTPS proxy). But in that case, you can instead prove to the server that the client has the password without sending it at all (even encrypted, for which the encryption key would have to be shared with the client over an untrusted network so bad idea) by sending a hash of the password plus some non-secret pseudo-random stuff (and send the pseudo-random stuff too).

That being said, you shouldn't store the user's password in any form on the client-side (when authenticating, you can still send a hash derived from the password, instead of the password itself, in case HTTPS is compromised).

Store a token (such as an OIDC access token) generated by the server after the initial authentication. The token expires (typically ranging from an hour to a couple of days), can be revoked with minimal inconvenience to the user (he doesn't have to create a new password) and is not enough to change the user's password or email (typically the user would have to enter the old password for that) and perform other critical account operations, so the user can at least recover the account even if some damage is done with a stolen token.

Community
  • 1
  • 1
Touffy
  • 6,309
  • 22
  • 28
  • 1
    huh. Didn't expect my answer to be so enlightening, I just wanted to add some use cases of client-side crypto to semako's answer, which should be the baseline. I'll try to explain better in an edit… – Touffy Nov 05 '17 at 19:27
  • Yeah i was storing form data in state. I first tried using **method="post" and action="/"** and on the server side i was not getting anything because i was not parsing body (using body-parser) and i thought **method action** dont work in react and tried to store in state and send to backend. lol. thank you – Naveen Nov 06 '17 at 08:10
  • If you shouldn't store the user's password they entered from an input field into React state, then how would you be able to retrieve it from the input field? I thought it was standard to have a state attribute for the field and use an onChange() to update the field (to later do something with). – Akcore Jan 04 '22 at 11:17
  • @Akcore the issue here is persistent / globally accessible storage like cookies or localStorage, and what you send over the network. React state is not an issue. Obviously the cleartext will be available as the input element''s value, too, and if you've got a XSS that can look at your DOM, you're screwed anyway. – Touffy Jan 04 '22 at 12:32
  • Ok. I understood the meaning but got thrown off by the previous comment. Thanks. – Akcore Jan 04 '22 at 21:58