-1

I have a web app which is secured with JWT. How to make it remember my login data and not to enter it all again if I open a new tab? I use axios.post to the authenticate endpoint and save the token in localStorage My code of the authentication service in frontend:

import axios from 'axios'

const API_URL = 'http://localhost:8080/map-runner'

export const USER_NAME_SESSION_ATTRIBUTE_NAME = 'authenticatedUser'

class AuthenticationService {

    executeJwtAuthenticationService(username, password) {
        return axios.post(`${API_URL}/authenticate`, {
            username,
            password
        })
    }

    registerSuccessfulLoginForJwt(username, token) {
        sessionStorage.setItem(USER_NAME_SESSION_ATTRIBUTE_NAME, username)
        localStorage.setItem("token", token)
    }

    createJWTToken(token) {
        return 'Bearer ' + token
    }


    logout() {
        sessionStorage.removeItem(USER_NAME_SESSION_ATTRIBUTE_NAME);
    }

    isUserLoggedIn() {
        let user = sessionStorage.getItem(USER_NAME_SESSION_ATTRIBUTE_NAME)
        if (user === null) return false
        return true
    }

    getLoggedInUserName() {
        let user = sessionStorage.getItem(USER_NAME_SESSION_ATTRIBUTE_NAME)
        if (user === null) return ''
        return user
    }

    setupAxiosInterceptors(token) {
        axios.interceptors.request.use(
            (config) => {
                if (this.isUserLoggedIn()) {
                    config.headers.authorization = token
                }
                return config
            }
        )
    }
}

export default new AuthenticationService()

Now my Login Component:

import React, { Component } from 'react'
import AuthenticationService from '../service/AuthenticationService';

class LoginComponent extends Component {

    constructor(props) {
        super(props)

        this.state = {
            username: '',
            password: '',
            hasLoginFailed: false,
            showSuccessMessage: false
        }
    }

    handleChange = (event) => {
        this.setState(
            {
                [event.target.name]
                    : event.target.value
            }
        )
    }

    loginClicked = () => {
        AuthenticationService
            .executeJwtAuthenticationService(this.state.username, this.state.password)
            .then((response) => {
                AuthenticationService.registerSuccessfulLoginForJwt(this.state.username, response.data.token)
                console.log(response.data.token);
                this.props.history.push(`/calculations`)
            }).catch(() => {
                this.setState({ showSuccessMessage: false })
                this.setState({ hasLoginFailed: true })
            })
    }

    render() {
        return (
            <div>
                <h1>Вход</h1>
                <div className="container">
                    {this.state.hasLoginFailed && <div className="alert alert-warning">Неверные данные</div>}
                    {this.state.showSuccessMessage && <div>Вход выполнен успешно</div>}
                    Имя пользователя: <input type="text" name="username" value={this.state.username} onChange={this.handleChange} />
                    Пароль: <input type="password" name="password" value={this.state.password} onChange={this.handleChange} />
                    <button className="btn btn-success" onClick={this.loginClicked}>Вход</button>
                </div>
            </div>
        )
    }
}

export default LoginComponent

The backend in spring boot is quite long even regarding the JWT part, so I guess I'll leave the link to the tutorial which was the basis of my backend. The paths are a bit different but in general these backend parts are the same.. I also tried to use sessionstorage instead of localstorage, doesnt work. If possible, maybe we can test everything out firstly replicating the whole tutorial code as the jwt part is almost the same there (I have a copy and they have a link to their github in the article)

guido
  • 65
  • 1
  • 9
  • just retrieve the token from the localstorage and put it in your post, then in backend check if you are already logged and if is still valid – Margon Jan 13 '20 at 16:09
  • 1
    Does this answer your question? [Where to store JWT in browser? How to protect against CSRF?](https://stackoverflow.com/questions/27067251/where-to-store-jwt-in-browser-how-to-protect-against-csrf) – JEY Jan 13 '20 at 16:10

2 Answers2

1

You can save the token either in local storage or cookie. And every-time you send any xhr request you can pass the token in the header.

Sim
  • 287
  • 1
  • 2
  • 13
1

You must be having login page where you would be sending jwt token at the time of login so store the jwt token at the time if login as

 axios.post("http:yourAPIaddresshere", formData)
    .then((response) => {
       if(response.status === 200) {
          // storing session 
          localStorage.setItem('session', response.data.token)
          this.props.history.push('home');
        } else {
          this.showMessage('Error message', "Please check your credentials.")
        }
      } 
    });
}

This is where your session is stored in localStorage now in other all the files retrieve the token In same login file also do :

 componentDidMount(){
       if (localStorage.getItem('session') !== null) {
         this.props.history.push('home')
       }
     }

this will always push your navigation to other tabs. To make your other tabs/pages secure also check session if not null it won't let you open other pages using routes without session token

 componentDidMount(){
       if (localStorage.getItem('session') === null)
     this.props.history.push('login') }

P.S: Make sure to empty the sesion token at the time of logout as :

 localStorage.removeItem('session');
Ansh Varun
  • 100
  • 1
  • 12