Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly store access token in memory react

I'm searching for a clean way to store my access token in React.

  • First thing: I don't want to use local storage. I don't need to make my access token persistent since I can always refresh it.
  • I also excluded a cookie since I want to prevent CSRF attacks. By storing the access token only in memory, in fact, the page needs to be loaded to get the token and authenticate requests (refresh token can be used only to refresh)
  • I thought of using redux/context, however, the function calling the API is not a child of a component so I can't access the token from that. Furthermore, I don't want to pass the token as a parameter, since I want to keep decoupled the HTTP logic. Maybe there is a clean way to use it?

After a bit of research, I found that using a global variable is a working "cheat" to obtain what I want. However, I was guessing if there was a clearer way to get the same result.

//token.js

const access_token= "";

export const setAccessToken(token){
 access_token=token;
}

export const getAccessToken(){
 return access_token;
}

//NOTICE:
// -ON LOGIN/REFRESH: I set the access token
// -ON API CALLS: I get the access token and I add it to the header
api.js

const baseURL= "http://my_base_url";

const generateApiInterface = ()=>{
    let headers : any= {
       
    };
    
    token=getAccessToken(); //HERE I NEED TO RETRIEVE MY ACCESS TOKEN

    if(token){
        headers={
            'Authorization': 'Token '+ token,
            ...headers //append other basic proprieties
        }
    }

    return axios.create({
        baseURL: baseURL,
        headers: headers
    });
}

const api = generateApiInterface();

like image 593
Andrea Costanzo Avatar asked May 26 '26 01:05

Andrea Costanzo


1 Answers

The way you're doing it is preferable to keep anything in memory. If this is server side, then you'd want to make sure you delete the token once you're done, but if not then the current approach is desirable. Note, you're using a const, you'd want to change that to a let. Another idea would be to use session storage, but then that brings the idea of XSS.

However, React provide a way to have "global" state - this would be to use a provider and context. Here's an example:

// provider.tsx

import React, { useContext, createContext, FC, useState } from 'react'

type AccessTokenContext = [string, React.Dispatch<React.SetStateAction<string>>]

const AccessTokenProvider: FC = (props) => {
    const [accessToken, setAccessToken] = useState<string>(null)
    return <AccessToken.Provider value={[accessToken, setAccessToken]} {...props} />
}

const AccessToken = createContext<AccessTokenContext>(null)

const useAccessToken = (): AccessTokenContext => useContext<AccessTokenContext>(AccessToken)

export { AccessTokenProvider, useAccessToken }

You'd have to wrap your app container in AccessTokenProvider:

// index.tsx

import React from 'react'
import ReactDOM from 'react-dom'

import './index.css'

import App from './App'
import { AccessTokenProvider } from './providers/AccessTokenProvider'

ReactDOM.render(
    <AccessTokenProvider>
        <App />
    </AccessTokenProvider>,
    document.getElementById('app')
)

Then you can then use the hook useAccessToken in App and any children of App. Of course, this provider doesn't have to be root level, but it's easiest to include it here.

// app.tsx

import React, { FC } from 'react'

const App: FC = props => {
    const [accessToken, setAccessToken] = useAccessToken()
    return <div>{/* content */}</div>
}

export default App
like image 172
Kobe Avatar answered May 28 '26 13:05

Kobe



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!