Chapter 4: Authentication & Token Management
Have you ever used a key card to access a building? You need to swipe it at the entrance, and it grants you access if it's valid. In our Local Gist Manager, GitHub authentication works similarly - you need a valid "key card" (token) to access your gists. Let's explore how this system works!
The Problem: Securely Connecting to GitHub
Imagine wanting to access your personal files in a secure building. You wouldn't want just anyone to walk in and view your documents - you need a system to verify that you're authorized to access them.
Similarly, when our application wants to access your GitHub gists: 1. We need to prove to GitHub that you've authorized our app 2. We need to do this securely without exposing your credentials 3. We want to remember your authorization so you don't have to log in every time
Personal Access Tokens: Your Digital Key Card
GitHub uses Personal Access Tokens (PATs) for authentication. These are long strings that look something like:
ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890
Think of this token as your special key card to GitHub. When you provide this token to our app, it can: - Fetch your gists - Create new gists - Update existing gists - Delete gists
But it can only do these things because GitHub recognizes the token as belonging to you.
The Token Flow: How Authentication Works
Here's how the authentication process works in our application:
Let's walk through this diagram: 1. You enter your GitHub token in our application 2. Our app tests if the token is valid by trying to fetch your gists 3. If valid, we store the token in your browser cookies 4. On future visits, we check for this saved token first 5. If found, we automatically use it to fetch your gists
This is like the building remembering your key card, so you don't have to swipe it every time you visit!
The TokenForm Component: Your Entry Point
The first step in our authentication process is the TokenForm
component that collects your GitHub token:
const TokenForm = ({ onTokenSubmit }) => {
const [token, setToken] = useState("");
const [hasSavedToken, setHasSavedToken] = useState(false);
// Check for saved token when component loads
useEffect(() => {
const savedToken = getTokenFromCookie();
if (savedToken) {
setToken(savedToken);
setHasSavedToken(true);
}
}, []);
// More code for form submission...
This component: - Creates a state variable to hold the token - Checks if there's already a saved token in your cookies - If found, it fills the input field with that token - Lets you submit the form to authenticate
Cookie Management: Remembering Your Key Card
To remember your token between visits, we use browser cookies. These are small pieces of data stored in your browser:
// Save token to cookies
export const saveTokenToCookie = (token) => {
setCookie(null, 'github_token', token, {
maxAge: 30 * 24 * 60 * 60, // 30 days
path: '/',
sameSite: 'strict'
});
};
// Get token from cookies
export const getTokenFromCookie = () => {
const cookies = parseCookies();
return cookies['github_token'] || '';
};
The first function saves your token in a cookie that will last for 30 days. The second function retrieves your saved token when you return to the application.
Token Validation: Testing Your Key Card
When you submit your token, our application needs to check if it's valid:
const handleTokenSubmit = async (submittedToken) => {
setToken(submittedToken);
setLoading(true);
try {
// Try to fetch gists using the token
const fetchedGists = await getGists(submittedToken);
setGists(fetchedGists);
// Save token to cookies when successful
saveTokenToCookie(submittedToken);
} catch (err) {
setError("Failed to fetch gists. Please check your token.");
// Clear invalid token
removeTokenFromCookie();
} finally {
setLoading(false);
}
};
This function: 1. Updates the token state with what you submitted 2. Shows a loading indicator 3. Tries to fetch your gists using that token 4. If successful, it saves the token to cookies 5. If there's an error, it shows an error message and clears any saved token
It's like trying your key card at the building entrance - if it works, great! If not, we need to get a new key card.
Using the Token for API Requests
Once we have a valid token, we use it for all requests to GitHub's API:
const getGists = async (token) => {
const response = await fetch('https://api.github.com/gists', {
headers: {
'Authorization': `token ${token}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Failed to fetch gists`);
}
return response.json();
};
This function: 1. Makes a request to GitHub's API 2. Includes your token in the Authorization header 3. Throws an error if the request fails 4. Returns the gist data if successful
The token in the Authorization
header is like showing your key card to access different rooms within the building. Without it, GitHub would reject your request.
Automatic Login: Using Saved Tokens
When you return to our application, we automatically check for a saved token:
useEffect(() => {
const loadSavedToken = async () => {
// Check for token in cookie
const savedToken = getTokenFromCookie();
if (savedToken) {
setToken(savedToken);
try {
const fetchedGists = await getGists(savedToken);
setGists(fetchedGists);
} catch (err) {
// Token is invalid, clear it
removeTokenFromCookie();
setToken("");
}
}
};
loadSavedToken();
}, []);
This code: 1. Runs when the application first loads 2. Checks if there's a saved token in cookies 3. If found, it tries to use that token to fetch gists 4. If the token is no longer valid, it removes it from cookies
This is like the building entrance automatically recognizing your key card from a distance when you approach, without you having to take it out of your pocket!
Logging Out: Clearing Your Token
Sometimes you want to remove your authorization. Our application provides a logout function:
const handleLogout = () => {
setToken("");
setGists([]);
// Remove token from cookies
removeTokenFromCookie();
};
This function: 1. Clears the token from the application state 2. Clears the list of gists 3. Removes the token from cookies
This is like turning in your key card when you don't need access to the building anymore.
Token Security Best Practices
Security is important when working with authentication tokens. Here are some best practices our application follows:
- Secure Storage: We store tokens in cookies with security flags
- Limited Lifespan: Tokens expire after 30 days
- Secure Transmission: Tokens are only sent over secure HTTPS connections
- Minimal Permissions: We recommend tokens with only the permissions needed
Authentication Flow in Action
Let's see how all of this works together in a real user flow:
- First Visit
- You visit Local Gist Manager for the first time
- The app shows the
TokenForm
component -
You enter your GitHub token and submit
-
Token Validation
- The app tries to fetch your gists using the token
- If successful, it saves the token to cookies
-
The app displays your gists
-
Subsequent Visits
- You return to Local Gist Manager
- The app finds your saved token in cookies
- It automatically fetches your gists
-
You see your gists without having to re-enter your token
-
Logout
- You click "Clear Token" in the header
- The app removes the token from cookies
- You return to the token entry screen
Creating a GitHub Personal Access Token
If you don't have a token yet, here's how to create one:
- Go to GitHub Settings > Personal Access Tokens
- Click "Generate new token"
- Give your token a descriptive name (e.g., "Local Gist Manager")
- Select the "gist" scope to give access to your gists
- Click "Generate token"
- Copy the generated token (you won't be able to see it again!)
Remember that this token gives access to your gists, so keep it secure and don't share it.
Conclusion
In this chapter, we've learned about Authentication & Token Management in our Local Gist Manager application. We've seen how Personal Access Tokens work as digital key cards for GitHub, how we validate and store these tokens in cookies, and how we use them to access your gists.
This authentication system ensures that only you can access your gists through our application, while also making the experience convenient by remembering your authentication between visits.
In the next chapter, we'll explore GitHub API Integration, which builds on this authentication system to communicate with GitHub's servers.