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
10 changes: 6 additions & 4 deletions .deepsource.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
version = 1

test_patterns = ["**/*.test.ts"]

[[analyzers]]
name = "shell"

[[analyzers]]
name = "javascript"

[analyzers.meta]
environment = ["nodejs"]
[analyzers.meta]
environment = ["nodejs"]

[[analyzers]]
name = "docker"

[analyzers.meta]
dockerfile_paths = ["Dockerfile"]
[analyzers.meta]
dockerfile_paths = ["Dockerfile"]
13 changes: 2 additions & 11 deletions .github/config.workflow.toml
Original file line number Diff line number Diff line change
Expand Up @@ -453,17 +453,8 @@ log_level = "info" # For console output
# log_level = "info"

[authentication]
# If enabled, Versia will require users to log in with an OpenID provider
forced_openid = false

# Allow registration with OpenID providers
# If signups.registration is false, it will only be possible to register with OpenID
openid_registration = true

[authentication.keys]
# Run Versia Server with those values missing to generate a new key
public = "MCowBQYDK2VwAyEAfyZx8r98gVHtdH5EF1NYrBeChOXkt50mqiwKO2TX0f8="
private = "MC4CAQAwBQYDK2VwBCIEILDi1g7+bwNjBBvL4CRWHZpCFBR2m2OPCot62Wr+TCbq"
# Run Versia Server with this value missing to generate a new key
key = "ZWcwanRaQAqY3ChUro/Jey9XGQjzsxEed5iqTp4yFr8W6vEnXdz91F/Pu/uf7HBMbNeIK7V6aHsM0lq9onrO8Q=="

# The provider MUST support OpenID Connect with .well-known discovery
# Most notably, GitHub does not support this
Expand Down
14 changes: 6 additions & 8 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 15 additions & 4 deletions cli/user/token.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Token } from "@versia-server/kit/db";
import { Client, Token } from "@versia-server/kit/db";
import { randomUUIDv7 } from "bun";
import chalk from "chalk";
// @ts-expect-error - Root import is required or the Clec type definitions won't work
Expand All @@ -22,13 +22,24 @@ export const generateTokenCommand = defineCommand(
throw new Error(`User ${chalk.gray(username)} not found.`);
}

const application = await Client.insert({
id:
user.id +
Buffer.from(
crypto.getRandomValues(new Uint8Array(32)),
).toString("base64"),
name: "Versia",
redirectUris: [],
scopes: ["openid", "profile", "email"],
secret: "",
});

const token = await Token.insert({
id: randomUUIDv7(),
accessToken: randomString(64, "base64url"),
code: null,
scope: "read write follow",
tokenType: "Bearer",
scopes: ["read", "write", "follow"],
userId: user.id,
clientId: application.id,
});

console.info(
Expand Down
13 changes: 2 additions & 11 deletions config/config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -459,17 +459,8 @@ log_level = "info" # For console output
# log_level = "info"

[authentication]
# If enabled, Versia will require users to log in with an OpenID provider
forced_openid = false

# Allow registration with OpenID providers
# If signups.registration is false, it will only be possible to register with OpenID
openid_registration = true

# [authentication.keys]
# Run Versia Server with those values missing to generate a new key
# public = ""
# private = ""
# Run Versia Server with this value missing to generate a new key
# key = ""

# The provider MUST support OpenID Connect with .well-known discovery
# Most notably, GitHub does not support this
Expand Down
56 changes: 2 additions & 54 deletions docs/frontend/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Multiple API routes are exposed for authentication, to be used by frontend developers.

> [!INFO]
>
>
> These are different from the Client API routes, which are used by clients to interact with the Mastodon API.

A frontend is a web application that is designed to be the primary user interface for an instance. It is used also used by clients to perform authentication.
Expand Down Expand Up @@ -48,58 +48,6 @@ Frontend configuration.
}
```

## Sign In

```http
POST /api/auth/login
```

Allows users to sign in to the instance. This is the first step in the authentication process.

- **Returns**: `302 Found` with a `Location` header to redirect the user to the next step, as well as a `Set-Cookie` header with the session JWT.
- **Authentication**: Not required
- **Permissions**: None
- **Version History**:
- `0.7.0`: First documented.

### Request

- `identifier` (string, required): The username or email of the user. Case-insensitive.
- `password` (string, required): The password of the user.

#### Query Parameters

- `client_id` (string, required): Client ID of the [application](https://docs.joinmastodon.org/entities/Application/) that is making the request.
- `redirect_uri` (string, required): Redirect URI of the [application](https://docs.joinmastodon.org/entities/Application/) that is making the request. Must match the saved value.
- `response_type` (string, required): Must be `code`.
- `scope` (string, required): OAuth2 scopes. Must match the value indicated in the [application](https://docs.joinmastodon.org/entities/Application/).

#### Example

```http
POST /api/auth/login?client_id=123&redirect_uri=https%3A%2F%2Fexample.com%2Fauth&response_type=code&scope=read%20write
Content-Type: application/json

