K
Kinde8mo ago
Masini

Express Protected Routes: How to pass JWT from client?

Hi, I have an express API which is using the protectRoute and getUser middlewares in each route. From the client-side, I am using Expo and getting a JWT once successfully logging in, but I'm not sure how I should pass this as a parameter when invoking one of my API endpoints. How can I do this?
3 Replies
Oli - Kinde
Oli - Kinde8mo ago
Hey @Masini, To pass the JWT from your Expo client-side application to your Express API using the protectRoute and getUser middlewares, you need to include the JWT in the Authorization header of your HTTP requests. Here's a step-by-step guide on how to do this: 1. Store the JWT: After logging in on your Expo app and receiving the JWT, store it in a secure place within your application, such as secure storage. 2. Set up the HTTP request: When making a request to your Express API, include the JWT in the Authorization header. The common practice is to use the 'Bearer' schema. Here’s an example of how you can set up the request:
const jwt = 'your_jwt_token_here'; // Assume you have fetched this from secure storage

fetch('https://yourapi.com/protected-route', {
method: 'GET', // or 'POST', 'PUT', etc.
headers: {
'Authorization': `Bearer ${jwt}`,
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
const jwt = 'your_jwt_token_here'; // Assume you have fetched this from secure storage

fetch('https://yourapi.com/protected-route', {
method: 'GET', // or 'POST', 'PUT', etc.
headers: {
'Authorization': `Bearer ${jwt}`,
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
3. Handle the JWT in Express: On your server-side, the protectRoute middleware will automatically extract the JWT from the Authorization header, validate it, and if valid, the getUser middleware will populate the request object with the user's data. Ensure your server is set up to handle and authenticate the token correctly. By following these steps, your Expo application will be able to securely communicate with your Express API, passing the JWT for authentication and user identification on protected routes. Please let me know if you have any further questions.
Masini
MasiniOP7mo ago
I can confirm that my JWT is valid and I implemented it the same way. However it's still not working. From my API, the only thing being logged is "undefined". Below are the code snippets: Expo:
const jwt = await Storage.getAccessToken();
if (!jwt) {
throw new Error("No JWT available!");
}

console.log(jwt);

const response = await fetch(
`${process.env.EXPO_PUBLIC_CLOUDFLARE_API_URL}/test`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
'Authorization': `Bearer ${jwt}`,
},
}
);

if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

const data = (await response.json());
const jwt = await Storage.getAccessToken();
if (!jwt) {
throw new Error("No JWT available!");
}

console.log(jwt);

const response = await fetch(
`${process.env.EXPO_PUBLIC_CLOUDFLARE_API_URL}/test`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
'Authorization': `Bearer ${jwt}`,
},
}
);

if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

const data = (await response.json());
Express API:
router.get("/test", protectRoute, getUser, (req, res) => {
const user = (req as any).user as UserType;

if(!user) throw new Error("User is undefined");

console.log("USER: ", user);

res.status(200).json("success");
})
router.get("/test", protectRoute, getUser, (req, res) => {
const user = (req as any).user as UserType;

if(!user) throw new Error("User is undefined");

console.log("USER: ", user);

res.status(200).json("success");
})
Oli - Kinde
Oli - Kinde7mo ago
Hi @Masini,
the only thing being logged is "undefined"
Is this the case in your Express API or Expo app? Or Both? It seems like the issue might be related to how the JWT is being handled on the server side, particularly within the protectRoute and getUser middlewares. Here are a few steps you can take to troubleshoot and resolve the issue: 1. Verify JWT Extraction: Ensure that the protectRoute middleware is correctly extracting the JWT from the Authorization header. You can add a console log in this middleware to check if the JWT is being correctly parsed. 2. Check JWT Validation: Confirm that the JWT is being validated correctly in the protectRoute middleware. If there's an issue with the validation (e.g., wrong secret key, expired token), it might not pass the user info to the getUser middleware. 3. Middleware Configuration: Make sure that the middlewares are correctly set up to pass the user information from protectRoute to getUser. There might be an issue in the middleware chain that prevents the user data from being attached to the request object. 4. Logging and Error Handling: Enhance logging in both middlewares to capture more detailed information about the flow and any potential errors. This can help identify where the process breaks. 5. Environment Variables: Double-check your environment variables on both the client and server sides. Ensure that all necessary variables are correctly configured and accessible where needed. 6. Request Headers: On the client side, ensure that the headers are set correctly in the fetch request. It looks correct in your snippet, but it's worth double-checking for any typos or issues. 7. Test with Static Token: Temporarily replace the dynamic token retrieval with a static valid token in your client-side code to rule out any issues with how the token is being fetched or stored. Here's an example of how you might add logging to your protectRoute middleware:
const protectRoute = (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'No token provided' });
}

const token = authHeader.split(' ')[1];
console.log('Extracted Token:', token);

// Add your JWT validation logic here
// Log the result of the validation
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
console.log('Decoded JWT:', decoded);
req.user = decoded;
next();
} catch (error) {
console.error('JWT Validation Error:', error);
return res.status(401).json({ error: 'Invalid token' });
}
};
const protectRoute = (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'No token provided' });
}

const token = authHeader.split(' ')[1];
console.log('Extracted Token:', token);

// Add your JWT validation logic here
// Log the result of the validation
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
console.log('Decoded JWT:', decoded);
req.user = decoded;
next();
} catch (error) {
console.error('JWT Validation Error:', error);
return res.status(401).json({ error: 'Invalid token' });
}
};
By following these steps, you should be able to pinpoint the issue and get your authentication flow working correctly. If the problem persists, you may need to review the configuration of your JWT library or the specifics of how your JWTs are issued. Please let me know if you are still experiencing issues.
Want results from more Discord servers?
Add your server