Source Code added

This commit is contained in:
Fr4nz D13trich 2026-02-02 15:06:40 +01:00
parent 800376eafd
commit 9efa9bc6dd
3912 changed files with 754770 additions and 2 deletions

View file

@ -0,0 +1,6 @@
FROM node:24.1.0-alpine3.20@sha256:8fe019e0d57dbdce5f5c27c0b63d2775cf34b00e3755a7dea969802d7e0c2b25
RUN corepack enable
ADD package.json *.ts ./
RUN pnpm install
EXPOSE 2286
CMD ["pnpm", "run", "start"]

View file

@ -0,0 +1,133 @@
import { exportJWK, generateKeyPair } from 'jose';
import Provider from 'oidc-provider';
export enum OAuthClient {
DEFAULT = 'client-default',
RS256_TOKENS = 'client-RS256-tokens',
RS256_PROFILE = 'client-RS256-profile',
}
export enum OAuthUser {
NO_EMAIL = 'no-email',
NO_NAME = 'no-name',
WITH_QUOTA = 'with-quota',
WITH_USERNAME = 'with-username',
WITH_ROLE = 'with-role',
}
const claims = [
{ sub: OAuthUser.NO_EMAIL },
{
sub: OAuthUser.NO_NAME,
email: 'oauth-no-name@immich.app',
email_verified: true,
},
{
sub: OAuthUser.WITH_USERNAME,
email: 'oauth-with-username@immich.app',
email_verified: true,
immich_username: 'user-username',
},
{
sub: OAuthUser.WITH_QUOTA,
email: 'oauth-with-quota@immich.app',
email_verified: true,
preferred_username: 'user-quota',
immich_quota: 25,
},
{
sub: OAuthUser.WITH_ROLE,
email: 'oauth-with-role@immich.app',
email_verified: true,
immich_role: 'admin',
},
];
const withDefaultClaims = (sub: string) => ({
sub,
email: `${sub}@immich.app`,
name: 'OAuth User',
given_name: `OAuth`,
family_name: 'User',
email_verified: true,
});
const getClaims = (sub: string) => claims.find((user) => user.sub === sub) || withDefaultClaims(sub);
const setup = async () => {
const { privateKey, publicKey } = await generateKeyPair('RS256');
const redirectUris = ['http://127.0.0.1:2285/auth/login', 'https://photos.immich.app/oauth/mobile-redirect'];
const port = 2286;
const host = '0.0.0.0';
const oidc = new Provider(`http://${host}:${port}`, {
renderError: async (ctx, out, error) => {
console.error(out);
console.error(error);
ctx.body = 'Internal Server Error';
},
findAccount: (ctx, sub) => ({ accountId: sub, claims: () => getClaims(sub) }),
scopes: ['openid', 'email', 'profile'],
claims: {
openid: ['sub'],
email: ['email', 'email_verified'],
profile: [
'name',
'given_name',
'family_name',
'preferred_username',
'immich_quota',
'immich_username',
'immich_role',
],
},
features: {
jwtUserinfo: {
enabled: true,
},
},
cookies: {
names: {
session: 'oidc.session',
interaction: 'oidc.interaction',
resume: 'oidc.resume',
state: 'oidc.state',
},
},
pkce: {
required: () => false,
},
jwks: { keys: [await exportJWK(privateKey)] },
clients: [
{
client_id: OAuthClient.DEFAULT,
client_secret: OAuthClient.DEFAULT,
redirect_uris: redirectUris,
grant_types: ['authorization_code'],
response_types: ['code'],
},
{
client_id: OAuthClient.RS256_TOKENS,
client_secret: OAuthClient.RS256_TOKENS,
redirect_uris: redirectUris,
grant_types: ['authorization_code'],
id_token_signed_response_alg: 'RS256',
jwks: { keys: [await exportJWK(publicKey)] },
},
{
client_id: OAuthClient.RS256_PROFILE,
client_secret: OAuthClient.RS256_PROFILE,
redirect_uris: redirectUris,
grant_types: ['authorization_code'],
userinfo_signed_response_alg: 'RS256',
jwks: { keys: [await exportJWK(publicKey)] },
},
],
});
const onStart = () => console.log(`[e2e-auth-server] http://${host}:${port}/.well-known/openid-configuration`);
const app = oidc.listen(port, host, onStart);
return () => app.close();
};
export default setup;

View file

@ -0,0 +1,15 @@
{
"name": "@immich/e2e-auth-server",
"version": "0.1.0",
"type": "module",
"main": "auth-server.ts",
"scripts": {
"start": "tsx startup.ts"
},
"devDependencies": {
"jose": "^5.6.3",
"@types/oidc-provider": "^9.0.0",
"oidc-provider": "^9.0.0",
"tsx": "^4.20.6"
}
}

View file

@ -0,0 +1,8 @@
import setup from './auth-server'
const teardown = await setup()
process.on('exit', () => {
teardown()
console.log('[e2e-auth-server] stopped')
process.exit(0)
})