Open chawax opened 6 years ago
I use apisauce.
I found a solution storing tokens in api and using addResponseTransform
and addRequestTransform
. It means the auth tokens are not in Redux store, but it could make sense if you can consider the auth tokens are part of api implementation.
const tokens = {}
const create = (baseURL = Config.API_ENDPOINT) => {
const api = apisauce.create({
baseURL,
headers: {
'Cache-Control': 'no-cache',
Accept: 'application/json',
},
timeout: 10000
})
api.addResponseTransform((response) => {
if (response.ok) {
if (response.headers.authentication) {
tokens.jwtToken = response.headers.authentication
}
}
})
api.addRequestTransform((request) => {
if (tokens.jwtToken) {
request.headers.Authentication = `Bearer ${tokens.jwtToken}`
}
})
....
}
I added the following methods into in my Api.js file for configuring the auth header, which I call from the sagas:
const setAuthToken = (userAuth) => api.setHeader('Authorization', 'Bearer ' + userAuth)
const removeAuthToken = () => api. deleteHeader('Authorization')
https://github.com/ruddell/ignite-jhipster/blob/master/boilerplate/App/Services/Api.js.ejs#L51-L52
@chawax I personally do a setHeader inside the Api.js in every api endpoint call. like so:
const register = (token, data) => {
api.setHeader('Authorization', 'Bearer ' + token)
return api.post('api/register', { ...data })
}
That way you just select the token from the Store/Offline cache with a selector, inside your saga and pass it to the api function along with the data you want to submit to your backend.
So it means you have to do it in any saga that calls the api. And that's what I wanted to avoid.
@chawax You normally would use Sagas for the api calls.
If you want to directly call the api from the component you can do something like:
import React, {Component} from 'react'
import { View } from 'react-native'
import API from '../Services/Api'
class TestComponent extends Component{
componentDidMount(){
const yourBearerToken = '1234567890'
const api = API.create('https://jsonplaceholder.typicode.com/')
api.setHeader('Authorization', 'Bearer ' + yourBearerToken)
api.get('posts/1'}).then(result => console.log(result))
}
render(){
return(
<View />
)
}
}
export default TestComponent
UPDATE: Sorry didnt get your question at first, than realised my answer was not what you were looking for. But as for sagas, you can use selectors in every saga that needs your token, and do it that way.
You can use an awesome library https://github.com/reduxjs/reselect huge benefit of it is what exactly they state on their main page:
Selectors are efficient. A selector is not recomputed unless one of its arguments changes.
In my recent implementations, I didn't try to use the token in the store but from AsyncStorage, or Secure Store instead. I wrapped API calls as a client SDK, and then I can have only one API instance in root store/global.
If we try to token passed in header ....Try this method
const api = 'your api';
const token = JSON.parse(sessionStorage.getItem('data'));
const token = user.data.id; /*take only token and save in token variable*/
axios.get(api , { headers: {"Authorization" : `Bearer ${token}`} })
.then(res => {
console.log(res.data);
.catch((error) => {
console.log(error)
});
Does someone want to add some documentation to this effect?
This works for me: https://github.com/axios/axios#global-axios-defaults
I need to set authentication tokens in headers on api calls but the tokens are not known at the time the api is created : they are stored in the Redux store after the user was logged. So I need to retrieve them from the store on any api calls. I could retrieve them in sagas and pass them as parameter for api calls.
In saga :
In api :
But it means I have to do it in every saga.
I thought about exporting the store from
Containers/App.js
file, importing it in api and usingaddRequestTransform
to set headers, but I know it was bad practice to export store.What is the proper way to resolve such a problem ?