diff --git a/src/test/java/net/geant/nmaas/portal/api/auth/OIDCAuthControllerTest.java b/src/test/java/net/geant/nmaas/portal/api/auth/OIDCAuthControllerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..90b0cdce3b969d71985ae2f40f9266854f644f11
--- /dev/null
+++ b/src/test/java/net/geant/nmaas/portal/api/auth/OIDCAuthControllerTest.java
@@ -0,0 +1,158 @@
+package net.geant.nmaas.portal.api.auth;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.ws.rs.core.HttpHeaders;
+import net.geant.nmaas.portal.api.configuration.ConfigurationView;
+import net.geant.nmaas.portal.api.security.JWTTokenService;
+import net.geant.nmaas.portal.persistent.entity.Domain;
+import net.geant.nmaas.portal.persistent.entity.Role;
+import net.geant.nmaas.portal.persistent.entity.User;
+import net.geant.nmaas.portal.persistent.entity.UserRole;
+import net.geant.nmaas.portal.service.ConfigurationManager;
+import net.geant.nmaas.portal.service.DomainService;
+import net.geant.nmaas.portal.service.OidcUserService;
+import net.geant.nmaas.portal.service.UserLoginRegisterService;
+import net.geant.nmaas.portal.service.UserService;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.oauth2.core.oidc.OidcIdToken;
+import org.springframework.security.oauth2.core.oidc.user.OidcUser;
+import org.springframework.test.util.ReflectionTestUtils;
+import org.springframework.web.servlet.view.RedirectView;
+
+import java.lang.reflect.Constructor;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class OIDCAuthControllerTest {
+
+    @InjectMocks
+    private OIDCAuthController oidcAuthController;
+
+    @Mock
+    private OidcUserService oidcUserService;
+    @Mock
+    private JWTTokenService jwtTokenService;
+    @Mock
+    private UserLoginRegisterService loginRegisterService;
+    @Mock
+    private UserService userService;
+    @Mock
+    private PasswordEncoder passwordEncoder;
+    @Mock
+    private DomainService domainService;
+    @Mock
+    private ConfigurationManager configurationManager;
+    @Mock
+    private HttpServletRequest request;
+
+    @Test
+    void shouldReturnOidcTokenOnSuccessfulLinking() throws Exception {
+        // Given
+        OidcLogin oidcLogin = new OidcLogin("user@example.com", "pass123", "uuid-123", "John", "Doe", "oidc-token");
+
+        Constructor<User> userConstructor = User.class.getDeclaredConstructor();
+        userConstructor.setAccessible(true);
+        User user = userConstructor.newInstance();
+
+        ReflectionTestUtils.setField(user, "password", "hashed-password");
+        ReflectionTestUtils.setField(user, "enabled", true);
+        ReflectionTestUtils.setField(user, "termsOfUseAccepted", true);
+        ReflectionTestUtils.setField(user, "privacyPolicyAccepted", true);
+
+        Constructor<Domain> domainConstructor = Domain.class.getDeclaredConstructor();
+        domainConstructor.setAccessible(true);
+        Domain domain = domainConstructor.newInstance();
+        ReflectionTestUtils.setField(domain, "name", "Global");
+
+        UserRole role = new UserRole(user, domain, Role.ROLE_USER);
+        ReflectionTestUtils.setField(user, "roles", List.of(role));
+
+        when(userService.findByEmail(any())).thenReturn(user);
+        when(passwordEncoder.matches(any(), any())).thenReturn(true);
+
+        ConfigurationView config = mock(ConfigurationView.class);
+        when(config.isMaintenance()).thenReturn(false);
+        when(configurationManager.getConfiguration()).thenReturn(config);
+
+        User linkedUser = userConstructor.newInstance();
+        when(oidcUserService.linkUser(any(), any(), any(), any())).thenReturn(linkedUser);
+        when(jwtTokenService.getToken(any())).thenReturn("jwt-token");
+        when(jwtTokenService.getRefreshToken(any())).thenReturn("refresh-token");
+
+        when(request.getHeader(HttpHeaders.HOST)).thenReturn("localhost");
+        when(request.getHeader(HttpHeaders.USER_AGENT)).thenReturn("JUnit");
+
+        // When
+        UserOidcToken result = oidcAuthController.oidcLinkedSuccess(oidcLogin, request);
+
+        // Then
+        assertEquals("jwt-token", result.token());
+        assertEquals("refresh-token", result.refreshToken());
+        assertEquals("uuid-123", result.oidcToken());
+
+        verify(loginRegisterService).registerNewSuccessfulLogin(eq(user), any(), any(), any());
+    }
+
+    @Test
+    void shouldRedirectToLoginSuccessIfOidcUserIsValid() throws Exception {
+        // given
+        OidcUser oidcUser = mock(OidcUser.class);
+        OidcIdToken idToken = mock(OidcIdToken.class);
+        when(idToken.getTokenValue()).thenReturn("oidc-token");
+        when(oidcUser.getIdToken()).thenReturn(idToken);
+
+        when(oidcUserService.externalUserRequiredLinking(any())).thenReturn(false);
+
+        Constructor<User> userConstructor = User.class.getDeclaredConstructor();
+        userConstructor.setAccessible(true);
+        User user = userConstructor.newInstance();
+
+        when(oidcUserService.checkUser(any())).thenReturn(user);
+        when(jwtTokenService.getToken(any())).thenReturn("jwt-token");
+        when(jwtTokenService.getRefreshToken(any())).thenReturn("refresh-token");
+
+        when(request.getHeader(HttpHeaders.HOST)).thenReturn("localhost");
+        when(request.getHeader(HttpHeaders.USER_AGENT)).thenReturn("JUnit");
+
+        // when
+        RedirectView result = oidcAuthController.oidcLoginSuccess(oidcUser, request);
+
+        // then
+        assertTrue(result.getUrl().contains("login-success"));
+        assertTrue(result.getUrl().contains("token=jwt-token"));
+        assertTrue(result.getUrl().contains("refresh_token=refresh-token"));
+        assertTrue(result.getUrl().contains("oidc_token=oidc-token"));
+
+        verify(loginRegisterService).registerNewSuccessfulLogin(eq(user), any(), any(), any());
+    }
+
+    @Test
+    void shouldRedirectToLinkingIfExternalUserRequiresLinking() {
+        // given
+        OidcUser oidcUser = mock(OidcUser.class);
+        OidcIdToken idToken = mock(OidcIdToken.class);
+        when(idToken.getTokenValue()).thenReturn("oidc-token");
+        when(oidcUser.getIdToken()).thenReturn(idToken);
+
+        when(oidcUserService.externalUserRequiredLinking(any())).thenReturn(true);
+
+        // when
+        RedirectView result = oidcAuthController.oidcLoginSuccess(oidcUser, request);
+
+        // then
+        assertTrue(result.getUrl().contains("/login-linking?oidc_token=oidc-token"));
+    }
+}