Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/johanns/ref-secure-share

SecureShare is a tutorial and reference implementation of a one-time-use message sharing web-app, developed using Next.JS 14, TypeScript, Prisma, and styled with Tailwind CSS
https://github.com/johanns/ref-secure-share

cryptography next tailwindcss tutorial typescript webcrypto

Last synced: 11 days ago
JSON representation

SecureShare is a tutorial and reference implementation of a one-time-use message sharing web-app, developed using Next.JS 14, TypeScript, Prisma, and styled with Tailwind CSS

Awesome Lists containing this project

README

        

## Secure Share web-app

*Important Note: This project is part of an in-person tutorial series and serves as a reference implementation for educational purposes. The goal is to demonstrate how to build a simple product with real-world utility beyond academic exercises. It is not intended for production use.*

SecureShare is a tutorial and reference implementation of a one-time-use message sharing web-app, developed using Next.JS 14, TypeScript, Prisma, and styled with Tailwind CSS

### Core functionality

- Messages are encrypted directly on the sender's device (browser) before being sent, so the server only receives and stores encrypted data without ever accessing the encryption key.
- After storing the encrypted message, the server generates a unique retrieval key and returns it to the sender. The sender then creates a unique URL that includes this retrieval key and appends the encryption key in the URL's anchor (the part after '#'). Since the anchor is not transmitted to the server during HTTP requests, the server remains unaware of the encryption key.
- Recipients use this unique URL to retrieve the encrypted message from the server and decrypt it using the encryption key embedded in the URL's anchor.
- Once the message is viewed, it is automatically marked as read and its content is overwritten on the server, ensuring that it can only be accessed once.

See [Sequence diagram](#sequence-diagram) below for a detailed overview of the process

![Demo](/doc/screencast.gif)

#### Technology Stack:

Framework: Next.js 14
Language: TypeScript
ORM: Prisma (for PostgreSQL)
Styling: Tailwind CSS

### System requirements

- Node.js (16.x or later) or Bun (1.1 or later)
- PostgreSQL (13.x or later)

### Recommended tools

- Visual Studio Code
- Postman
- Chrome

### Setup

1. Clone the repository:

```bash
git clone [email protected]:johanns/ref-secure-share.git
```

2. Install dependencies:

```bash
npm install
```
or
```bash
bun install
```

3. Create a `.env` file in the project root and add the following environment variables:

```bash
DATABASE_URL="postgresql://:@localhost:5432/"
```

NOTE: Replace ``, ``, and `` with your PostgreSQL credentials.

4. Run the Prisma migration:

```bash
npx prisma migrate dev
```
or
```bash
bun run prisma migrate dev
```

5. Run the development server:

```bash
npm run dev
```
or
```bash
bun run dev
```

5. Open your browser and navigate to `http://localhost:3000`.

### Project directory structure and core files

```
prisma
├── migrations/ -- Database migration files
└── schema.prisma -- Prisma schema definition

src
├── app
│   ├── api
│   │   └── message
│   │   ├── route.ts -- Message creation endpoint (POST)
│   │   └── [stub]
│   │   └── route.ts -- Message retrieval endpoint (GET, DELETE)
│   ├── layout.tsx -- Application layout
│   ├── page.tsx -- Message creation page
│   └── [stub]
│   └── page.tsx -- Message retrieval page
├── assets
│   └── css
│   └── globals.css
├── lib
│   ├── crypto.ts - Client-side encryption/decryption functions
│   ├── modelValidationError.ts - Model validation error handler
│   └── prisma.ts - Prisma client initialization
└── models
└── message.ts - Message model
```

### Sequence diagram

#### Compose (happy path)

```mermaid
sequenceDiagram
autonumber

Sender->>Server: GET /

Server-->>Sender: Render
/app/page.tsx

note over Sender,Server: On form submit
Sender->>Sender: Generate encryption key
/lib/crypto.ts
Sender->>Sender: Encrypt data
/lib/crypto.ts
Sender->>+Server: Submit encrypted form data

Server<<-->>Database: Find unique retrieval stub
/models/message.ts
Server<<-->>Database: Store encrypted form data
/models/message.ts
Server-->>-Sender: Render JSON: {stub: stub}

Sender->>Sender: Construct retrieval URL
(stub + key)

note over Sender,Server: Show retrieval URL
```

#### Retrieve (happy path)

```mermaid
sequenceDiagram
autonumber

Recipient->>+Server: GET /
/app/[stub]/page.tsx
Server-->>-Recipient: Render page

note over Recipient,Server: On page load
useEffect(...)

Recipient->>+Server: GET /api/message/[stub]
/app/api/message/[stub]/route.ts
Server<<-->>Database: Find encrypted data
/models/message.ts
Server<<-->>Database: Mark message as read
/models/message.ts
Server-->>-Recipient: Render JSON: {data: encryptedData}

Recipient->>Recipient: Extract key from URL
/lib/crypto.ts
Recipient->>Recipient: Decrypt data
/lib/crypto.ts

note over Recipient,Server: Show decrypted data or already read notice
```