Implementing a logout feature in your web application involves invalidating the user's session or token on both the client and server sides. Since you're using token-based authentication (JWT), the process is mostly client-side because JWTs are stateless; they aren't stored on the server (unless you have a blacklist mechanism in place). Here's how you can implement the logout functionality:
In your React application, "logging out" a user typically involves removing the token from localStorage
(or wherever it's stored) and updating the application's state accordingly.
Here's an example of what the logout button's click handler might look like:
const logoutUser = () => {
// Remove the token from localStorage
localStorage.removeItem('token');
// Optionally, redirect the user to the login page or somewhere else
// This can be achieved using React Router's useHistory hook, for instance
// history.push('/login');
};
You would then use this logoutUser
function as an event handler for your logout button or link. For example:
import React from 'react';
const Navbar = ({ /* your props here */ }) => {
// ... your other component logic ...
const logoutUser = () => {
localStorage.removeItem('token');
// Redirect to login or any other page
};
return (
<nav>
{/* ... your other nav items ... */}
<button onClick={logoutUser}>Logout</button>
</nav>
);
};
export default Navbar;
Since JWTs are stateless and don't maintain any session between requests, there's not much you need to do on the server-side when a user logs out if you're using a standard JWT setup. However, if you want to invalidate JWTs before they expire naturally, you would need to implement a token blacklist.
Here's a simplified example of what that might look like:
from flask import Flask, jsonify, request
app = Flask(__name__)
# This is a simple in-memory blacklist.
# For production applications, you might want a more persistent storage system.
TOKEN_BLACKLIST = set()
@app.route('/logout', methods=['POST'])
def logout():
auth_header = request.headers.get('Authorization')
if auth_header:
token = auth_header.split(" ")[1]
TOKEN_BLACKLIST.add(token)
return jsonify({'message': 'Logout successful.'})
else:
return jsonify({'message': 'No authorization token provided.'}), 401
# Use this decorator for routes where the token needs to be checked against the blacklist
def check_blacklist(f):
@wraps(f)
def decorated(*args, **kwargs):
# ... your existing token validation logic ...
if token in TOKEN_BLACKLIST:
return jsonify({'message': 'Token has been blacklisted.'}), 401
return f(*args, **kwargs)
return decorated
Remember, the blacklist approach requires that your server remembers blacklisted tokens, which means your JWT authentication is no longer stateless. This can introduce complexities, especially in distributed systems.
After the token is removed on the client side, ensure that your application's UI updates to reflect the fact that the user is no longer authenticated. Common practices include redirecting the user to the login page or updating the UI components to remove things that require authentication. Also, secure your application by ensuring that the backend APIs verify the token's validity and don't serve requests that require authentication if the token is missing or invalid.