From 8a5ba389fc856d84b21953a530712f2b599744c5 Mon Sep 17 00:00:00 2001 From: Skye Date: Mon, 24 Jun 2024 16:16:57 +0900 Subject: [PATCH 1/6] add OIDC support --- packages/backend/package.json | 1 + packages/backend/src/config.ts | 23 ++ packages/backend/src/server/ServerModule.ts | 2 + .../src/server/api/ApiServerService.ts | 13 ++ .../backend/src/server/api/OidcApiService.ts | 216 ++++++++++++++++++ packages/frontend/src/components/MkSignin.vue | 44 +++- pnpm-lock.yaml | 34 +++ 7 files changed, 332 insertions(+), 1 deletion(-) create mode 100644 packages/backend/src/server/api/OidcApiService.ts diff --git a/packages/backend/package.json b/packages/backend/package.json index bfa32c8612..f75a964ac6 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -138,6 +138,7 @@ "ip-cidr": "4.0.2", "ipaddr.js": "2.2.0", "is-svg": "6.1.0", + "jose": "^6.1.3", "js-yaml": "4.1.0", "json5": "2.2.3", "jsonld": "8.3.3", diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index be3892e942..6c2967706c 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -161,6 +161,17 @@ type Source = { customHtml?: { head?: string; } + + oidc: { + name: string; + authEndpoint: string; + tokenEndpoint: string; + clientId: string; + clientSecret: string; + scope: string[]; + autoRegister: boolean; + usernameClaim: string; + } | undefined; }; export type PrivateNetworkSource = string | { network?: string, ports?: number[] }; @@ -339,6 +350,17 @@ export type Config = { } | undefined; pidFile: string; + + oidc: { + name: string; + authEndpoint: string; + tokenEndpoint: string; + clientId: string; + clientSecret: string; + scope: string[]; + autoRegister: boolean; + usernameClaim: string; + } | undefined; filePermissionBits?: string; activityLogging: { @@ -521,6 +543,7 @@ export function loadConfig(loggerService: LoggerService): Config { customHtml: { head: config.customHtml?.head ?? '', }, + oidc: config.oidc, }; } diff --git a/packages/backend/src/server/ServerModule.ts b/packages/backend/src/server/ServerModule.ts index 8ff8da380a..4e0283ddac 100644 --- a/packages/backend/src/server/ServerModule.ts +++ b/packages/backend/src/server/ServerModule.ts @@ -64,6 +64,7 @@ import { ChatRoomChannelService } from './api/stream/channels/chat-room.js'; import { ReversiChannelService } from './api/stream/channels/reversi.js'; import { ReversiGameChannelService } from './api/stream/channels/reversi-game.js'; import { SigninWithPasskeyApiService } from './api/SigninWithPasskeyApiService.js'; +import { OidcApiService } from './api/OidcApiService.js'; @Module({ imports: [ @@ -128,6 +129,7 @@ import { SigninWithPasskeyApiService } from './api/SigninWithPasskeyApiService.j ApiStatusMastodon, ApiTimelineMastodon, ServerUtilityService, + OidcApiService, ], exports: [ ServerService, diff --git a/packages/backend/src/server/api/ApiServerService.ts b/packages/backend/src/server/api/ApiServerService.ts index 8900048de0..daed496936 100644 --- a/packages/backend/src/server/api/ApiServerService.ts +++ b/packages/backend/src/server/api/ApiServerService.ts @@ -19,6 +19,7 @@ import { SignupApiService } from './SignupApiService.js'; import { SigninApiService } from './SigninApiService.js'; import { SigninWithPasskeyApiService } from './SigninWithPasskeyApiService.js'; import { CacheService } from '@/core/CacheService.js'; +import { OidcApiService } from './OidcApiService.js'; import type { FastifyInstance, FastifyPluginOptions } from 'fastify'; @Injectable() @@ -43,7 +44,11 @@ export class ApiServerService { private signupApiService: SignupApiService, private signinApiService: SigninApiService, private signinWithPasskeyApiService: SigninWithPasskeyApiService, +<<<<<<< HEAD private cacheService: CacheService, +======= + private oidcApiService: OidcApiService, +>>>>>>> cd7330e1a2 (add OIDC support) ) { //this.createServer = this.createServer.bind(this); } @@ -210,6 +215,14 @@ export class ApiServerService { } }); + fastify.get('/oidc/meta', (request, reply) => this.oidcApiService.meta(request, reply)); + fastify.get<{ + Querystring: { + code?: string; + error?: string; + }; + }>('/oidc/callback', (request, reply) => this.oidcApiService.callback(request, reply)); + // Make sure any unknown path under /api returns HTTP 404 Not Found, // because otherwise ClientServerService will return the base client HTML // page with HTTP 200. diff --git a/packages/backend/src/server/api/OidcApiService.ts b/packages/backend/src/server/api/OidcApiService.ts new file mode 100644 index 0000000000..d5229f69d8 --- /dev/null +++ b/packages/backend/src/server/api/OidcApiService.ts @@ -0,0 +1,216 @@ +/* + * SPDX-FileCopyrightText: skye and other Sharkey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import * as jose from 'jose'; +import { IsNull } from 'typeorm'; +import { DI } from '@/di-symbols.js'; +import type { + UsedUsernamesRepository, + UsersRepository, +} from '@/models/_.js'; +import type { Config } from '@/config.js'; +import { getIpHash } from '@/misc/get-ip-hash.js'; +import type { MiLocalUser } from '@/models/User.js'; +import { bindThis } from '@/decorators.js'; +import { MetaService } from '@/core/MetaService.js'; +import { FastifyReplyError } from '@/misc/fastify-reply-error.js'; +import { SignupService } from '@/core/SignupService.js'; +import { HttpRequestService } from '@/core/HttpRequestService.js'; +import { RateLimiterService } from './RateLimiterService.js'; +import { SigninService } from './SigninService.js'; +import type { FastifyReply, FastifyRequest } from 'fastify'; + +@Injectable() +export class OidcApiService { + constructor( + @Inject(DI.config) + private config: Config, + + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + + @Inject(DI.usedUsernamesRepository) + private usedUsernamesRepository: UsedUsernamesRepository, + + private rateLimiterService: RateLimiterService, + private signinService: SigninService, + private signupService: SignupService, + private metaService: MetaService, + private httpRequestService: HttpRequestService, + ) { + } + + @bindThis + public async meta( + _request: FastifyRequest, + _reply: FastifyReply, + ) { + if (this.config.oidc === undefined) { + return { + enabled: false, + }; + } + const url = new URL(this.config.oidc.authEndpoint); + url.searchParams.append('client_id', this.config.oidc.clientId); + url.searchParams.append('redirect_uri', `${this.config.apiUrl}/oidc/callback`); + url.searchParams.append('response_type', 'code'); + url.searchParams.append('scope', this.config.oidc.scope.join(' ')); + return { + enabled: true, + name: this.config.oidc.name, + url, + }; + } + + @bindThis + public async callback( + request: FastifyRequest<{ + Querystring: { + code?: string; + error?: string; + }; + }>, + reply: FastifyReply, + ) { + reply.header('Access-Control-Allow-Origin', this.config.url); + reply.header('Access-Control-Allow-Credentials', 'true'); + + const instance = await this.metaService.fetch(true); + + const query = request.query; + + function error(status: number, error: { id: string }) { + reply.code(status); + return { error }; + } + + if (query.error !== undefined) { + return error(403, { + id: 'bf721f0c-ed11-4c94-bc0a-84aaf8b7431a', + }); + } + + if (query.code === undefined) { + return error(400, { + id: '797c0ae2-2eb9-402d-a2d6-090b5f3f3686', + }); + } + + if (this.config.oidc === undefined) { + return error(403, { + id: '726c5012-eec4-49c8-b613-74fb23c2bdce', + }); + } + + try { + // not more than 1 attempt per second and not more than 10 attempts per hour + await this.rateLimiterService.limit({ key: 'signin', duration: 60 * 60 * 1000, max: 10, minInterval: 1000 }, getIpHash(request.ip)); + } catch (err) { + reply.code(429); + return { + error: { + message: 'Too many failed attempts to sign in. Try again later.', + code: 'TOO_MANY_AUTHENTICATION_FAILURES', + id: '22d05606-fbcf-421a-a2db-b32610dcfd1b', + }, + }; + } + + const tokenResponse: { id_token: string } | { error: string } = await (await this.httpRequestService.send(this.config.oidc.tokenEndpoint, { + body: new URLSearchParams({ + code: query.code, + client_id: this.config.oidc.clientId, + client_secret: this.config.oidc.clientSecret, + grant_type: 'authorization_code', + redirect_uri: `${this.config.apiUrl}/oidc/callback`, + }).toString(), + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + })).json() as { id_token: string } | { error: string }; + + if ('error' in tokenResponse) { + return error(403, { + id: 'afae6924-7744-4efb-aed1-cfda2ddd8c43', + }); + } + + const token = jose.decodeJwt>(tokenResponse.id_token); + + const username = token[this.config.oidc.usernameClaim]; + + if (username === undefined) { + return error(400, { + id: '3b02c880-cd46-4886-9cda-325529340226', + }); + } + + // Fetch user + let user = await this.usersRepository.findOneBy({ + usernameLower: username.toLowerCase(), + host: IsNull(), + }) as MiLocalUser; + + if (user == null) { + if (this.config.oidc.autoRegister) { + try { + if (await this.usedUsernamesRepository.exists({ where: { username: username.toLowerCase() } })) { + throw new FastifyReplyError(400, 'USED_USERNAME'); + } + const { account } = await this.signupService.signup({ + username, + }); + user = account as MiLocalUser; + } catch (err) { + throw new FastifyReplyError(400, typeof err === 'string' ? err : (err as Error).toString()); + } + } else { + return error(404, { + id: '6cc579cc-885d-43d8-95c2-b8c7fc963280', + }); + } + } + + if (user.isSuspended) { + return error(403, { + id: 'e03a5f46-d309-4865-9b69-56282d94e1eb', + }); + } + + if (!user.approved && instance.approvalRequiredForSignup) { + reply.code(403); + return { + error: { + message: 'The account has not been approved by an admin yet. Try again later.', + code: 'NOT_APPROVED', + id: '22d05606-fbcf-421a-a2db-b32241faft1b', + }, + }; + } + + if (!instance.approvalRequiredForSignup && !user.approved) this.usersRepository.update(user.id, { approved: true }); + + const resp = this.signinService.signin(request, reply, user); + reply.type('text/html'); + return ` + + + Please wait... + + + Please wait... + + + `; + } +} diff --git a/packages/frontend/src/components/MkSignin.vue b/packages/frontend/src/components/MkSignin.vue index 68151fdc78..31bd0c1ced 100644 --- a/packages/frontend/src/components/MkSignin.vue +++ b/packages/frontend/src/components/MkSignin.vue @@ -60,6 +60,7 @@ SPDX-License-Identifier: AGPL-3.0-only
+ Sign in with {{ oidcName }} @@ -70,7 +71,7 @@ import { supported as webAuthnSupported, parseRequestOptionsFromJSON } from '@gi import type { AuthenticationPublicKeyCredential } from '@github/webauthn-json/browser-ponyfill'; import type { OpenOnRemoteOptions } from '@/utility/please-login.js'; import type { PwResponse } from '@/components/MkSignin.password.vue'; -import { misskeyApi } from '@/utility/misskey-api.js'; +import { misskeyApi, misskeyApiGet } from '@/utility/misskey-api.js'; import { showSuspendedDialog } from '@/utility/show-suspended-dialog.js'; import { i18n } from '@/i18n.js'; import { showSystemAccountDialog } from '@/utility/show-system-account-dialog.js'; @@ -105,6 +106,47 @@ const needCaptcha = ref(false); const userInfo = ref(null); const password = ref(''); +const oidcName = ref('OpenID Connect'); +const oidcLogin = ref(false); + +let oidcUrl: string | undefined; + +misskeyApiGet('oidc/meta').then((resp: { + enabled: false +} | { + enabled: true, + name: string, + url: string, +}) => { + oidcLogin.value = resp.enabled; + if (resp.enabled) { + oidcName.value = resp.name; + oidcUrl = resp.url; + } +}); + +const vOidc = { + mounted: (el) => { + window.addEventListener('message', oidcEvent); + }, + unmounted: (el) => { + window.removeEventListener('message', oidcEvent); + }, +}; + +async function oidcPopup() { + window.open(oidcUrl, undefined, 'popup'); +} + +function oidcEvent(event) { + const data = event.data; + if (typeof data === 'object' && 'type' in data && data.type === 'login-ok') { + const res = (data as { type: 'login-ok', data: unknown }).data; + emit('login', res); + return onLoginSucceeded(res); + } +} + //#region Passkey Passwordless const credentialRequest = shallowRef(null); const passkeyContext = ref(''); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f42a30bf6c..73a98da035 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -258,6 +258,9 @@ importers: is-svg: specifier: 6.1.0 version: 6.1.0 + jose: + specifier: ^6.1.3 + version: 6.1.3 js-yaml: specifier: 4.1.0 version: 4.1.0 @@ -4199,9 +4202,17 @@ packages: resolution: {integrity: sha1-50hzNdDZoxqKTCy+G9PdW3VDVso=, tarball: https://activitypub.software/api/v4/projects/229/packages/npm/@transfem-org/cli-highlight/-/@transfem-org/cli-highlight-2.1.13.tgz} engines: {node: ^22.0.0} +<<<<<<< HEAD '@transfem-org/sfm-js@0.26.1': resolution: {integrity: sha1-42SS8z0rQLz7gjyg5fbNeUIHHVk=, tarball: https://activitypub.software/api/v4/projects/2/packages/npm/@transfem-org/sfm-js/-/@transfem-org/sfm-js-0.26.1.tgz} engines: {node: ^22.0.0} +======= + '@transfem-org/sfm-js@0.24.6': + resolution: {integrity: sha1-7t+TkCd3PZk+RbbrGbZ/iMs2y7o=, tarball: https://activitypub.software/api/v4/projects/2/packages/npm/@transfem-org/sfm-js/-/@transfem-org/sfm-js-0.24.6.tgz} + + '@transfem-org/summaly@5.2.1': + resolution: {integrity: sha1-bSQjLRWt0g/UkhYnGjT5/UPig20=, tarball: https://activitypub.software/api/v4/projects/217/packages/npm/@transfem-org/summaly/-/@transfem-org/summaly-5.2.1.tgz} +>>>>>>> cd7330e1a2 (add OIDC support) '@transfem-org/summaly@5.2.3': resolution: {integrity: sha1-ru+BBpNlr8yJwI+KWp5I5ZHvnTM=, tarball: https://activitypub.software/api/v4/projects/217/packages/npm/@transfem-org/summaly/-/@transfem-org/summaly-5.2.3.tgz} @@ -7524,6 +7535,7 @@ packages: joi@17.13.3: resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} +<<<<<<< HEAD joi@18.0.1: resolution: {integrity: sha512-IiQpRyypSnLisQf3PwuN2eIHAsAIGZIrLZkd4zdvIar2bDyhM91ubRjy8a3eYablXsh9BeI/c7dmPYHca5qtoA==} engines: {node: '>= 20'} @@ -7531,6 +7543,14 @@ packages: js-beautify@1.15.4: resolution: {integrity: sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==} engines: {node: '>=14'} +======= + jose@5.10.0: + resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} + + js-beautify@1.14.9: + resolution: {integrity: sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==} + engines: {node: '>=12'} +>>>>>>> cd7330e1a2 (add OIDC support) hasBin: true js-cookie@3.0.5: @@ -14375,7 +14395,15 @@ snapshots: '@transfem-org/summaly@5.2.3': dependencies: +<<<<<<< HEAD cheerio: 1.1.2 +======= + '@twemoji/parser': 15.0.0 + + '@transfem-org/summaly@5.2.1': + dependencies: + cheerio: 1.0.0 +>>>>>>> cd7330e1a2 (add OIDC support) escape-regexp: 0.0.1 got: 14.4.9 html-entities: 2.6.0 @@ -18515,6 +18543,7 @@ snapshots: '@sideway/formula': 3.0.1 '@sideway/pinpoint': 2.0.0 +<<<<<<< HEAD joi@18.0.1: dependencies: '@hapi/address': 5.1.1 @@ -18526,6 +18555,11 @@ snapshots: '@standard-schema/spec': 1.0.0 js-beautify@1.15.4: +======= + jose@5.10.0: {} + + js-beautify@1.14.9: +>>>>>>> cd7330e1a2 (add OIDC support) dependencies: config-chain: 1.1.13 editorconfig: 1.0.4 From 9d2df321da662f2d4452a0337dab6211a28cd1c4 Mon Sep 17 00:00:00 2001 From: illuc Date: Sun, 28 Dec 2025 01:42:57 +0200 Subject: [PATCH 2/6] Added nix flake --- flake.lock | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000..f8964420ec --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1766651565, + "narHash": "sha256-QEhk0eXgyIqTpJ/ehZKg9IKS7EtlWxF3N7DXy42zPfU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3e2499d5539c16d0d173ba53552a4ff8547f4539", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000000..80eefa3f6f --- /dev/null +++ b/flake.nix @@ -0,0 +1,52 @@ +{ + description = "Development environment for Sharkey"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { + devShells.default = pkgs.mkShell { + buildInputs = with pkgs; [ + nodejs + pnpm_9 + + pkg-config + python3 + makeWrapper + + cairo + pango + pixman + vips + ffmpeg-headless + jemalloc + + ]; + + shellHook = '' + export NODE_ENV=development + export npm_config_nodedir=${pkgs.nodejs} + ''; + + LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [ + pkgs.ffmpeg-headless + pkgs.jemalloc + pkgs.stdenv.cc.cc + pkgs.cairo + pkgs.pango + pkgs.pixman + pkgs.vips + ]; + + PKG_CONFIG_PATH = "${pkgs.cairo}/lib/pkgconfig:${pkgs.pango}/lib/pkgconfig:${pkgs.pixman}/lib/pkgconfig:${pkgs.vips}/lib/pkgconfig"; + }; + } + ); +} From 932b0c41baeb37b35705a0175f399622d5dd9632 Mon Sep 17 00:00:00 2001 From: illuc Date: Sun, 28 Dec 2025 01:57:54 +0200 Subject: [PATCH 3/6] tweaking --- .../backend/src/server/api/ApiServerService.ts | 3 --- pnpm-lock.yaml | 18 ++---------------- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/packages/backend/src/server/api/ApiServerService.ts b/packages/backend/src/server/api/ApiServerService.ts index daed496936..c717716342 100644 --- a/packages/backend/src/server/api/ApiServerService.ts +++ b/packages/backend/src/server/api/ApiServerService.ts @@ -44,11 +44,8 @@ export class ApiServerService { private signupApiService: SignupApiService, private signinApiService: SigninApiService, private signinWithPasskeyApiService: SigninWithPasskeyApiService, -<<<<<<< HEAD private cacheService: CacheService, -======= private oidcApiService: OidcApiService, ->>>>>>> cd7330e1a2 (add OIDC support) ) { //this.createServer = this.createServer.bind(this); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 73a98da035..d9ed017588 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4202,17 +4202,9 @@ packages: resolution: {integrity: sha1-50hzNdDZoxqKTCy+G9PdW3VDVso=, tarball: https://activitypub.software/api/v4/projects/229/packages/npm/@transfem-org/cli-highlight/-/@transfem-org/cli-highlight-2.1.13.tgz} engines: {node: ^22.0.0} -<<<<<<< HEAD '@transfem-org/sfm-js@0.26.1': resolution: {integrity: sha1-42SS8z0rQLz7gjyg5fbNeUIHHVk=, tarball: https://activitypub.software/api/v4/projects/2/packages/npm/@transfem-org/sfm-js/-/@transfem-org/sfm-js-0.26.1.tgz} engines: {node: ^22.0.0} -======= - '@transfem-org/sfm-js@0.24.6': - resolution: {integrity: sha1-7t+TkCd3PZk+RbbrGbZ/iMs2y7o=, tarball: https://activitypub.software/api/v4/projects/2/packages/npm/@transfem-org/sfm-js/-/@transfem-org/sfm-js-0.24.6.tgz} - - '@transfem-org/summaly@5.2.1': - resolution: {integrity: sha1-bSQjLRWt0g/UkhYnGjT5/UPig20=, tarball: https://activitypub.software/api/v4/projects/217/packages/npm/@transfem-org/summaly/-/@transfem-org/summaly-5.2.1.tgz} ->>>>>>> cd7330e1a2 (add OIDC support) '@transfem-org/summaly@5.2.3': resolution: {integrity: sha1-ru+BBpNlr8yJwI+KWp5I5ZHvnTM=, tarball: https://activitypub.software/api/v4/projects/217/packages/npm/@transfem-org/summaly/-/@transfem-org/summaly-5.2.3.tgz} @@ -7535,7 +7527,6 @@ packages: joi@17.13.3: resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} -<<<<<<< HEAD joi@18.0.1: resolution: {integrity: sha512-IiQpRyypSnLisQf3PwuN2eIHAsAIGZIrLZkd4zdvIar2bDyhM91ubRjy8a3eYablXsh9BeI/c7dmPYHca5qtoA==} engines: {node: '>= 20'} @@ -7543,16 +7534,11 @@ packages: js-beautify@1.15.4: resolution: {integrity: sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==} engines: {node: '>=14'} -======= + hasBin: true + jose@5.10.0: resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} - js-beautify@1.14.9: - resolution: {integrity: sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==} - engines: {node: '>=12'} ->>>>>>> cd7330e1a2 (add OIDC support) - hasBin: true - js-cookie@3.0.5: resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} engines: {node: '>=14'} From 882f88791e15e9b99f7e7ecf3c203769011d679b Mon Sep 17 00:00:00 2001 From: illuc Date: Sun, 28 Dec 2025 02:19:27 +0200 Subject: [PATCH 4/6] tweaking2 --- packages/backend/src/server/api/OidcApiService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/OidcApiService.ts b/packages/backend/src/server/api/OidcApiService.ts index d5229f69d8..2374e29a13 100644 --- a/packages/backend/src/server/api/OidcApiService.ts +++ b/packages/backend/src/server/api/OidcApiService.ts @@ -19,7 +19,7 @@ import { MetaService } from '@/core/MetaService.js'; import { FastifyReplyError } from '@/misc/fastify-reply-error.js'; import { SignupService } from '@/core/SignupService.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; -import { RateLimiterService } from './RateLimiterService.js'; +import { SkRateLimiterService } from '@/server/SkRateLimiterService.js'; import { SigninService } from './SigninService.js'; import type { FastifyReply, FastifyRequest } from 'fastify'; From fc8e4be06642ce613e304686e036bf3638db6e8f Mon Sep 17 00:00:00 2001 From: illuc Date: Sun, 28 Dec 2025 02:35:31 +0200 Subject: [PATCH 5/6] schlanguish --- packages/backend/src/server/api/OidcApiService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/OidcApiService.ts b/packages/backend/src/server/api/OidcApiService.ts index 2374e29a13..168efc2956 100644 --- a/packages/backend/src/server/api/OidcApiService.ts +++ b/packages/backend/src/server/api/OidcApiService.ts @@ -35,7 +35,7 @@ export class OidcApiService { @Inject(DI.usedUsernamesRepository) private usedUsernamesRepository: UsedUsernamesRepository, - private rateLimiterService: RateLimiterService, + private rateLimiterService: SkRateLimiterService, private signinService: SigninService, private signupService: SignupService, private metaService: MetaService, From 8acf6867bf73e91474b049f7fe4cd6a1791bebbe Mon Sep 17 00:00:00 2001 From: illuc Date: Sun, 28 Dec 2025 04:25:52 +0200 Subject: [PATCH 6/6] oidc format tweaks --- .../src/components/MkSignin.input.vue | 56 ++++++++++++++++++- packages/frontend/src/components/MkSignin.vue | 49 +++------------- 2 files changed, 64 insertions(+), 41 deletions(-) diff --git a/packages/frontend/src/components/MkSignin.input.vue b/packages/frontend/src/components/MkSignin.input.vue index aacd1eae2a..cafb40224f 100644 --- a/packages/frontend/src/components/MkSignin.input.vue +++ b/packages/frontend/src/components/MkSignin.input.vue @@ -30,6 +30,8 @@ SPDX-License-Identifier: AGPL-3.0-only + +
@@ -48,17 +50,29 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts.signinWithPasskey }} + + +
+

{{ i18n.ts.or }}

+
+
+ + Sign in with {{ oidcName }} + +
+