mirror of
https://github.com/immich-app/immich
synced 2025-11-14 17:36:12 +00:00
refactor(web,server): use feature flags for oauth (#3928)
* refactor: oauth to use feature flags * chore: open api * chore: e2e test for authorize endpoint
This commit is contained in:
parent
c7d53a5006
commit
a26ed3d1a6
26 changed files with 660 additions and 110 deletions
|
|
@ -1,5 +1,12 @@
|
|||
import { SystemConfig, UserEntity } from '@app/infra/entities';
|
||||
import { BadRequestException, Inject, Injectable, Logger, UnauthorizedException } from '@nestjs/common';
|
||||
import {
|
||||
BadRequestException,
|
||||
Inject,
|
||||
Injectable,
|
||||
InternalServerErrorException,
|
||||
Logger,
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import cookieParser from 'cookie';
|
||||
import { IncomingHttpHeaders } from 'http';
|
||||
import { DateTime } from 'luxon';
|
||||
|
|
@ -27,6 +34,7 @@ import {
|
|||
mapAdminSignupResponse,
|
||||
mapLoginResponse,
|
||||
mapUserToken,
|
||||
OAuthAuthorizeResponseDto,
|
||||
OAuthConfigResponseDto,
|
||||
} from './response-dto';
|
||||
import { IUserTokenRepository } from './user-token.repository';
|
||||
|
|
@ -201,6 +209,22 @@ export class AuthService {
|
|||
return { ...response, buttonText, url, autoLaunch };
|
||||
}
|
||||
|
||||
async authorize(dto: OAuthConfigDto): Promise<OAuthAuthorizeResponseDto> {
|
||||
const config = await this.configCore.getConfig();
|
||||
if (!config.oauth.enabled) {
|
||||
throw new BadRequestException('OAuth is not enabled');
|
||||
}
|
||||
|
||||
const client = await this.getOAuthClient(config);
|
||||
const url = await client.authorizationUrl({
|
||||
redirect_uri: this.normalize(config, dto.redirectUri),
|
||||
scope: config.oauth.scope,
|
||||
state: generators.state(),
|
||||
});
|
||||
|
||||
return { url };
|
||||
}
|
||||
|
||||
async callback(
|
||||
dto: OAuthCallbackDto,
|
||||
loginDetails: LoginDetails,
|
||||
|
|
@ -280,8 +304,13 @@ export class AuthService {
|
|||
const redirectUri = this.normalize(config, url.split('?')[0]);
|
||||
const client = await this.getOAuthClient(config);
|
||||
const params = client.callbackParams(url);
|
||||
const tokens = await client.callback(redirectUri, params, { state: params.state });
|
||||
return client.userinfo<OAuthProfile>(tokens.access_token || '');
|
||||
try {
|
||||
const tokens = await client.callback(redirectUri, params, { state: params.state });
|
||||
return client.userinfo<OAuthProfile>(tokens.access_token || '');
|
||||
} catch (error: Error | any) {
|
||||
this.logger.error(`Unable to complete OAuth login: ${error}`, error?.stack);
|
||||
throw new InternalServerErrorException(`Unable to complete OAuth login: ${error}`, { cause: error });
|
||||
}
|
||||
}
|
||||
|
||||
private async getOAuthClient(config: SystemConfig) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsString } from 'class-validator';
|
||||
|
||||
export class OAuthConfigDto {
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
@ApiProperty()
|
||||
redirectUri!: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,3 +5,7 @@ export class OAuthConfigResponseDto {
|
|||
buttonText?: string;
|
||||
autoLaunch?: boolean;
|
||||
}
|
||||
|
||||
export class OAuthAuthorizeResponseDto {
|
||||
url!: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import {
|
|||
AuthUserDto,
|
||||
LoginDetails,
|
||||
LoginResponseDto,
|
||||
OAuthAuthorizeResponseDto,
|
||||
OAuthCallbackDto,
|
||||
OAuthConfigDto,
|
||||
OAuthConfigResponseDto,
|
||||
|
|
@ -31,12 +32,19 @@ export class OAuthController {
|
|||
};
|
||||
}
|
||||
|
||||
/** @deprecated use feature flags and /oauth/authorize */
|
||||
@PublicRoute()
|
||||
@Post('config')
|
||||
generateConfig(@Body() dto: OAuthConfigDto): Promise<OAuthConfigResponseDto> {
|
||||
return this.service.generateConfig(dto);
|
||||
}
|
||||
|
||||
@PublicRoute()
|
||||
@Post('authorize')
|
||||
authorizeOAuth(@Body() dto: OAuthConfigDto): Promise<OAuthAuthorizeResponseDto> {
|
||||
return this.service.authorize(dto);
|
||||
}
|
||||
|
||||
@PublicRoute()
|
||||
@Post('callback')
|
||||
async callback(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue