Hold-Krykke / Security_and_FullstackJavascript_Exam

4. Semester Security og Fullstack Javascript Eksamens Projekt
0 stars 0 forks source link

Update check for JWT in Login Screen (check if token can be refreshed) #62

Open MrHardcode opened 4 years ago

MrHardcode commented 4 years ago

Make sure to check if the token can be refreshed before deleting invalid (old) token from secure storage at startup. Also make sure not to "log in" users if token exists at startup before the token has been checked with the backend.

MrHardcode commented 4 years ago

Idea on how to solve the issue:

In ResolverMap change the resolver for checking JWT from:

checkToken(_, args, context): boolean {
            try {
                requiresLogIn(context);
                return true;
            } catch (err) {
                return false;
            }
        }

to

checkToken(_, args, context): boolean {
            requiresLogIn(context);
            return true;
        }

This will make the resolver throw an UNAUTHENTICATED error which should then trigger the refresh-JWT mechanism in #46

In LoginScreen the following code performs the check on the token's validity:

const { data, error } = useQuery(facade.CHECK_JWT);

    useEffect(() => {
        async function check() {
            if (data) {
                if (!data.checkToken) {
                    // We need to set the username to something that's not empty because another 
                    // useEffect checks this value and shows the username modal if this value is falsy
                    setUser({ username: "..." });
                    setFirstLogin(false);
                    setSignedIn(false);
                    await SecureStore.deleteItemAsync(secureStoreKey);
                    navigation.navigate("LoginScreen");
                    return;
                }
            }
        }
        check();
    }, [data]);

Right now the error is not being used for anything but it could be used to check the UNAUTHENTICATED error thrown by the backend and then delete the JWT in the client and log the user out.

Also - the following useEffect runs independently of the useEffect above:

useEffect(() => {
        const checkIfLoggedIn = async () => {
            const token = await SecureStore.getItemAsync(secureStoreKey);
            if (token) {
                const decoded = jwt_decode(token);
                const temp_user = {
                    email: decoded.useremail,
                    username: decoded.username,
                };
                setUser({ ...temp_user });
                // console.log(JSON.stringify({ temp_user }, null, 4));
                setSignedIn(true);
                navigation.navigate("UserScreen");
            }
        };
        checkIfLoggedIn();
    }, []);

This is the code that logs the user in, if there is a JWT in their secure storage. This code should be modified to run only after the JWT check has been performed. This could be done by combining the two useEffects but I don't know if that's the best solution.