API Authentication
By the Syncfusion DevTutorials team · Last updated
Make the API ask who is calling: protect endpoints with API keys, read and validate JWT bearer tokens, and answer 401 with WWW-Authenticate.
Authentication answers one simple question: Who is calling?
Before an API returns private information or performs an action, it must verify the identity of the caller. The caller may prove their identity using an API key, a token, or another authentication method.
Authentication happens before the API decides what the caller is allowed to do. That second step is called authorization, and it is covered in a later lesson.
Watch Anyone Read Every Order
The Brew & Bytes API has an endpoint that returns orders. There is one problem: it does not check who is calling. Press Run.
Program.cs — anyone can read every order
The request sends no API key, no token, and no credentials. Yet the API still returns the customer ids, the order totals, and the order information. Anyone who discovers the URL can access the data.
This is one of the most common API security mistakes.
In simple words: the API never verified the identity of the caller. In this lesson, you will learn how to require authentication before returning protected data.
TL;DR
- Authentication answers Who are you?
- Authorization answers What are you allowed to do?
- API keys are secret values often used for server-to-server communication.
- JWTs (JSON Web Tokens) are commonly used to authenticate users.
- A JWT is sent in this header:
Authorization: Bearer <token> - A JWT contains a header, a payload, and a signature.
- Anyone can read the header and payload.
- The signature proves the token has not been changed.
- Every request should validate the signature, the expiration (
exp), and the audience (aud). - Missing or invalid credentials should return
401 Unauthorized, with an appropriateWWW-Authenticateheader.
A Real-World Example
Think about entering an office building. A security guard checks your ID card before allowing access.
The ID card includes your name, your photo, an expiry date, and security features that are difficult to fake. The guard does not call headquarters every time someone enters. Instead, they verify that the card is genuine and that the card has not expired.
JWTs work in a similar way. The token contains information about the user, and the API verifies that the token is valid before trusting it.
The client sends credentials with each request. The API validates them and returns either a successful response or an authentication error.
What You Will Learn
In this lesson, you will learn:
- The difference between authentication and authorization.
- How API keys work.
- What information a JWT contains.
- How JWT validation works.
- Why token signatures matter.
- How OAuth 2.0 and PKCE support secure sign-in.
Authentication vs Authorization
These concepts are closely related but solve different problems.
| Question | Concept |
|---|---|
| Who is calling? | Authentication |
| What may they do? | Authorization |
Examples: a valid token means authentication succeeds. If a staff permission is required, authorization decides whether access is allowed. A missing token returns 401 Unauthorized. A valid token with insufficient permission returns 403 Forbidden.
API Keys
API keys are commonly used when one server talks to another server. A partner receives a secret key and sends it with each request.
Example: X-Api-Key: bb_live_7f3a...
Program.cs — an API key
Results:
No Key
The response is 401 Unauthorized with WWW-Authenticate: ApiKey header="X-Api-Key".
Invalid Key
The response is 401 Unauthorized.
Valid Key
The response is 200 OK. The request succeeds.
Never put API keys inside browser applications or mobile apps. Users can pull them out of the app and use them somewhere else. API keys are only for trusted server-to-server communication.
Inside a JWT
A JSON Web Token (JWT) contains three parts that are separated by periods: header.payload.signature
A JWT contains a header, payload, and signature. Only the signature proves the token is authentic.
JwtDecoder.cs — look inside a JWT
Header
The header contains metadata about the token. Example: {"alg": "HS256", "typ": "JWT"}
Payload
The payload contains claims. Example: {"sub": "customer-7", "aud": "brew-and-bytes-api", "exp": 1780000000}
Important claims include:
| Claim | Purpose |
|---|---|
sub | User identifier |
aud | Intended API |
exp | Expiration time |
iss | Token issuer |
role | User role |
Signature
The signature proves the token was issued by a trusted authority and has not been changed.
Important
Anyone who has the token can read the header and payload. Never store passwords, API secrets, or sensitive private information inside a JWT.
Validate the Token
The API should validate every bearer token before processing a protected request. The validation process follows four steps.
1. Read the Token
Read the header: Authorization: Bearer eyJ...
2. Verify the Signature
The API recalculates the signature and compares it with the token.
3. Check Expiration
Verify that the time in "exp": 1780000000 has not passed.
4. Check Audience
Verify that "aud": "brew-and-bytes-api" matches your API.
Program.cs — validate a bearer token
Results:
| Token State | Result |
|---|---|
| Valid token | Access granted |
| Expired token | 401 Unauthorized |
| Invalid audience | 401 Unauthorized |
| Invalid signature | 401 Unauthorized |
| Missing token | 401 Unauthorized |
Each failure should explain the problem using the WWW-Authenticate header.
In real ASP.NET Core applications, JWT validation is usually handled for you with this setup: builder.Services.AddAuthentication().AddJwtBearer(); and this call on protected endpoints: .RequireAuthorization(). The framework does the same validation steps for you.
How Token Signing Works
When a user signs in, a trusted server creates the token. It creates a header, creates a payload, signs both using a secret or private key, and produces a signature. The token is then returned to the client.
JwtSigner.cs — sign a token
Even a tiny change produces a completely different signature. For example, {"sub": "customer-7"} and {"sub": "customer-8"} generate different signatures.
Because the signature depends on the content, users cannot change claims without making the token invalid.
Store signing secrets in a safe place. Use configuration files, environment variables, or secret-management services. Do not hard-code secrets in source code.
Signing In with OAuth 2.0 and PKCE
Most modern sign-in systems use OAuth 2.0 Authorization Code Flow with PKCE. Instead of handling passwords directly:
- The user signs in through an identity provider.
- The identity provider returns an authorization code.
- The application exchanges the code for tokens.
PKCE adds extra protection by checking that the application that exchanges the code is the same application that started the sign-in process.
PKCE protects authorization codes by linking them to the application that initiated sign-in.
Pkce.cs — sign in with PKCE
Important parts:
Code Verifier
A secret value that is generated by the client.
Code Challenge
A hash of the verifier: BASE64URL(SHA256(verifier))
State
A random value that prevents request forgery. Example: state=xyz123
Token Exchange
The authorization server validates the verifier before issuing tokens. If the verifier does not match, this error is returned: {"error": "invalid_grant"}
The stolen authorization code becomes useless.
Do not build your own authentication system or identity provider. Use a trusted provider such as Microsoft Entra ID, Auth0, Keycloak, or another established identity platform.
Where You See This
- Mobile apps authenticate users with bearer tokens.
- Web applications use OAuth 2.0 and PKCE for sign-in.
- Partner integrations often use API keys.
- Internal services may use machine-to-machine tokens.
- Public APIs protect user and business data through token validation.
Common mistakes
| Symptom | Cause | Fix |
|---|---|---|
| Anyone can view private data | Authentication is missing | Require tokens or API keys |
| Expired tokens continue to work | Expiration is not checked | Validate exp |
| Tokens issued for another API are accepted | Audience is not checked | Validate aud |
| Modified tokens are accepted | Signature is not verified | Validate the signature |
| Stolen authorization codes can be exchanged | OAuth flow does not use PKCE | Use PKCE and verify the code verifier |
| API keys are discovered by users | Keys are embedded in client apps | Move keys to server-side code only |
Exercises
What to Remember
- Every endpoint with private data must ask who is calling.
- API keys are for servers. JWTs are for the apps of users.
- The payload of a JWT can be read by anyone. The signature proves that it is real.
- Check signature, expiry and audience on every request.
- Missing or bad credentials:
401withWWW-Authenticate.
Next: API Authorization and Security. You will decide what each caller is allowed to do, and when to answer 403 Forbidden.