https://github.com/openchami/tokensmith
JWT handling code for the OpenCHAMI project
https://github.com/openchami/tokensmith
Last synced: over 1 year ago
JSON representation
JWT handling code for the OpenCHAMI project
- Host: GitHub
- URL: https://github.com/openchami/tokensmith
- Owner: OpenCHAMI
- License: mit
- Created: 2025-03-17T13:14:01.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-03-18T08:49:52.000Z (over 1 year ago)
- Last Synced: 2025-03-18T09:38:46.941Z (over 1 year ago)
- Language: Go
- Size: 1000 Bytes
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# TokenSmith
TokenSmith bridges external OIDC user identity with internal identity and access management using signed JWTs. It provides internal service-to-service identity and access management, along with a standalone chi middleware for JWT verification using PKI.
## Token Flow
```mermaid
sequenceDiagram
participant User
participant OIDC
participant TokenSmith
participant ServiceA
participant ServiceB
%% User Authentication Flow
User->>OIDC: Authenticate
OIDC-->>User: ID Token
User->>TokenSmith: Exchange ID Token
TokenSmith-->>User: Internal JWT
User->>ServiceA: Request with Internal JWT
%% Service-to-Service Flow
ServiceA->>TokenSmith: Request Service Token
TokenSmith-->>ServiceA: Service JWT
ServiceA->>ServiceB: Request with Service JWT
ServiceB->>ServiceB: Verify JWT (Middleware)
```
## Features
- **Identity Bridging**
- Exchange external OIDC tokens for internal JWTs
- Map external identities to internal service identities
- Group-based authorization and scope management
- Support for multiple OIDC providers (Keycloak, Hydra, Authelia)
- **Service-to-Service Authentication**
- Secure internal service communication
- PKI-based JWT signing and verification
- Service-specific claims and scopes
- Automatic token validation
- **JWT Middleware**
- Standalone chi middleware for JWT verification
- PKI-based signature validation
- Support for RSA key pairs and JWKS
- Scope-based authorization
- Service-to-service authentication
- Extensible claims handling
- **OIDC Provider Support**
- Keycloak integration
- Hydra integration
- Authelia integration
- Extensible provider interface
## Container Deployment
TokenSmith can be deployed using Docker. The following environment variables can be used to configure the service:
### Required Environment Variables
| Environment Variable | Description | Default |
|---------------------|-------------|---------|
| `TOKENSMITH_ISSUER` | The issuer URL for the token service | `https://tokensmith.openchami.dev` |
| `TOKENSMITH_CLUSTER_ID` | The ID of the cluster | `default-cluster` |
| `TOKENSMITH_OPENCHAMI_ID` | The ID of the OpenCHAMI instance | `default-openchami` |
| `TOKENSMITH_CONFIG` | Path to the configuration file | `/tokensmith/config.json` |
| `TOKENSMITH_KEY_DIR` | Directory for storing JWT keys | `/tokensmith/keys` |
| `TOKENSMITH_OIDC_PROVIDER` | OIDC provider type (hydra, keycloak, authelia) | `hydra` |
| `TOKENSMITH_PORT` | HTTP server port | `8080` |
### OIDC Provider Credentials
Depending on your chosen OIDC provider, you'll need to set the following credentials:
#### Hydra
- `HYDRA_CLIENT_ID` - Client ID for Hydra
- `HYDRA_CLIENT_SECRET` - Client Secret for Hydra
#### Keycloak
- `KEYCLOAK_CLIENT_ID` - Client ID for Keycloak
- `KEYCLOAK_CLIENT_SECRET` - Client Secret for Keycloak
#### Authelia
- `AUTHELIA_CLIENT_ID` - Client ID for Authelia
- `AUTHELIA_CLIENT_SECRET` - Client Secret for Authelia
### Example Docker Run Command
```bash
docker run -d \
-p 8080:8080 \
-e TOKENSMITH_ISSUER="https://tokensmith.example.com" \
-e TOKENSMITH_CLUSTER_ID="my-cluster" \
-e TOKENSMITH_OPENCHAMI_ID="my-openchami" \
-e TOKENSMITH_OIDC_PROVIDER="hydra" \
-e HYDRA_CLIENT_ID="your-client-id" \
-e HYDRA_CLIENT_SECRET="your-client-secret" \
-v /path/to/config.json:/tokensmith/config.json \
-v /path/to/keys:/tokensmith/keys \
tokensmith:latest
```
### Important Notes
1. The `keys` directory is used to store JWT signing keys. Make sure to:
- Mount a persistent volume for the keys directory
- Set appropriate permissions on the host directory
- Back up the keys directory regularly
2. The configuration file should be mounted from the host system and contain your group scope mappings. Tokensmith can generate a configuration file to start with: `tokensmith generate-config --config=config.json`
3. For security:
- Never commit OIDC credentials to version control
- Use Docker secrets or a secure secrets management system in production
## Project Structure
```
tokensmith/
├── cmd/
│ └── tokensmith/ # Main application entry point
├── pkg/
│ ├── jwt/ # JWT package (shared)
│ │ ├── oidc/ # OIDC provider implementations
│ │ │ ├── authelia/ # Authelia provider
│ │ │ ├── hydra/ # Hydra provider
│ │ │ └── keycloak/ # Keycloak provider
│ │ └── provider.go # Provider interface
│ ├── tokenservice/ # Token exchange service
│ └── middleware/ # JWT middleware (standalone)
└── example/ # Example applications
└── middleware/ # Example of middleware usage
```
## Local Installation
### Main Service
```bash
go get github.com/openchami/tokensmith
```
### JWT Middleware
```bash
go get github.com/openchami/tokensmith/middleware
```
See the [middleware documentation](middleware/README.md) for detailed usage instructions.
## Usage
### Token Service
The token service can be run as a standalone application. First, generate a default configuration file:
```bash
tokensmith generate-config --config config.json
```
Then start the service with the configuration file:
```bash
tokensmith serve \
--provider=keycloak \
--issuer=http://tokensmith:8080 \
--port=8080 \
--cluster-id=test-cluster-id \
--openchami-id=test-openchami-id \
--config=config.json
```
#### Configuration File
The configuration file (JSON format) contains settings that don't change frequently:
```json
{
"groupScopes": {
"admin": ["admin", "write", "read"],
"operator": ["write", "read"],
"viewer": ["read"],
"user": ["read"]
}
}
```
Configuration options:
| Flag | Description | Default |
|------|-------------|---------|
| `--provider` | OIDC provider type (keycloak, hydra, authelia) | `hydra` |
| `--issuer` | Token issuer identifier | `http://tokensmith:8080` |
| `--port` | HTTP server port | `8080` |
| `--cluster-id` | Unique identifier for this cluster | `cl-F00F00F00` |
| `--openchami-id` | Unique identifier for this instance of OpenCHAMI | `oc-F00F00F00` |
| `--hydra-url` | Hydra admin API URL | `http://hydra:4445` |
| `--authelia-url` | Authelia admin API URL | `http://authelia:9091` |
| `--keycloak-url` | Keycloak admin API URL | `http://keycloak:8080` |
| `--keycloak-realm` | Keycloak realm | `openchami` |
| `--config` | Path to configuration file | `""` |
| Environment Variable | Description |
|------|-------------|
| `HYDRA_CLIENT_ID` | Client ID for hydra |
| `HYDRA_CLIENT_SECRET` | Client Secret for hydra |
| `KEYCLOAK_CLIENT_ID` | Client ID for Keycloak |
| `KEYCLOAK_CLIENT_SECRET` | Client Secret for Keycloak |
| `AUTHELIA_CLIENT_ID` | Client ID for Authelia |
| `AUTHELIA_CLIENT_SECRET` | Client Secret for Authelia |
### JWT Middleware
```bash
go get github.com/openchami/tokensmith/middleware
```
## Development
### Prerequisites
- Go 1.21 or later
- Access to an OIDC provider (Keycloak, Hydra, or Authelia)
### Build & Install
This project uses [GoReleaser](https://goreleaser.com/) to automate releases and embed additional build metadata (commit info, build time, versioning, etc.).
#### 1. Environment Variables
Before building, make sure to set the following environment variables to include detailed build metadata:
- **GIT_STATE**: Indicates whether there are uncommitted changes. (`clean` if no changes, `dirty` if there are.)
- **BUILD_HOST**: Hostname of the machine performing the build.
- **GO_VERSION**: The version of Go used.
- **BUILD_USER**: The username of the person or system performing the build.
Example:
```bash
export GIT_STATE=$(if git diff-index --quiet HEAD --; then echo 'clean'; else echo 'dirty'; fi)
export BUILD_HOST=$(hostname)
export GO_VERSION=$(go version | awk '{print $3}')
export BUILD_USER=$(whoami)
```
#### 2. Installing GoReleaser
Follow the official [GoReleaser installation instructions](https://goreleaser.com/install/) to set up GoReleaser locally.
#### 3. Building Locally with GoReleaser
Use snapshot mode to build locally without releasing:
```bash
goreleaser release --snapshot --clean
```
- The build artifacts (including embedded metadata) will be placed in the `dist/` directory.
- Inspect the resulting binaries to ensure the metadata was correctly embedded.
### Testing
```bash
# Run all tests
go test ./...
# Run specific package tests
go test ./pkg/tokenservice
go test ./pkg/middleware
```
## Contributing
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
See the [OpenCHAMI Contributors Guide](https://github.com/OpenCHAMI/.github/blob/main/CONTRIBUTING.md) for more information.
## License
This project is licensed under the MIT License - see the LICENSE file for details.
## Acknowledgments
- OpenCHAMI community
- OIDC provider maintainers
- Contributors and maintainers of this project