Skip to content
Merged
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
*~
/.gradle/
/.idea/
/*/.idea/
/.micronaut/
/build/
AuthGenHash/bin
setenv.sh
/UnityAuth/bin/
3 changes: 3 additions & 0 deletions AuthGenHash/.sdkmanrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Enable auto-env through the sdkman_auto_env config
# Add key=value pairs of SDKs to use below
java=21.0.4-tem
10 changes: 6 additions & 4 deletions AuthGenHash/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
plugins {
id("com.github.johnrengelman.shadow") version "8.1.1"
id("io.micronaut.application") version "4.2.1"
id("com.gradleup.shadow") version "${shadowVersion}"
id("io.micronaut.application") version "${micronautPluginVersion}"
id("io.micronaut.test-resources") version "${micronautPluginVersion}"
id("io.micronaut.aot") version "${micronautPluginVersion}"
}

version = "0.1"
Expand All @@ -27,8 +29,8 @@ application {
mainClass.set("io.unityfoundation.auth.AuthGenHashCommand")
}
java {
sourceCompatibility = JavaVersion.toVersion("17")
targetCompatibility = JavaVersion.toVersion("17")
sourceCompatibility = JavaVersion.toVersion("21")
targetCompatibility = JavaVersion.toVersion("21")
}


Expand Down
7 changes: 6 additions & 1 deletion AuthGenHash/gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
micronautVersion=4.2.4
# Java
javaVersion=21
# Micronaut
micronautVersion=4.8.2
micronautPluginVersion=4.5.3
shadowVersion=8.3.6
Binary file modified AuthGenHash/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion AuthGenHash/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
8 changes: 5 additions & 3 deletions AuthGenHash/gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

##############################################################################
#
Expand Down Expand Up @@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
Expand Down Expand Up @@ -84,7 +86,7 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Expand Down Expand Up @@ -203,7 +205,7 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
Expand Down
22 changes: 12 additions & 10 deletions AuthGenHash/gradlew.bat
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem

@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
Expand Down Expand Up @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

Expand All @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto execute

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

Expand Down
2 changes: 1 addition & 1 deletion AuthGenHash/settings.gradle
Original file line number Diff line number Diff line change
@@ -1 +1 @@
rootProject.name="AuthGenHash"
rootProject.name="AuthGenHash"
10 changes: 10 additions & 0 deletions DockerfileFrontend-dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM node:24

COPY frontend frontend
WORKDIR frontend
RUN npm install

EXPOSE 3000

# Start the app in development mode
ENTRYPOINT ["npm", "run", "dev"]
4 changes: 2 additions & 2 deletions FrontendDockerfile → DockerfileFrontend-prod
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Build the frontend and serve with nginx
FROM node:18
FROM node:24 AS builder

COPY frontend frontend
WORKDIR frontend
RUN npm install && npm run build

FROM nginx:1.24.0-alpine

COPY --from=0 /frontend/build /usr/share/nginx/html
COPY --from=builder /frontend/build /usr/share/nginx/html
COPY nginx-default.conf /etc/nginx/conf.d/default.conf
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
compose_api:
docker network create unity-network > /dev/null 2>&1 || true
docker compose -f ./docker-compose.local.yml up unity-auth-db unity-auth-api

compose_ui:
docker network create unity-network > /dev/null 2>&1 || true
docker compose -f ./docker-compose.local.yml up unity-auth-db unity-auth-ui

compose_all:
docker network create unity-network > /dev/null 2>&1 || true
docker compose -f ./docker-compose.local.yml up
202 changes: 202 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# UnityAuth

UnityAuth is a comprehensive authentication and authorization service built with modern
microservices architecture. It provides JWT-based authentication, user management, and
a web-based administration interface.

## QuickStart

### Local Environment
From the project root, copy `setenv.sh.example` into `setenv.sh` and update the correct
environment variable values.
* If used together with Libre311 project
(https://github.com/UnityFoundation-io/Libre311.git), `LIBRE311_UI_BASE_URL` must be updated
to base URL of Libre311 UI.
* If use a local database, also update the `DATASOURCES_DEFAULT_*` environment variables
for the corresponding database.

Run the UnityAuth API with:
```shell
source setenv.sh
cd UnityAuth
./gradlew run
```

Run the UnityAuth UI in another terminal windows:
```shell
source setenv.sh
cd frontend
npm install
npm run dev
```

### Docker Environment
To launch the auth service, you can use the docker compose from the project root:

```sh
docker compose -f docker-compose.local.yml up
```

This will start containers for the UnityAuth API, UI and database server with service
names `unity-auth-api`, `unity-auth-ui`, and `unity-auth-db`, respectively.

- **UnityAuth API** on http://localhost:9090 (inside Docker http://unity-auth-api:9090)
- **UnityAuth UI** on http://localhost:3001 (inside Docker http://unity-auth-ui:3000)
- **MySQL Database** is open on port `13306` in `localhost` (within Docker is port `3306`
with host name `unity-auth-db`)

#### Hosts File Updates

When using Docker environment, add these to your `/etc/hosts` file
for consistent internal-external service name resolution:

```txt
127.0.0.1 unity-auth-api
127.0.0.1 unity-auth-ui
```

You can log in with these accounts.
**Password for all the following accounts is `test`**

- **Unity Administrator** `[email protected]`
- **Tenant Administrator** `[email protected]`
- **Libre311 Administrator** `[email protected]`
- **Libre311 Request Manager** `[email protected]`
- **Libre311 Jurisdiction Administrator** `[email protected]`
- **Libre311 Jurisdiction Request Manager** `[email protected]`
- **STL Sub-tenant Administrator** `[email protected]`

## Project Structure

This repository contains three main subprojects:

### 1. UnityAuth (Main Service)

**Location:** `/UnityAuth/`
**Technology:** Java 21 + Micronaut Framework

The core authentication service that provides:

- JWT token generation and validation
- User authentication and authorization
- RESTful API endpoints for authentication operations
- Database integration with MySQL
- JWK (JSON Web Key) management for token signing
- Flyway database migrations

**Key Features:**

- Micronaut-based microservice architecture
- JWT security with configurable key rotation
- BCrypt password hashing
- Database connection pooling with HikariCP
- Reactive programming support with Reactor

### 2. AuthGenHash (Utility Tool)

**Location:** `/AuthGenHash/`
**Technology:** Java 17 + Micronaut + PicoCLI

A command-line utility for generating secure password hashes compatible with the UnityAuth service.

**Purpose:**

- Generate BCrypt password hashes for administrative users
- Secure password handling (interactive mode prevents history logging)
- Standalone tool for initial system setup and user management

### 3. Frontend (Web Administration Interface)

**Location:** `/frontend/`
**Technology:** SvelteKit + TypeScript + Tailwind CSS

A modern web application providing administrative interface for the UnityAuth service.

**Features:**

- User authentication and session management
- User administration and management
- Tenant management capabilities
- Settings configuration
- Responsive design with Tailwind CSS
- TypeScript for type safety
- Comprehensive testing with Playwright and Vitest

**Key Technologies:**

- SvelteKit for the web framework
- TypeScript for type safety
- Tailwind CSS for styling
- Playwright for end-to-end testing
- Vitest for unit testing
- ESLint and Prettier for code quality

## Architecture Overview

The system follows a microservices architecture:

1. **Database Layer:** MySQL database for persistent storage
2. **API Layer:** UnityAuth service provides REST APIs
3. **Frontend Layer:** SvelteKit web application
4. **Utility Layer:** AuthGenHash for administrative tasks

## Client Integration

To integrate with the UnityAuth service, add this configuration to your client application's `application.yaml`:

```yaml
security:
enabled: true
token:
enabled: true
jwt:
enabled: true
signatures:
jwks:
unity:
url: ${AUTH_JWKS:`http://localhost:8081/keys`}
```

## Security Configuration

The service uses JSON Web Keys (JWK) for token signing. To generate primary and secondary keys:

1. Visit <https://mkjwk.org/>
2. Generate JSON Web Keys
3. Set environment variables:
- `JWK_PRIMARY`: Primary signing key
- `JWK_SECONDARY`: Secondary signing key for rotation

## Development Environment

### Prerequisites

- Java 17 or higher
- Node.js 18 or higher
- Docker and Docker Compose
- MySQL 8.0 (if running locally)

### Individual Service Development

#### UnityAuth Service

```bash
cd UnityAuth
./gradlew run
```

#### Frontend Development

```bash
cd frontend
npm install
npm run dev
```

#### AuthGenHash Utility

```bash
cd AuthGenHash
./gradlew shadowJar
java -jar build/libs/AuthGenHash-0.1-all.jar -p
```
10 changes: 10 additions & 0 deletions UnityAuth/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
gradle/caches

# Exclude gradle build caches but not wrapper
.gradle/
.DS_Store

build/

docker-compose.*
DockerfileAPI
3 changes: 3 additions & 0 deletions UnityAuth/.sdkmanrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Enable auto-env through the sdkman_auto_env config
# Add key=value pairs of SDKs to use below
java=21.0.4-tem
Loading