Getting Started
Install, configure and set up ErtisAuth, and get your first token.
This guide takes you from an empty machine to a running ErtisAuth instance with a membership, an administrator and a first token. It takes about ten minutes.
1. Requirements#
- .NET 10 SDK (to build from source), or Docker
- MongoDB 7.0 or later. A standalone server is enough; a replica set is not required.
2. Run ErtisAuth#
From source#
git clone https://github.com/ertugrulozcan/ErtisAuth.git
cd ErtisAuth
export Database__ConnectionString="mongodb://localhost:27017"
dotnet run --project src/ErtisAuth.WebAPIIn the development environment the API listens on http://localhost:9716, and the interactive API reference is at http://localhost:9716/docs.
With Docker Compose#
The repository contains a docker-compose.yml that starts ErtisAuth together with a MongoDB:
git clone https://github.com/ertugrulozcan/ErtisAuth.git
cd ErtisAuth
docker compose up -d --buildThe API listens on http://localhost:9716 and the API reference is at http://localhost:9716/docs. The MongoDB data is kept in the mongo-data volume.
With Docker#
Build the image and run it with a MongoDB of your own:
docker build -t ertisauth:latest .
docker run -p 9716:8080 \
-e Database__ConnectionString="mongodb://<host>:27017" \
ertisauth:latestThe container listens on port 8080 and runs as the non-root app user of the .NET images. It is based on the Debian image of ASP.NET Core, which includes ICU and the time zone database, so culture and time zone handling work as on a development machine.
ErtisAuth stores its data in the database named by Database:DefaultAuthDatabase (auth by default). See Configuration for all settings.
On startup ErtisAuth creates the indexes it needs. Check that it is up:
curl http://localhost:9716/healthcheck{
"status": "Unhealthy",
"message": "ErtisAuth has not been set up yet"
}Unhealthy with this message is expected at this point: the server is running, but it has no membership yet.
3. Set up the installation#
A fresh installation has no users, so nobody can sign in to create the first ones. The setup endpoint solves this: it creates the first resources in one call, and it is authorized by a token that you put into the database yourself. Having write access to the database proves that you are the operator of the installation.
3.1 Insert a setup token#
Generate a random token of at least 32 characters:
openssl rand -hex 32Insert it into the setup collection of the ErtisAuth database (with mongosh):
use auth
db.setup.insertOne({ token: "<setup_token>" })With Docker Compose, run it in the MongoDB container:
docker compose exec mongo mongosh auth --eval 'db.setup.insertOne({ token: "<setup_token>" })'3.2 Call the setup endpoint#
curl -X POST http://localhost:9716/setup \
-H 'X-Setup-Token: <setup_token>' \
-H 'Content-Type: application/json' \
-d '{
"membership": {
"name": "My Company",
"slug": "my-company",
"expires_in": 3600,
"refresh_token_expires_in": 86400,
"hash_algorithm": "ARGON2ID",
"encoding": "UTF-8"
},
"user": {
"username": "admin",
"firstname": "Ada",
"lastname": "Lovelace",
"email_address": "admin@example.com",
"password": "<a strong password>",
"user_type": "Employee"
},
"application": {
"name": "Backend",
"role": "admin"
}
}'| Field | Required | Description |
|---|---|---|
membership.name | yes | Display name of the membership. |
membership.slug | no | URL-friendly name; derived from the name when omitted. |
membership.expires_in | yes | Access token lifetime in seconds. |
membership.refresh_token_expires_in | yes | Refresh token lifetime in seconds. |
membership.hash_algorithm | yes | Password hash algorithm. ARGON2ID is recommended (see Memberships). |
membership.encoding | no | Text encoding used for hashing and signing (UTF-8 by default). |
membership.secret_key | no | The key tokens are signed with, at least 32 bytes. A random key is generated when omitted. |
user.* | yes | The administrator user. firstname, username, email_address and password (at least 6 characters) are required. |
user.user_type | no | Name of the user type created for the administrator (User by default). |
application | no | An application for machine-to-machine access, typically with the admin role. |
The setup creates, in this order:
- the membership,
- the
adminrole, which has every permission on every ErtisAuth resource, - a user type inheriting from the built-in
base-usertype, - the administrator user, already active, with the
adminrole, - the application, if requested.
If any step fails, the resources created before it are removed, so a failed setup can simply be retried.
3.3 Keep the response#
{
"membership": {
"_id": "66f1c0d2a4b5c6d7e8f90123",
"name": "My Company",
"slug": "my-company",
"expires_in": 3600,
"refresh_token_expires_in": 86400,
"secret_key": "…",
"hash_algorithm": "ARGON2ID",
"encoding": "UTF-8",
"…": "…"
},
"user": { "_id": "66f1c0d2a4b5c6d7e8f90124", "username": "admin", "role": "admin", "…": "…" },
"role": { "_id": "66f1c0d2a4b5c6d7e8f90125", "name": "Administrator", "slug": "admin", "permissions": [ "*.memberships.create.*", "…" ] },
"application": {
"_id": "66f1c0d2a4b5c6d7e8f90126",
"name": "Backend",
"slug": "backend",
"role": "admin",
"secret": "<application_secret>"
}
}Write down:
membership._id: you will send it with every sign-in request.application.secret: it is returned only once. ErtisAuth stores only its hash; if you lose it, rotate it.
When the setup succeeds, the setup collection is dropped and the endpoint is closed for good: further calls answer 409 AlreadySetUp. The health check now answers Healthy.
4. Sign in#
curl -X POST http://localhost:9716/generate-token \
-H 'X-Ertis-Alias: <membership_id>' \
-H 'Content-Type: application/json' \
-d '{ "username": "admin", "password": "<password>" }'{
"token_type": "Bearer",
"access_token": "eyJhbGciOiJIUzI1NiIs…",
"expires_in": 3600,
"refresh_token": "eyJhbGciOiJIUzI1NiIs…",
"refresh_token_expires_in": 86400,
"created_at": "2026-01-01T12:00:00Z"
}username also accepts the email address.
5. Call the API#
curl http://localhost:9716/me -H 'Authorization: Bearer <access_token>'curl 'http://localhost:9716/memberships/<membership_id>/users?limit=10&with_count=true' \
-H 'Authorization: Bearer <access_token>'The application can call the same endpoints with a Basic token made of its id and secret:
curl 'http://localhost:9716/memberships/<membership_id>/users' \
-H 'Authorization: Basic <application_id>:<application_secret>'Next steps#
- Design your user model with User Types.
- Create roles for your users in Roles and learn the permission model.
- Configure activation and password reset mails with Mail Hooks and Account Recovery.
- Protect your own services with the .NET SDK.
Found a mistake in the docs? Open an issue