Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 0 additions & 29 deletions .circleci/config.yml

This file was deleted.

5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.env
.git
node_modules
target
.DS_Store
8 changes: 8 additions & 0 deletions .env_example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copy this file to .env and fill in your Castle credentials.
# Grab them from the Castle dashboard: https://dashboard.castle.io (Settings -> API).

# Publishable key, used by the browser SDK to mint request tokens.
castle_pk=

# Server-side API secret, used by the Castle Java SDK.
castle_api_secret=
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: CI

on:
push:
branches: [master, main]
pull_request:

jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
java-version: ['17', '21', '25']
steps:
- name: Check out example
uses: actions/checkout@v5
with:
path: example

# castle-java 3.0.0 is not yet on Maven Central; build it from source and
# install it into the local repository so the example can resolve it.
- name: Check out castle-java SDK
uses: actions/checkout@v5
with:
repository: castle/castle-java
ref: develop
path: castle-java

- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: ${{ matrix.java-version }}
cache: maven

- name: Install castle-java SDK
run: mvn -B -ntp -f castle-java/pom.xml install -DskipTests -Dmaven.javadoc.skip=true

- name: Build and test example
run: mvn -B -ntp -f example/pom.xml verify
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.DS_Store
.env
.idea
*.iml
node_modules
target
23 changes: 0 additions & 23 deletions .project

This file was deleted.

35 changes: 35 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Fetch the Castle browser SDK from npm and build the Tailwind stylesheet.
FROM node:20-slim AS frontend
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY tailwind.config.js ./
COPY src/tailwind.css ./src/tailwind.css
COPY src/main/resources/templates ./src/main/resources/templates
COPY static ./static
RUN npm run build:css

# Build the Spring Boot jar.
FROM maven:3.9-eclipse-temurin-17 AS build
WORKDIR /app
COPY pom.xml ./
RUN mvn -B -q -DskipTests dependency:go-offline
COPY src ./src
RUN mvn -B -q -DskipTests package

# Final runtime image.
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY --from=build /app/target/castle-example.jar ./app.jar
COPY --from=frontend /app/static ./static
COPY --from=frontend /app/node_modules/@castleio/castle-js/dist ./node_modules/@castleio/castle-js/dist

ENV location=docker
ENV PORT=80

# Only the Castle credentials are needed at runtime (e.g. docker run -e ...);
# the simulated demo user values are baked in as code defaults.

EXPOSE 80

ENTRYPOINT ["java", "-jar", "app.jar"]
95 changes: 79 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,94 @@
# Castle Java Example
# Castle demo application: Java

[![CircleCI](https://circleci.com/gh/castle/castle-java-example.svg?style=svg)](https://circleci.com/gh/castle/castle-java-example)
This project demonstrates key Castle workflows in a small Spring Boot app built
on the [Castle Java SDK](https://github.com/castle/castle-java). The pages are
rendered server-side with Thymeleaf and the JSON endpoints are plain Spring MVC
controllers.

This is an example of integrating Castle with a standard Java web application.
## What's demonstrated

Prerequisites
==============
The app walks through a full user lifecycle. Every action mints a fresh Castle
request token in the browser (`Castle.createRequestToken()`) and forwards it to
the backend, which calls Castle and acts on the verdict.

* Maven
* Java 7+
- **sign up** – `$registration` to `filter` (anonymous, so the email goes in `params`): `$attempted` for a new email, `$failed` (resolved via `matching_user_id`) for an email that already exists
- **login** – `$login` reusing one request token across two calls: `filter` `$attempted` first, then `risk` `$succeeded` on success or `filter` `$failed` (wrong password / unknown user)
- **account** – post-login actions: profile update (`$profile_update` to `risk`), a custom event (`Castle.custom()`), and logout (`$logout` via the non-blocking `log` endpoint)
- **password reset** – `$password_reset` via the non-blocking `log` endpoint
- **lists** – the Lists API (`createList`, `getAllLists`)
- **privacy** – the Privacy API (`requestUserData` and a delete call to the privacy endpoint)
- **webhooks** – incoming Castle webhooks are signature-verified with `verifyWebhookSignature` (against the `X-Castle-Signature` header) and the most recent payloads are listed

Running the code
================
## Prerequisites

Set environment variables `CASTLE_SDK_API_SECRET` and `CASTLE_SDK_APP_ID`.
You'll need a Castle account. If you don't have one, start a free trial at
https://castle.io. For local development, use a **sandbox** environment so demo
traffic from `localhost` stays separate from production data — from the Castle
dashboard (Settings → API) grab the sandbox keys:

- your **publishable key** (`castle_pk`) – used by the browser SDK
- your **API secret** (`castle_api_secret`) – used by the backend SDK

These are the only two values you need to configure.

## Running locally

Requires **JDK 17+** and **Maven**.

```bash
git clone https://github.com/castle/castle-java-example.git
cd castle-java-example
```

The Castle browser SDK and the Tailwind stylesheet are built from npm, so
install the dependencies and build the CSS:

```bash
npm install
npm run build:css
```

Create your `.env` from the example and fill in your two Castle keys:

```bash
cp .env_example .env
```
export CASTLE_SDK_API_SECRET=....
export CASTLE_SDK_APP_ID=...

Run the app:

```bash
mvn spring-boot:run
# Castle Java demo listening on http://localhost:4009
```

Run the web server with:
The server listens on `:4009` (override with `PORT`). Open
<http://localhost:4009>.

## Running with Docker

The bundled `Dockerfile` builds the stylesheet and browser SDK, compiles the
Spring Boot jar and serves the app on port 80.

```bash
docker build -t castle-java-example .

docker run -d -p 4009:80 \
-e castle_pk=YOUR_PUBLISHABLE_KEY \
-e castle_api_secret=YOUR_API_SECRET \
castle-java-example
```
$ mvn jetty:run

The app will be available at http://127.0.0.1:4009. Point it at a Castle sandbox
environment when running locally.

## Running the tests

```bash
mvn test
```

Navigate to:
## Disclaimer

http://localhost:8080/
We're sharing this sample app in the hope that other developers find it
valuable. Although it is not an officially supported sample, we welcome
questions and suggestions at `support@castle.io`.
Loading
Loading