Skip to content

tulio3101/TwitterSpringBoot

Repository files navigation

Twitter-like Application with Microservices and Auth0

A secure Twitter-like web application that allows authenticated users to create and view short posts (maximum 140 characters) in a single public global stream. The project begins as a Spring Boot monolith with full Swagger/OpenAPI documentation and evolves into independent microservices (Posts, Feed, and User Authentication) communicating asynchronously via RabbitMQ events. The entire API is secured using Auth0 JWT tokens, and the frontend is built with React using the Auth0 React SDK.

VIDEO

VIDEO EXPLICACIÓN

Architecture Overview

Evolution: Monolith → Microservices

Phase 1 – Monolith

alt text

alt text

Phase 2 – Microservices

alt text

Security Flow

User → Auth0 Login → JWT Access Token
JWT Token → Spring Boot OAuth2 Resource Server
Resource Server → Validates issuer (https://YOUR_DOMAIN.auth0.com/)
                → Validates audience (https://twitter-api)
                → Grants/denies access

Getting Started

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.

Prerequisites

# Verify Java
java -version   # should show 21.x

# Verify Maven
mvn -version

# Verify Node
node -version   # should show 18.x or higher

Auth0 Configuration

Before running the application, set up Auth0:

  1. Create a Single Page Application (SPA) in your Auth0 dashboard.

    Auth0 Dashboard

    • Note the Domain and Client ID.
    • Set Allowed Callback URLs: http://localhost:3000
    • Set Allowed Logout URLs: http://localhost:3000
    • Set Allowed Web Origins: http://localhost:3000

    Application Settings

    Callback URL Configuration

  2. Create an API in Auth0.

    • Set the Identifier (Audience) to: https://twitter-api
    • Enable RBAC and add the following permissions/scopes: read:posts, write:posts, read:profile

Installing

1. Clone the repository

git clone https://github.com/tulio3101/TwitterSpringBoot.git
cd TwitterSpringBoot

2. Set up RabbitMQ via CloudAMQP

This project uses CloudAMQP (free tier) as its AMQP broker — no local installation required.

  1. Create a free account at cloudamqp.com
  2. Create a new instance — select the Little Lemur plan (free)
  3. Open the instance details and copy the AMQP URL (format: amqps://user:password@host/vhost)
  4. Use the individual parts of that URL to populate the RABBITMQ_* environment variables in the next step

3. Configure environment variables

Each Spring Boot service reads configuration from environment variables. Set the following before running each service:

Variable Used By Description
MONGODB_URI All services MongoDB connection string
AUTH0_ISSUER_URI Twitter (Gateway) https://YOUR_DOMAIN.auth0.com/
CORS_ALLOWED_ORIGIN Twitter (Gateway) Frontend origin, e.g. http://localhost:3000
SERVER_PORT Twitter (Gateway) Service port (default: 4040)
RABBITMQ_HOST PostsService, FeedService CloudAMQP hostname (e.g. your-instance.cloudamqp.com)
RABBITMQ_PORT PostsService, FeedService AMQP port (5672 for AMQP, 5671 for AMQPS)
RABBITMQ_USERNAME PostsService, FeedService CloudAMQP username
RABBITMQ_PASSWORD PostsService, FeedService CloudAMQP password
RABBITMQ_VIRTUAL_HOST PostsService, FeedService CloudAMQP virtual host (same as your username by default)

Example (Linux/macOS):

export MONGODB_URI="mongodb+srv://user:password@cluster.mongodb.net/twitter"
export AUTH0_ISSUER_URI="https://YOUR_DOMAIN.auth0.com/"
export CORS_ALLOWED_ORIGIN="http://localhost:3000"
export RABBITMQ_HOST="your-instance.cloudamqp.com"
export RABBITMQ_PORT="5672"
export RABBITMQ_USERNAME="your-cloudamqp-user"
export RABBITMQ_PASSWORD="your-cloudamqp-password"
export RABBITMQ_VIRTUAL_HOST="your-cloudamqp-vhost"

4. Build and run the Spring Boot services

Run each service in a separate terminal:

# Terminal 1 – Twitter API Gateway (Monolith / Gateway)
cd Twitter
mvn spring-boot:run
# Runs on port 4040
# Terminal 2 – PostsService (Microservice)
cd PostsService
mvn spring-boot:run
# Runs on port 8081
# Terminal 3 – FeedService (Microservice)
cd FeedService
mvn spring-boot:run
# Runs on port 8082
# Terminal 4 – UserAuthentication (Microservice)
cd UserAuthentication
mvn spring-boot:run
# Runs on port 8082

5. Configure and run the frontend

Create a .env file inside the twitter-frontend directory:

REACT_APP_AUTH0_DOMAIN=YOUR_DOMAIN.auth0.com
REACT_APP_AUTH0_CLIENT_ID=YOUR_CLIENT_ID
REACT_APP_API_BASE_URL=http://localhost:4040

Then install dependencies and start the dev server:

cd twitter-frontend
npm install
npm start

The frontend will be available at http://localhost:3000.

6. Quick demo – create your first post

After logging in via the frontend, you can also test the API directly. Obtain a JWT token from your Auth0 tenant and run:

curl -X POST http://localhost:4040/api/posts/create \
  -H "Authorization: Bearer <YOUR_JWT_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"message": "Hello from TwitterSpringBoot!"}'

Then view the public stream (no authentication needed):

curl http://localhost:4040/api/stream

API Documentation

The monolith exposes a full Swagger UI powered by Springdoc OpenAPI 2.6.0:

  • Swagger UI: http://localhost:4040/swagger-ui.html
  • OpenAPI JSON spec: http://localhost:4040/v3/api-docs

Endpoint Reference

Method Endpoint Auth Required Description
GET /api/posts No Retrieve all posts
POST /api/posts/create Yes Create a new post (max 140 chars)
PUT /api/posts/update/{postId} Yes Update an existing post
DELETE /api/posts/{postId} Yes Delete a post
GET /api/stream No Get the global public feed
DELETE /api/stream/{postId} Yes Remove a post from the stream
POST /api/users/me Yes Register the currently authenticated user
GET /api/users/me Yes Get the current user's profile
GET /api/users/{id} No Get a user profile by ID

Protected endpoints require a valid JWT Bearer token issued by Auth0 with audience https://twitter-api.

Running the Tests

Explain how to run the automated tests for this system.

Backend context tests

Each microservice includes a Spring Boot application context test. Run from each service directory:

# Run from each service root directory (Twitter, PostsService, FeedService, UserAuthentication)
mvn test

These tests verify that the Spring Boot application context loads correctly with all beans, security configuration, and database connections.

End-to-end tests

Via Swagger UI:

  1. Open http://localhost:4040/swagger-ui.html
  2. Click Authorize and paste your JWT token (obtained from Auth0 or the frontend after login)
  3. Test each protected endpoint directly from the browser

For example, to test post creation:

  • Expand POST /api/posts/create
  • Click Try it out
  • Enter {"message": "Hello from Swagger!"} as the request body
  • Execute and verify a 201 Created response

Via curl:

# Public endpoint – no token required
curl -X GET http://localhost:4040/api/posts

# Public endpoint – get global stream
curl -X GET http://localhost:4040/api/stream

# Protected endpoint – create a post
curl -X POST http://localhost:4040/api/posts/create \
  -H "Authorization: Bearer <JWT>" \
  -H "Content-Type: application/json" \
  -d '{"message": "Test post from curl"}'

# Protected endpoint – get current user profile (/api/me equivalent)
curl -X GET http://localhost:4040/api/users/me \
  -H "Authorization: Bearer <JWT>"

Auth flow test

  1. Open the frontend at http://localhost:3000
  2. Click Login — you are redirected to Auth0
  3. Authenticate with your credentials
  4. You are redirected back with a valid JWT stored in localStorage
  5. Create a post using the form — it should appear in the public feed
  6. Log out and verify the feed is still publicly readable without authentication

Deployment

Frontend on Amazon S3 (or Vercel/Netlify)

The React single-page application is built (npm run build) and deployed as static assets. The frontend authenticates users via Auth0 and makes secure, cross-origin HTTP requests to the AWS API Gateway (for serverless components) and the EC2 instance (for the feed).

alt text

alt text

Microservices on AWS Lambda & EC2

To comply with the serverless architecture while maintaining the event-driven messaging requirement (RabbitMQ):

  1. PostsService & UserAuthentication: Deployed as AWS Lambda functions behind a single AWS API Gateway using aws-serverless-java-container. This allows Spring Boot's @RestController and Spring Security (Auth0 JWT validation) to run seamlessly in a serverless environment.
  2. FeedService: Deployed on an AWS EC2 instance. This architectural decision was made because RabbitMQ requires a persistent, long-lived TCP connection (@RabbitListener) which is fundamentally incompatible with the ephemeral, freeze-thaw lifecycle of AWS Lambda.

alt text

alt text

alt text

Built With

Authors

License

This project is licensed under the MIT License — see the LICENSE file for details.

Acknowledgments

About

Monolith and Microservice twitter application

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors