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

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: about 2 months 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

> [!WARNING]
> 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

#### Client-Side Encryption:
Messages are encrypted directly within the sender's browser before transmission. This ensures that the server only receives and stores the encrypted data, without ever accessing the encryption key.

#### Unique URL Generation:
After storing the encrypted message, the server generates a unique retrieval key and returns it to the sender. The sender then constructs a unique URL that includes this retrieval key and appends the encryption key in the URL's anchor (the portion after #). Since the anchor is not sent to the server during HTTP requests, the server remains unaware of the encryption key.

#### Secure Message Retrieval and Decryption:
Recipients use the unique URL to fetch the encrypted message from the server. The encryption key embedded in the URL's anchor allows them to decrypt the message locally in their browser.

#### One-Time Access Enforcement:
Once the message has been viewed, it is automatically marked as read, and its content is overwritten on the server. This ensures that the message can only be accessed a single time, maintaining its one-time-use nature.

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 git@github.com: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
```