API Keys and Token Authentication
# CHAPTER 14
API Keys and Token Authentication
1. Introduction
We know that REST APIs require the client to present an "ID card" with every request. In Chapter 14, we will learn how to actually build this system from scratch using PHP and MySQL. We will explore two of the most common methods: API Keys (for server-to-server or application-level access) and Bearer Tokens (for user-level access). We will cover database design, token generation, and the validation process.2. Learning Objectives
By the end of this chapter, you will be able to:- Design a MySQL database schema to store API tokens.
- Generate secure, random API keys using PHP.
- Implement an authentication middleware/check in your PHP script.
- Understand the difference between Application API Keys and User Access Tokens.
- Authenticate requests by validating tokens against the database.
3. Beginner-Friendly Explanation
- API Key: Think of this as a VIP pass given to a specific *company* or *app*. For example, when your server talks to Stripe to process payments, it uses an API Key. It represents the app, not a specific human.
- User Token: Think of this as a hotel room key given to a specific *human*. When you log into the mobile app, you get a token. It represents *you*.
Both work the exact same way technically: they are long, random strings of text checked against a database.
4. Real-World Examples
- API Key: Google Maps API. You generate an API key in the Google Console and hardcode it into your website so your site is allowed to load the map.
- User Token: GitHub Personal Access Tokens. You generate a token on GitHub and use it in your terminal to push code, acting on behalf of your user account.
5. Detailed Code Examples
Let's build a basic User Token authentication system.1. Database Schema (users table):
2. Generating a Token on Login (login.php):
3. Validating the Token on a Protected Route (profile.php):
6. Request/Response Examples
Protected Request:Successful Response:
7. HTTP Examples
Sometimes, simple API Keys are passed using a custom header rather than the standardBearer format.
*Note: While common for server-to-server APIs, Bearer tokens are preferred for user authentication.*
8. JSON Examples
When a user logs out, the API should "revoke" the token by setting it to NULL in the database.9. Best Practices
-
Use
randombytes(): Never userand(),mtrand(), ormd5(time())to generate tokens. They are predictable and easily hacked. Always use a cryptographically secure function likerandombytes().
-
Database Indexing: Ensure your
apitokencolumn in MySQL has aUNIQUE INDEX. Since every single API request requires aWHERE apitoken = ?lookup, an index will make this query lightning fast.
10. Common Mistakes
- Storing API Keys in Frontend Code: If you build a React or Vue app, do NOT hardcode your secret API keys in the JavaScript. Anyone can open Chrome DevTools and steal them.
- Not revoking tokens: If a user resets their password, you should regenerate or revoke their API token. Otherwise, an attacker who stole the token can still access the account!
11. Mini Exercises
-
1.
What PHP function is used to convert binary data (from
randombytes) into a readable hexadecimal string?
bin2hex())*
12. Coding Challenges
Challenge 1: Write a PHP snippet that takes theAuthorization header, checks if it starts with "Bearer ", and extracts just the token string into a variable called $token.
13. MCQs with Answers
What is the most secure way to generate a random token in PHP?
When authenticating a request, how does the server know WHICH user the token belongs to?
Why should the apitoken column in MySQL be indexed?
14. Interview Questions
-
Q: Walk me through the database flow of a token-based login system, from the
/loginrequest to a subsequent protected/profilerequest.
- Q: What is the difference between an API Key and a User Bearer Token?
- Q: How do you securely handle "Log Out" in a stateless API?
15. FAQs
Q: Doesn't looking up the token in the database on EVERY request slow down the server? A: Yes, it is a database hit on every request. For small to medium apps, an indexed MySQL lookup takes less than 1 millisecond, which is fine. However, for massive apps like Netflix, hitting the database on every request is too slow. They use caching (like Redis) or JWTs (which we cover next!).16. Summary
In Chapter 14, we built a working authentication system. We generated a secure random token using PHP'srandom_bytes(), saved it to the database, and required the client to pass it via the Authorization: Bearer header. We then learned how to extract that header, query the database, and verify the user's identity statelessly.