A. Atiyah
A. Atiyah

Reputation: 555

protecting routes with nextjs and express

So I'm developing an app using NextJS, Firebase Authentication and Express and when a user sign up or sign in Firebase sends me a token that I can verify the user with and protect my routes.

  componentDidMount() {
    const { setCurrentUser } = this.props;

    this.unsubscribeFromAuth = auth.onAuthStateChanged(async userAuth => {
      if (userAuth) {
        const userRef = await createUserProfileDocument(userAuth);
        this.setState({
          currentUser: {
            ...userRef
          }
        });

        const token = await auth.currentUser.getIdToken();
        axios.defaults.headers.common['Authorization'] = token;
      }

      this.setState({ currentUser: userAuth });
    });
  }

now every time I get that token I try to add it to the defaults of Axios so I can access these routes but I can't seem to do it because at this point the componentDidMount method didn't even run yet.

and I'm stuck in a loop and can't seem to find a good way to pass the token down I tried stuff like redux and even then I couldn't do it

Post.getInitialProps = async ({ store }) => {
  // axios.defaults.headers.common['Authorization'] = token;
  // const res = await axios.get('http://localhost:5000/api/posts/2');
  // return { data: res.data };
};

how do people who use next with api backend do it? I'd love a good reference to that.

Upvotes: 1

Views: 3210

Answers (1)

Titus Sutio Fanpula
Titus Sutio Fanpula

Reputation: 3613

I think you should try to make a service in your reactApp.

For example, httpService.js:

import axios from "axios";

function setJwt(jwt) {
  axios.defaults.headers.common["x-auth-token"] = jwt;
}

export default {
  get: axios.get,
  post: axios.post,
  put: axios.put,
  delete: axios.delete,
  setJwt
};

After you create httpService.js, you can also create auth.js that handles your tokens, including logging in, registering and saving them to localstorage and ready to use when you want.

For example auth.js:

import jwtDecode from "jwt-decode";
import http from "./httpService";
import {apiUrl} from "../config.json";

const apiEndpoint = apiUrl + "/auth";
const tokenKey = "token";

http.setJwt (getJwt());

export async login function(email, password) {
  const {data: jwt} = await http.post(apiEndpoint, {email, password});
  localStorage.setItem(tokenKey, jwt);
}

export function loginWithJwt(jwt) {
  localStorage.setItem(tokenKey, jwt);
}

export function logout() {
  localStorage.removeItem(tokenKey);
}

function getCurrentUser() {
  try {
    const jwt = localStorage.getItem(tokenKey);
    return jwtDecode(jwt);
  } catch(ex) {
    return null;
  }
}

export function getJwt() {
  return localStorage.getItem(tokenKey);
}

export default {
  login,
  logout
  getCurrentUser,
  loginWithJwt,
  getJwt
};

So if you want to protect your router, then you only need to call auth.getCurrentUser().

I hope the code above can help you.

Upvotes: 0

Related Questions