feat: oauth integration (#2659)

* feat: add Google OAuth login support (#2625)

* 🔧 Add login via google

* 🔧 Update code style and docs

* Add fix for db migrate

* 🔧 Update docker-compose

* 🔧 Fix sqlite"

* 🔧 Update docker-compose

* ⚰️ Remove environments

* 🔧 Fix: remove ensureGoogleIdColumn workaround from sqlite.ts

* 🔧 Remove space

* move oauth section

* add openid client

* wip make oauth more generic

* properly allow multiple providers

* fix type import

* github login flow

* adjust github logo with theme

* move docs to own page

* nullable password, prevent timing attack

this prevents timing attacks by always checking hash even if there is none
prevents using basic auth if 2fa is enabled

* support generic oidc

* add ability to set password for oidc users

this allows oidc users to add password login
cant be removed after

* move password login route

move password login route from /api/session to /api/auth/password
align with oauth

* unique index on oauth

* link/unlink logic

* improve docs

* support allowed domains

* support auto register

* refactoring

* disable pw auth

* move 2fa to its own page

* 2fa for oauth, rework 2fa system

* fix design, fix link

Closes #2650

* add auto launch

* improve docs

* improvements

---------

Co-authored-by: Daniel Molenda <dm@fotc.com>
This commit is contained in:
Bernd Storath
2026-06-12 13:38:32 +02:00
committed by GitHub
co-authored by Daniel Molenda
parent c70ad1d08b
commit ac547bbf7c
44 changed files with 2848 additions and 222 deletions
+6 -3
View File
@@ -47,8 +47,8 @@ type SharedUserType =
export type SharedPublicUser = Pick<
UserType,
'id' | 'username' | 'name' | 'email' | 'totpVerified'
> & { role: BrandedNumber };
'id' | 'username' | 'name' | 'email' | 'totpVerified' | 'oauthProvider'
> & { role: BrandedNumber; hasPassword: boolean };
type PermissionCheck<Key extends keyof Permissions> =
| boolean
@@ -144,7 +144,10 @@ export function hasPermissionsWithData<Resource extends keyof Permissions>(
const isAllowed = hasPermissions(user, resource, action, data);
if (!isAllowed) {
throw new Error('Permission denied');
throw createError({
statusCode: 403,
statusMessage: 'Permission denied',
});
}
return isAllowed;