diff --git a/scm-webapp/src/main/java/sonia/scm/security/AnonymousRealm.java b/scm-webapp/src/main/java/sonia/scm/security/AnonymousRealm.java index 17a14cce73..16ecead815 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/AnonymousRealm.java +++ b/scm-webapp/src/main/java/sonia/scm/security/AnonymousRealm.java @@ -6,8 +6,10 @@ import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher; import org.apache.shiro.realm.AuthenticatingRealm; +import sonia.scm.ConfigurationException; import sonia.scm.SCMContext; import sonia.scm.plugin.Extension; +import sonia.scm.user.UserDAO; import javax.inject.Singleton; @@ -27,10 +29,12 @@ public class AnonymousRealm extends AuthenticatingRealm { * dao realm helper */ private final DAORealmHelper helper; + private final UserDAO userDAO; @Inject - public AnonymousRealm(DAORealmHelperFactory helperFactory) { + public AnonymousRealm(DAORealmHelperFactory helperFactory, UserDAO userDAO) { this.helper = helperFactory.create(REALM); + this.userDAO = userDAO; setAuthenticationTokenClass(AnonymousToken.class); setCredentialsMatcher(new AllowAllCredentialsMatcher()); @@ -38,6 +42,9 @@ public class AnonymousRealm extends AuthenticatingRealm { @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) { + if (!userDAO.contains(SCMContext.USER_ANONYMOUS)) { + throw new ConfigurationException("trying to access anonymous but _anonymous user does not exist"); + } checkArgument(authenticationToken instanceof AnonymousToken, "%s is required", AnonymousToken.class); return helper.authenticationInfoBuilder(SCMContext.USER_ANONYMOUS).build(); } diff --git a/scm-webapp/src/test/java/sonia/scm/security/AnonymousRealmTest.java b/scm-webapp/src/test/java/sonia/scm/security/AnonymousRealmTest.java index 769d7406ca..1a67ea192c 100644 --- a/scm-webapp/src/test/java/sonia/scm/security/AnonymousRealmTest.java +++ b/scm-webapp/src/test/java/sonia/scm/security/AnonymousRealmTest.java @@ -8,7 +8,9 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import sonia.scm.ConfigurationException; import sonia.scm.SCMContext; +import sonia.scm.user.UserDAO; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -26,6 +28,9 @@ class AnonymousRealmTest { @Mock private DAORealmHelper.AuthenticationInfoBuilder builder; + @Mock + private UserDAO userDAO; + @InjectMocks private AnonymousRealm realm; @@ -35,20 +40,28 @@ class AnonymousRealmTest { @BeforeEach void prepareObjectUnderTest() { when(realmHelperFactory.create(AnonymousRealm.REALM)).thenReturn(realmHelper); - realm = new AnonymousRealm(realmHelperFactory); + realm = new AnonymousRealm(realmHelperFactory, userDAO); } @Test void shouldDoGetAuthentication() { when(realmHelper.authenticationInfoBuilder(SCMContext.USER_ANONYMOUS)).thenReturn(builder); when(builder.build()).thenReturn(authenticationInfo); + when(userDAO.contains(SCMContext.USER_ANONYMOUS)).thenReturn(true); AuthenticationInfo result = realm.doGetAuthenticationInfo(new AnonymousToken()); assertThat(result).isSameAs(authenticationInfo); } + @Test + void shouldThrowNotAuthorizedExceptionIfAnonymousUserNotExists() { + when(userDAO.contains(SCMContext.USER_ANONYMOUS)).thenReturn(false); + assertThrows(ConfigurationException.class, () -> realm.doGetAuthenticationInfo(new AnonymousToken())); + } + @Test void shouldThrowIllegalArgumentExceptionForWrongTypeOfToken() { + when(userDAO.contains(SCMContext.USER_ANONYMOUS)).thenReturn(true); assertThrows(IllegalArgumentException.class, () -> realm.doGetAuthenticationInfo(new UsernamePasswordToken())); } }