Golang React Authorization

35 Views Asked by At

I am working with React as Frontend and Go as Backend.

I use JWT token to authorize the user. So here is a JWT Middleware for secure routes. The problem is I am using cookies for authorization and middleware also checks cookies to validate. While I use localStorage in React to save the JWT. To be more exact the code is here:

http.SetCookie(w, &http.Cookie{ // on Login
    Name:     "token",
    Value:    tokenString,
    Expires:  time.Now().UTC().Add(time.Hour),
    HttpOnly: true, // Prevents client-side JS from accessing the cookie
    Secure:   true, // Ensures cookie is sent over HTTPS
    Path:     "/",  // Cookie available to entire domain
})

http.SetCookie(w, &http.Cookie{ // on Logout
    Name:     "token",
    Value:    "",
    Expires:  time.Unix(0, 0),
    HttpOnly: true,
    Secure:   true,
    Path:     "/",
})

here is middleware:

func JWTMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    c, err := r.Cookie("token")
    if err != nil {
        if err == http.ErrNoCookie {
            functionalities.WriteJSON(w, http.StatusUnauthorized, APIServerError{Error: "Unauthorized"})
            return
        }
        functionalities.WriteJSON(w, http.StatusBadRequest, APIServerError{Error: err.Error()})
        return
    }


    tknStr := c.Value
    claims := &Claims{}

    tkn, err := jwt.ParseWithClaims(tknStr, claims, func(token *jwt.Token) (interface{}, error) {
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, http.ErrNotSupported
        }

        return []byte("SECRET"), nil
    })

    if err != nil {
        if err == jwt.ErrSignatureInvalid {
            functionalities.WriteJSON(w, http.StatusUnauthorized, APIServerError{Error: "Unauthorized"})
            return
        }
        functionalities.WriteJSON(w, http.StatusBadRequest, APIServerError{Error: err.Error()})
        return
    }
    if !tkn.Valid {
        functionalities.WriteJSON(w, http.StatusUnauthorized, APIServerError{Error: "Unauthorized"})
        return
    }

    next.ServeHTTP(w, r)
})

}

As I writed before I use localStorage in Frontend side.

So I do not know how to send the requests like this:

useEffect (() => {
const userId = 'your_user_id_here'; // Replace this with actual logic to retrieve the user's ID
const fetchProfile = async () => {
  try {
    const response = await axios.get(`http://127.0.0.1:8080/api/accounts/${userId}`, {
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('authToken')}` // Assuming the token is stored in local storage
      }
    });

    // Assuming the response data structure matches the expected profile data
    setProfileData(response.data);
  } catch (error) {
    console.error('Profile fetch error:', error.response ? error.response.data : error.message);
  }
};

fetchProfile();

}, []);

Guys, I would be more than happy if you help me or guide me to solve this problem. I am ready to rewrite the backend side and do more radical things :D

2

There are 2 best solutions below

0
Irtaza Hussain On

The Authorization header now reads the token directly from the cookie instead of from local storage.

The document.cookie property is used to access cookies. The regular expression is used to extract the value of the token cookie.


useEffect(() => {
  const fetchProfile = async () => {
    try {
      const response = await axios.get(`http://127.0.0.1:8080/api/accounts/${userId}`, {
        // No need to read from local storage, read from cookie instead
        headers: {
          'Authorization': `Bearer ${document.cookie.replace(/(?:(?:^|.*;\s*)token\s*\=\s*([^;]*).*$)|^.*$/, "$1")}`
        }
      });

      // Assuming the response data structure matches the expected profile data
      setProfileData(response.data);
    } catch (error) {
      console.error('Profile fetch error:', error.response ? error.response.data : error.message);
    }
  };

  fetchProfile();
}, []);

Assuming the cookies are there.

Use this package to play with the cookies on frontend and it provides all the functions and it is easy to use.

0
srmback On

The problem was with endpoint. So I changed this:

const response = await axios.get(`http://127.0.0.1:8080/api/accounts/${userId}`, {}...

to:

const response = await axios.get(`http://localhost:8080/api/accounts/${userId}`, {}...

Here it is.