19th June 2024

Understanding OAuth and JWT: A Detailed Overview with Practical Examples

oAuth-And-JWT-VS-Online-img

When building modern web applications, securing access to resources and ensuring data integrity are critical aspects. OAuth (Open Authorization) and JWT (JSON Web Token) are two powerful technologies that help in achieving these goals. This blog will provide a comprehensive overview of OAuth and JWT, their use cases, and practical examples to demonstrate their implementation.

1. Introduction to OAuth and JWT

What is OAuth?

OAuth is an open standard for access delegation commonly used for token-based authentication and authorization. It allows third-party services to exchange user information without exposing user credentials. OAuth enables secure access to user resources by issuing access tokens to client applications.

What is JWT?

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object and digitally signed using a secret key or a public/private key pair. JWTs are often used for authentication and information exchange.

Differences and Relationship between OAuth and JWT
  • OAuth is a framework for token-based authorization and can use different types of tokens, including JWT.
  • JWT is a token format that can be used within OAuth for access tokens and ID tokens.

2. When to Use OAuth and JWT

Use Cases for OAuth
  • Third-Party Logins: Allowing users to log in using their existing accounts from services like Google, Facebook, or GitHub.
  • Resource Access Delegation: Granting third-party applications access to user resources on a server without sharing credentials.
  • Single Sign-On (SSO): Enabling users to log in once and gain access to multiple applications.
Use Cases for JWT
  • API Authentication: Securing API endpoints by validating JWTs passed in HTTP headers.
  • Information Exchange: Transmitting claims between parties in a secure and compact way.
  • Session Management: Maintaining user sessions without the need for server-side storage.

3. How to Implement OAuth

Setting Up an OAuth Provider

To implement OAuth, you need to set up an OAuth provider. Popular services like Google, Facebook, and GitHub offer OAuth 2.0 support.

Authorizing Client Applications

Client applications must register with the OAuth provider to obtain client credentials (client ID and client secret).

Obtaining Access Tokens

The authorization process typically involves:

  • Authorization Request: The client application redirects the user to the OAuth provider's authorization endpoint.
  • User Consent: The user logs in and consents to the requested permissions.
  • Authorization Code: The OAuth provider redirects the user back to the client application with an authorization code.
  • Token Request: The client application exchanges the authorization code for an access token.
Practical Example: OAuth with Google
  • Register Your Application: Go to the Google API Console and create a new project. Enable the OAuth 2.0 API and configure the OAuth consent screen.
  • Obtain Client Credentials: Generate client ID and client secret.
Authorization Request:
                                
                                    
    <a href="https://accounts.google.com/o/oauth2/v2/auth?scope=email&access_type=offline&include_granted_scopes=true&response_type=code&state=state_parameter_passthrough_value&redirect_uri=http://localhost:3000/callback&client_id=YOUR_CLIENT_ID">
      Sign in with Google
    </a>

                                
                            
Exchange Authorization Code for Access Token:
                                
                                    
  const axios = require('axios');
  
  async function getAccessToken(code) {
    const response = await axios.post('https://oauth2.googleapis.com/token', {
      code: code,
      client_id: 'YOUR_CLIENT_ID',
      client_secret: 'YOUR_CLIENT_SECRET',
      redirect_uri: 'http://localhost:3000/callback',
      grant_type: 'authorization_code'
    });
    return response.data.access_token;
  }

                                
                            

4. How to Implement JWT

Structure of a JWT

A JWT consists of three parts separated by dots (.): Header, Payload, and Signature.

                                
                                    
  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

                                
                            
Creating and Validating JWTs
1. Creating a JWT:
                                
                                    
  const jwt = require('jsonwebtoken');
  
  const token = jwt.sign({ userId: 123 }, 'your-256-bit-secret', { expiresIn: '1h' });
  console.log(token);

                                
                            
2. Validating a JWT:
                                
                                    
  const jwt = require('jsonwebtoken');
  
  function verifyToken(token) {
    try {
      const decoded = jwt.verify(token, 'your-256-bit-secret');
      console.log(decoded);
    } catch (err) {
      console.error('Invalid token');
    }
  }
  
  verifyToken(token);

                                
                            

Practical Example: JWT in a Node.js Application

1. Setup:
                                
                                    
  mkdir jwt-example
  cd jwt-example
  npm init -y
  npm install express jsonwebtoken body-parser

                                
                            
2. Creating the Server:
                                
                                    
  const express = require('express');
  const jwt = require('jsonwebtoken');
  const bodyParser = require('body-parser');
  
  const app = express();
  const secretKey = 'your-256-bit-secret';
  
  app.use(bodyParser.json());
  
  app.post('/login', (req, res) => {
    const { username, password } = req.body;
    // Validate user credentials (this is just an example)
    if (username === 'user' && password === 'pass') {
      const token = jwt.sign({ userId: 1, username: 'user' }, secretKey, { expiresIn: '1h' });
      res.json({ token });
    } else {
      res.status(401).json({ error: 'Invalid credentials' });
    }
  });
  
  app.get('/protected', (req, res) => {
    const token = req.headers['authorization'];
    try {
      const decoded = jwt.verify(token, secretKey);
      res.json({ message: 'This is protected data', user: decoded });
    } catch (err) {
      res.status(401).json({ error: 'Invalid token' });
    }
  });
  
  app.listen(3000, () => {
    console.log('Server running on http://localhost:3000');
  });
 
                                
                            

5. Best Practices and Security Considerations

OAuth Best Practices
  • Use HTTPS: Always use HTTPS to protect data in transit.
  • Scope Limitation: Limit the scope of access tokens to the minimum necessary.
  • Token Expiry: Use short-lived access tokens and refresh tokens.
JWT Best Practices
  • Use Strong Secret Keys: Ensure the secret key is strong and kept confidential.
  • Validate Tokens: Always validate JWTs on the server-side.
  • Expiration Time: Set appropriate expiration times to mitigate the risk of token reuse.

Conclusion

OAuth and JWT are powerful tools for securing access to resources and exchanging information in modern web applications. OAuth is primarily used for access delegation and authorization, while JWT is used for authentication and secure data exchange. By following best practices and understanding their appropriate use cases, you can effectively implement these technologies to enhance the security and functionality of your applications.

Let's develop your ideas into reality