{
"identifier": "bobjones@gmail.com",
"password": "hunter2"
}
```

### Response

#### `302 Found`

Redirects the user to the consent page with some query parameters. The frontend should redirect the user to this URL.

This response also has a `Set-Cookie` header with a [JSON Web Token](https://jwt.io/) that contains the user's session information. This JWT is signed with the instance's secret key, and must be included in all subsequent authentication requests.

```http
HTTP/2.0 302 Found
Location: /oauth/consent?client_id=123&redirect_uri=https%3A%2F%2Fexample.com%2Fauth&response_type=code&scope=read%20write
Set-Cookie: jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=3600
```

## SSO Sign In

```http
Expand Down Expand Up @@ -136,4 +84,4 @@ Redirects the user to the OpenID Connect provider's login page.
```http
HTTP/2.0 302 Found
Location: https://accounts.google.com/o/oauth2/auth?client_id=123&redirect_uri=https%3A%2F%2Fexample.com%2Fauth&response_type=code&scope=openid%20email&state=123
```
```
2 changes: 1 addition & 1 deletion docs/frontend/routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ GET /oauth/authorize

This route should display a login form for the user to enter their username and password, as well as a list of OpenID providers to use if available.

The form should submit to [`POST /api/auth/login`](./auth.md#sign-in), or to the OpenID Connect flow.
The form should submit to the OpenID Connect flow.

Configurable in the Versia Server configuration at `frontend.routes.login`.

Expand Down
4 changes: 2 additions & 2 deletions drizzle.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import type { Config } from "drizzle-kit";
*/
export default {
dialect: "postgresql",
out: "./drizzle/migrations",
schema: "./drizzle/schema.ts",
out: "./packages/kit/tables/migrations",
schema: "./packages/kit/tables/schema.ts",
dbCredentials: {
/* host: "localhost",
port: 40000,
Expand Down
22 changes: 22 additions & 0 deletions nix/module.nix
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,28 @@ in {
StandardError = "journal";
SyslogIdentifier = "${name}";

# Hardening
CapabilityBoundingSet = [""];
LockPersonality = true;
PrivateMounts = true;
PrivateTmp = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
RemoveIPC = true;
NoNewPrivileges = true;

Environment = [
"CONFIG_LOCATION=${configFile}"
];
Expand Down
2 changes: 1 addition & 1 deletion nix/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ in
# Required else we get errors that our fixed-output derivation references store paths
dontFixup = true;

outputHash = "sha256-aG54v3luuJTmb/eonoILv3KBKW6mulk3xOpxLA6V5L8=";
outputHash = "sha256-geahFpkyWgHXKMxLp46AJW3TVWFm6jM4QZO0Z10mBWY=";
outputHashAlgo = "sha256";
outputHashMode = "recursive";
};
Expand Down
5 changes: 1 addition & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@logtape/otel": "^1.0.0",
"@scalar/hono-api-reference": "^0.9.7",
"@sentry/bun": "^9.35.0",
"openid-client": "^6.6.3",
"altcha-lib": "^1.3.0",
"blurhash": "^2.0.5",
"bullmq": "^5.56.1",
Expand All @@ -73,7 +74,6 @@
"ioredis": "^5.6.1",
"ip-matching": "^2.1.2",
"iso-639-1": "^3.1.5",
"jose": "^6.0.11",
"linkify-html": "^4.3.1",
"linkify-string": "^4.3.1",
"linkifyjs": "^4.3.1",
Expand All @@ -85,7 +85,6 @@
"markdown-it-toc-done-right": "^4.2.0",
"mime-types": "^3.0.1",
"mitata": "^1.0.34",
"oauth4webapi": "^3.5.5",
"ora": "^8.2.0",
"qs": "^6.14.0",
"sharp": "^0.34.2",
Expand Down Expand Up @@ -191,7 +190,6 @@
"ioredis": "catalog:",
"ip-matching": "catalog:",
"iso-639-1": "catalog:",
"jose": "catalog:",
"linkify-html": "catalog:",
"linkify-string": "catalog:",
"linkifyjs": "catalog:",
Expand All @@ -203,7 +201,6 @@
"markdown-it-toc-done-right": "catalog:",
"mime-types": "catalog:",
"mitata": "catalog:",
"oauth4webapi": "catalog:",
"ora": "catalog:",
"qs": "catalog:",
"sharp": "catalog:",
Expand Down
5 changes: 2 additions & 3 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"@versia-server/logging": "workspace:*",
"@versia/client": "workspace:*",
"@versia/sdk": "workspace:*",
"openid-client": "catalog:",
"youch": "catalog:",
"hono": "catalog:",
"hono-openapi": "catalog:",
Expand All @@ -66,7 +67,6 @@
"unicode-emoji-json": "catalog:",
"sharp": "catalog:",
"iso-639-1": "catalog:",
"jose": "catalog:",
"zod-openapi": "catalog:",
"@scalar/hono-api-reference": "catalog:",
"hono-rate-limiter": "catalog:",
Expand All @@ -75,7 +75,6 @@
"altcha-lib": "catalog:",
"@hono/standard-validator": "catalog:",
"zod-validation-error": "catalog:",
"confbox": "catalog:",
"oauth4webapi": "catalog:"
"confbox": "catalog:"
}
}
Loading
Loading