I'm completely new to using RTK Query, I created the app before but without the authentication and everything worked, now I want to add the authentication using Auth0 but I can't access any file I add getTokenSilently()
PS. getTokenSilently is the {token}
thanks for help
export const myApi = createApi({
reducerPath: "points",
baseQuery: fetchBaseQuery({
baseUrl: "/",
prepareHeaders: (headers, { getState }) => {
const token = getState()
if (token) {
headers.Authorization = `Bearer ${token}`
}
return headers
},
}),
endpoints: builder => ({
getPoints: builder.query({
query: () => `/`,
}),
}),
})
export const { useGetPointsQuery } = myApi
What I ended up doing was to store the token in my state and then added this to App:
useEffect(() => {
(async () => {
try {
const token = await getAccessTokenSilently({})
dispatch(setToken(token))
} catch (e) {
console.error(e);
}
})()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [getAccessTokenSilently])
There is a little more logic to know if you have not yet authenticated so that you can render a pending authentication state, but this was enough to get me going.
Related
As title says, I am having issues setting basic auth headers inside a headers object for redux query.
const wooApiHeaders = {
}
const baseUrl = 'https://stagemonkey.dk/kumau';
const createRequest = (url:any) => ({ url, headers: wooApiHeaders })
export const wooApi = createApi({
reducerPath: 'wooApi',
baseQuery: fetchBaseQuery({ baseUrl }),
endpoints: (builder) => ({
getWoo: builder.query({
query: () => createRequest('/wp-json/wc/v3/products')
})
})
})
I have been reading through docs but are facing some issues.
Is there a way to get the id token from firebase 9 directly in the axios interceptor? It was possible with firebase 8.
import axios from "axios";
import config from "../config";
import { getAuth, getIdToken } from "firebase/auth";
const API = axios.create({
responseType: "json",
baseURL: config.ApiUrl
});
API.interceptors.request.use(async (request) => {
const auth = getAuth();
const { currentUser } = auth;
request.headers = {
Authorization: `Bearer ${await currentUser.getIdToken()}`,
};
return request;
});
currentUser is null first because it is loaded async by firebase. How can I access it directly without always having the problem that the first time it crashes because the user is not loaded yet?
Thank your for your help.
You can create a function that waits for onAuthStateChanged() to load auth state and returns a promise containing user's token. Try:
const getUserToken = async () => {
return new Promise((resolve, reject) => {
const unsub = onAuthStateChanged(getAuth(), async (user) => {
if (user) {
const token = await getIdToken(user);
resolve(token)
} else {
console.log("User not logged in")
resolve(null)
}
unsub();
});
})
}
API.interceptors.request.use(async (request) => {
const token = await getUserToken();
if (token) {
request.headers = {
Authorization: `Bearer ${token}`,
};
} else {
// prompt user to login?
}
return request;
});
Make sure you have initialized Firebase SDK before using getAuth(). I recommend creating a different file firebase.js, initialize required services and exporting the instances as explained in this answer.
I'm trying to do a delete request. I can fetch the API route through pages/api/people/[something].js.
And this is the response I got from the browser's console.
DELETE - http://localhost:3000/api/people/6348053cad300ba679e8449c -
500 (Internal Server Error)
6348053cad300ba679e8449c is from the GET request at the start of the app.
In the Next.js docs, for example, the API route pages/api/post/[pid].js has the following code:
export default function handler(req, res) {
const { pid } = req.query
res.end(Post: ${pid})
}
Now, a request to /api/post/abc will respond with the text: Post: abc.
But from my API route pages/api/people/[something].js, something is undefined.
const { something } = req.query
UPDATED POST:
React component
export default function DatabaseTableContent(props) {
const id = props.item._id; // FROM A GET REQUEST
const hide = useWindowSize(639);
const [deletePeople] = useDeletePeopleMutation();
async function deleteHandler() {
await deletePeople(id);
}
return <Somecodes />;
}
apiSlice.js
export const apiSlice = createApi({
// reducerPath: "api",
baseQuery: fetchBaseQuery({ baseUrl: url }),
tagTypes: ["People"],
endpoints: (builder) => ({
getPeople: builder.query({
query: (people_id) => `/api/people/${people_id}`,
providesTags: ["People"],
}),
deletePeople: builder.mutation({
query: (studentInfo) => ({
url: `api/people/people-data/student-info/${studentInfo}`,
method: "DELETE",
headers: {
accept: "application/json",
},
}),
invalidatesTags: ["People"],
}),
}),
});
export const {
useGetPeopleQuery,
useDeletePeopleMutation,
} = apiSlice;
pages/api/people/people-data/student-info/[studentInfo].js
import { ObjectId, MongoClient } from "mongodb";
async function handler(res, req) {
const { studentInfo } = req.query; // the code stops here because "studentInfo" is undefined
const client = await MongoClient.connect(process.env.MONGODB_URI.toString());
const db = client.db("people-info");
if (req.method === "DELETE") {
try {
const deleteData = await db
.collection("student_info")
.deleteOne({ _id: ObjectId(studentInfo) });
const result = await res.json(deleteData);
client.close();
} catch (error) {
return res.status(500).json({ message: error });
}
}
}
export default handler;
The order of params passed to your handler functions needs to be reversed.
For NextJS API routes the req is the first param passed to the handler and the res param is second.
Example handler function from NextJS documentation:
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}
Hello there I have created dotnet core web api for login and register but in the app after refresh it always tries to log in again. Since I am new to react native I could not apply solutions to my project. I use redux and here is my action :
export const signin = (email, password) => {
return async dispatch => {
const response = await fetch(
'http://localhost:5000/api/user/login',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: email,
password: password,
}),
}
);
if (!response.ok) {
throw new Error('Something went wrong!');
}
const resData = await response.json();
console.log(resData);
dispatch({ type: SINGIN, token: resData.token, userId: resData.id });
saveDataToStorage(resData.token);
};
};
const saveDataToStorage = (token, userId) => {
AsyncStorage.setItem('userData', JSON.stringify({
token: token,
})
);
};
And here is my navigator with react navigation 5 :
export const Navigator = () => {
const [userToken, setUserToken] = React.useState(null);
const userData = AsyncStorage.getItem('userData');
const authContext = React.useMemo(() => {
return {
signIn: () => {
setUserToken(userData);
},
singnUp: () => {
setUserToken(userData);
},
signOut: () => {
setUserToken(null);
},
};
}, [userData]);
return (
<AuthContext.Provider value={authContext}>
<NavigationContainer>
<RootStackScreen userToken={userToken} />
</NavigationContainer>
</AuthContext.Provider >
);
};
As I said I could not find a way to apply solutions that I found. Thank you for you help.
First, make sure all of your actions with AsyncStorage should be async(Use promise or async/await).
Then follow this to implement the authentication flow of your application.
https://reactnavigation.org/docs/auth-flow
My this answer will be helpful for you.
React Navigation 5 Auth Flow
I'm setting a basic authentication on a Nuxt project with JWT token and cookies to be parsed by nuxtServerInit function.
On login with email/password, works as intended, setUser mutation is triggered and the appropriate user object is stored in state.auth.user.
On reload, nuxtServerInit will get the jwt token from req.headers.cookies, call the GET method and identify user.Works like a charm.
Problem starts when I hit the /logout endpoint. state.auth.user is set to false and Im effectively logged out... but If I refresh, I'm logged in again with the previous user data. Even if my cookies are properly empty (on below code, both user and cookie are undefined after logout and refresh, as expected)
So I really don't get why is my state.auth.user is back to its initial value...
store/index.js
import Vuex from "vuex";
import auth from "./modules/auth";
import axios from "~/plugins/axios";
const cookieparser = process.server ? require("cookieparser") : undefined;
const END_POINT = "api/users";
const createStore = () => {
return new Vuex.Store({
actions: {
async nuxtServerInit({ commit, dispatch}, { req }) {
let cookie = null;
console.log(req.headers.cookie)
if (req.headers.cookie) {
const parsed = cookieparser.parse(req.headers.cookie);
try {
cookie = JSON.parse(parsed.auth);
console.log("cookie", cookie)
const {accessToken} = cookie
const config = {
headers: {
Authorization: `Bearer ${accessToken}`
}
}
const response = await axios.get(`${END_POINT}/current`, config)
const user = response.data
console.log("user nuxt server init", user)
await commit('setUser', user)
} catch (err) {
// No valid cookie found
console.log(err);
}
}
}
},
modules: {
auth
}
});
};
export default createStore;
modules/auth.js
import axios from "~/plugins/axios";
const Cookie = process.client ? require("js-cookie") : undefined;
const END_POINT = "api/users";
export default {
state: {
user: null,
errors: {}
},
getters: {
isAuth: state => !!state.user
},
actions: {
login({ commit }, payload) {
axios
.post(`${END_POINT}/login`, payload)
.then(({ data }) => {
const { user, accessToken } = data;
const auth = { accessToken };
Cookie.set("auth", auth);
commit("setUser", user);
})
.catch(e => {
const error = e;
console.log(e);
commit("setError", error);
});
},
logout({ commit }) {
axios
.post(`${END_POINT}/logout`)
.then(({ data }) => {
Cookie.remove("auth");
commit("setUser", false);
})
.catch(e => console.log(e));
},
},
mutations: {
setUser(state, user) {
state.user = user;
},
setError(state, errors) {
state.errors = errors;
}
}
};
The way I logout my user is by creating a mutation called clearToken and commit to it in the action :
State :
token: null,
Mutations :
clearToken(state) {
state.token = null
},
Actions :
logout(context) {
context.commit('clearToken')
Cookie.remove('token')
}
This way, you token state revert back to null.