MSDN Documentation

Explore Examples: Token-Based Authentication

Token-Based Authentication Examples

This section provides practical examples demonstrating how to implement and utilize token-based authentication in your applications. Token-based authentication is a stateless method for securing APIs and web services, offering scalability and flexibility.

What is Token-Based Authentication?

In token-based authentication, after a user successfully logs in with their credentials, the server issues a unique token to the client. This token is then included in subsequent requests to authenticate the user. The server can validate this token without needing to store session state, making it highly efficient.

Common Token Types

Example 1: Generating and Validating a JWT

Server-Side: Generating a JWT

This example uses Node.js with the 'jsonwebtoken' library to create a JWT upon successful login.

Node.js (Server-Side)

const jwt = require('jsonwebtoken');
const secretKey = 'your_super_secret_key'; // Should be kept secure and not hardcoded in production

function generateAuthToken(userId, username) {
    const payload = {
        userId: userId,
        username: username,
        iss: 'your_api_issuer', // Issuer
        aud: 'your_api_audience', // Audience
        exp: Math.floor(Date.now() / 1000) + (60 * 60) // Token expires in 1 hour
    };
    return jwt.sign(payload, secretKey);
}

// Example usage after successful authentication
const userId = 123;
const username = 'testuser';
const token = generateAuthToken(userId, username);
console.log('Generated Token:', token);
// The token would then be sent back to the client in the response body or header.

Client-Side: Sending a JWT with Requests

The client receives the token and includes it in the 'Authorization' header for protected API calls.

JavaScript (Client-Side Fetch API)

async function fetchDataWithToken(token) {
    const response = await fetch('/api/protected-resource', {
        method: 'GET',
        headers: {
            'Authorization': `Bearer ${token}`,
            'Content-Type': 'application/json'
        }
    });

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

    return await response.json();
}

// Example usage:
const userToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEyMywidXNlcm5hbWUiOiJ0ZXN0dXNlciIsImlzcyI6InlvdXJfYXBpX2lzc3VlciIsImF1ZCI6InlvdXJfYXBpX2F1ZGllbmNlIiwiZXhwIjoxNjI3ODY4ODAwfQ.SflKxwRJSMe...'; // Replace with actual token
fetchDataWithToken(userToken)
    .then(data => console.log('Data from protected resource:', data))
    .catch(error => console.error('Error fetching data:', error));

Server-Side: Verifying a JWT

The server verifies the token's signature and checks for expiration and other claims.

Node.js (Server-Side Middleware)

const jwt = require('jsonwebtoken');
const secretKey = 'your_super_secret_key';

function authenticateToken(req, res, next) {
    const authHeader = req.headers['authorization'];
    const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN

    if (token == null) return res.sendStatus(401); // If there's no token

    jwt.verify(token, secretKey, (err, user) => {
        if (err) {
            console.error('JWT Verification Error:', err.message);
            return res.sendStatus(403); // If token is invalid or expired
        }
        req.user = user; // Attach user info to the request
        next(); // Proceed to the next handler
    });
}

// Apply this middleware to protected routes
// app.get('/api/protected-resource', authenticateToken, (req, res) => {
//     res.json({ message: 'Access granted to protected resource!', user: req.user });
// });

Example 2: Using an API Key (Simple Token)

For simpler scenarios or internal services, a static API key can act as a token.

Client-Side: Sending an API Key

JavaScript (Client-Side Fetch API)

async function callApiWithApiKey(apiKey) {
    const response = await fetch('/api/public-service', {
        method: 'GET',
        headers: {
            'X-API-Key': apiKey,
            'Content-Type': 'application/json'
        }
    });

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

    return await response.json();
}

// Example usage:
const myApiKey = 'your_generated_api_key_here';
callApiWithApiKey(myApiKey)
    .then(data => console.log('API Key Service Response:', data))
    .catch(error => console.error('Error calling API:', error));

Server-Side: Validating an API Key

The server checks if the provided API key is valid and authorized.

Node.js (Server-Side Middleware)

const validApiKeys = ['your_generated_api_key_here', 'another_valid_key']; // In real app, use a secure store

function validateApiKey(req, res, next) {
    const apiKey = req.headers['x-api-key'];

    if (!apiKey || !validApiKeys.includes(apiKey)) {
        return res.status(401).json({ message: 'Invalid or missing API Key.' });
    }
    next();
}

// Apply this middleware to routes requiring API key authentication
// app.get('/api/public-service', validateApiKey, (req, res) => {
//     res.json({ message: 'API Key accepted! Access granted to public service.' });
// });

Best Practices