mirror of
https://github.com/booklore-app/booklore.git
synced 2026-02-18 00:17:53 +01:00
Re-enable ForwardAuth and have ForwardAuth work using email address (#1426)
* Fallback to using email for auth if user not defined by forwardauth * Re-enable RemoteAuth * Update build env
This commit is contained in:
@@ -6,6 +6,8 @@ import com.adityachandel.booklore.exception.ApiError;
|
||||
import com.adityachandel.booklore.model.dto.UserCreateRequest;
|
||||
import com.adityachandel.booklore.model.dto.request.RefreshTokenRequest;
|
||||
import com.adityachandel.booklore.model.dto.request.UserLoginRequest;
|
||||
import com.adityachandel.booklore.model.entity.BookLoreUserEntity;
|
||||
import com.adityachandel.booklore.repository.UserRepository;
|
||||
import com.adityachandel.booklore.service.user.UserProvisioningService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@@ -21,6 +23,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Tag(name = "Authentication", description = "Endpoints for user authentication, registration, and token management")
|
||||
@Slf4j
|
||||
@@ -32,6 +35,7 @@ public class AuthenticationController {
|
||||
private final AppProperties appProperties;
|
||||
private final UserProvisioningService userProvisioningService;
|
||||
private final AuthenticationService authenticationService;
|
||||
private final UserRepository userRepository;
|
||||
|
||||
@Operation(summary = "Register a new user", description = "Register a new user. Only admins can register users.")
|
||||
@ApiResponses({
|
||||
@@ -81,6 +85,15 @@ public class AuthenticationController {
|
||||
log.debug("Remote-Auth: retrieved values from headers: name: {}, username: {}, email: {}, groups: {}", name, username, email, groups);
|
||||
log.debug("Remote-Auth: remote auth settings: {}", appProperties.getRemoteAuth());
|
||||
|
||||
if ((username == null || username.isEmpty()) && (email != null && !email.isEmpty())) {
|
||||
log.debug("Remote-Auth: username is empty, trying to find user by email: {}", email);
|
||||
Optional<BookLoreUserEntity> user = userRepository.findByEmail(email);
|
||||
if (user.isPresent()) {
|
||||
username = user.get().getUsername();
|
||||
log.debug("Remote-Auth: found user by email, username: {}", username);
|
||||
}
|
||||
}
|
||||
|
||||
return authenticationService.loginRemote(name, username, email, groups);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,5 +8,6 @@ import lombok.*;
|
||||
@NoArgsConstructor
|
||||
public class PublicAppSetting {
|
||||
private boolean oidcEnabled;
|
||||
private boolean remoteAuthEnabled;
|
||||
private OidcProviderDetails oidcProviderDetails;
|
||||
}
|
||||
@@ -12,6 +12,8 @@ public interface UserRepository extends JpaRepository<BookLoreUserEntity, Long>
|
||||
|
||||
Optional<BookLoreUserEntity> findByUsername(String username);
|
||||
|
||||
Optional<BookLoreUserEntity> findByEmail(String email);
|
||||
|
||||
Optional<BookLoreUserEntity> findById(Long id);
|
||||
|
||||
List<BookLoreUserEntity> findAllByLibraries_Id(Long libraryId);
|
||||
|
||||
@@ -73,6 +73,7 @@ public class AppSettingService {
|
||||
PublicAppSetting.PublicAppSettingBuilder builder = PublicAppSetting.builder();
|
||||
|
||||
builder.oidcEnabled(Boolean.parseBoolean(settingPersistenceHelper.getOrCreateSetting(AppSettingKey.OIDC_ENABLED, "false")));
|
||||
builder.remoteAuthEnabled(appProperties.getRemoteAuth().isEnabled());
|
||||
builder.oidcProviderDetails(settingPersistenceHelper.getJsonSetting(settingsMap, AppSettingKey.OIDC_PROVIDER_DETAILS, OidcProviderDetails.class, null, false));
|
||||
|
||||
return builder.build();
|
||||
@@ -111,4 +112,4 @@ public class AppSettingService {
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,18 @@ export function initializeAuthFactory() {
|
||||
|
||||
resolve();
|
||||
});
|
||||
} else if (publicSettings.remoteAuthEnabled) {
|
||||
authService.remoteLogin().subscribe({
|
||||
next: () => {
|
||||
authInitService.markAsInitialized();
|
||||
resolve();
|
||||
},
|
||||
error: err => {
|
||||
console.error('[Remote Login] failed:', err);
|
||||
authInitService.markAsInitialized();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (forceLocalOnly) {
|
||||
console.warn('[OIDC] Forced local-only login via ?localOnly=true');
|
||||
|
||||
@@ -8,6 +8,7 @@ import {AuthService} from './auth.service';
|
||||
|
||||
export interface PublicAppSettings {
|
||||
oidcEnabled: boolean;
|
||||
remoteAuthEnabled: boolean;
|
||||
oidcProviderDetails: OidcProviderDetails;
|
||||
}
|
||||
|
||||
@@ -76,6 +77,7 @@ export class AppSettingsService {
|
||||
private syncPublicSettings(appSettings: AppSettings): void {
|
||||
const updatedPublicSettings: PublicAppSettings = {
|
||||
oidcEnabled: appSettings.oidcEnabled,
|
||||
remoteAuthEnabled: appSettings.remoteAuthEnabled,
|
||||
oidcProviderDetails: appSettings.oidcProviderDetails
|
||||
};
|
||||
const current = this.publicAppSettingsSubject.value;
|
||||
@@ -83,6 +85,7 @@ export class AppSettingsService {
|
||||
if (
|
||||
!current ||
|
||||
current.oidcEnabled !== updatedPublicSettings.oidcEnabled ||
|
||||
current.remoteAuthEnabled !== updatedPublicSettings.remoteAuthEnabled ||
|
||||
JSON.stringify(current.oidcProviderDetails) !== JSON.stringify(updatedPublicSettings.oidcProviderDetails)
|
||||
) {
|
||||
this.publicAppSettingsSubject.next(updatedPublicSettings);
|
||||
|
||||
@@ -47,6 +47,17 @@ export class AuthService {
|
||||
);
|
||||
}
|
||||
|
||||
remoteLogin(): Observable<{ accessToken: string; refreshToken: string, isDefaultPassword: string }> {
|
||||
return this.http.get<{ accessToken: string; refreshToken: string, isDefaultPassword: string }>(`${this.apiUrl}/remote`).pipe(
|
||||
tap((response) => {
|
||||
if (response.accessToken && response.refreshToken) {
|
||||
this.saveInternalTokens(response.accessToken, response.refreshToken);
|
||||
this.initializeWebSocketConnection();
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
saveInternalTokens(accessToken: string, refreshToken: string): void {
|
||||
localStorage.setItem('accessToken_Internal', accessToken);
|
||||
localStorage.setItem('refreshToken_Internal', refreshToken);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
backend:
|
||||
image: gradle:8-jdk21-alpine
|
||||
image: gradle:9-jdk25-alpine
|
||||
command: sh -c "cd /booklore-api && ./gradlew bootRun"
|
||||
ports:
|
||||
- "${BACKEND_PORT:-8080}:8080"
|
||||
@@ -58,4 +58,4 @@ services:
|
||||
|
||||
volumes:
|
||||
node_modules:
|
||||
backend_db:
|
||||
backend_db:
|
||||
|
||||
Reference in New Issue
Block a user