diff --git a/src/main/kotlin/com/vauthenticator/server/account/emailverification/EMailVerificationEndPoint.kt b/src/main/kotlin/com/vauthenticator/server/account/emailverification/EMailVerificationEndPoint.kt index d6b097f9..8137411b 100644 --- a/src/main/kotlin/com/vauthenticator/server/account/emailverification/EMailVerificationEndPoint.kt +++ b/src/main/kotlin/com/vauthenticator/server/account/emailverification/EMailVerificationEndPoint.kt @@ -7,6 +7,7 @@ import com.vauthenticator.server.oauth2.clientapp.Scopes import com.vauthenticator.server.role.PermissionValidator import jakarta.servlet.http.HttpSession import org.springframework.http.ResponseEntity +import org.springframework.http.ResponseEntity.badRequest import org.springframework.http.ResponseEntity.noContent import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken import org.springframework.stereotype.Controller @@ -26,11 +27,16 @@ class MailVerificationEndPoint( principal: JwtAuthenticationToken ): ResponseEntity { permissionValidator.validate(principal, httpSession, Scopes.from(Scope.MAIL_VERIFY)) - //todo validate email field in body - sendVerifyEMailChallenge.sendVerifyMail(request["email"]!!) - return noContent().build() - } + return if (request.keys.contains("email")) { + val email = request["email"]!! + sendVerifyEMailChallenge.sendVerifyMail(email) + noContent().build() + } else { + badRequest().build() + } + + } } diff --git a/src/main/kotlin/com/vauthenticator/server/mfa/domain/OtpMfa.kt b/src/main/kotlin/com/vauthenticator/server/mfa/domain/OtpMfa.kt index 8429d662..00cbb278 100644 --- a/src/main/kotlin/com/vauthenticator/server/mfa/domain/OtpMfa.kt +++ b/src/main/kotlin/com/vauthenticator/server/mfa/domain/OtpMfa.kt @@ -10,7 +10,6 @@ import com.vauthenticator.server.mfa.OtpConfigurationProperties import com.vauthenticator.server.mfa.repository.MfaAccountMethodsRepository import org.apache.commons.codec.binary.Hex -//todo the interface has to take in account the enrolled method interface OtpMfa { fun generateSecretKeyFor(account: Account, mfaMethod: MfaMethod, mfaChannel: String): MfaSecret fun getTOTPCode(secretKey: MfaSecret): MfaChallenge @@ -58,7 +57,7 @@ class TaimosOtpMfa( System.currentTimeMillis(), tokenTimeWindow, properties.length - ); + ) if (!validated) { throw MfaException("Customer Code does not match with system code") } diff --git a/src/test/kotlin/com/vauthenticator/server/account/emailverification/MailVerificationEndPointTest.kt b/src/test/kotlin/com/vauthenticator/server/account/emailverification/MailVerificationEndPointTest.kt index 27d9ca96..82805188 100644 --- a/src/test/kotlin/com/vauthenticator/server/account/emailverification/MailVerificationEndPointTest.kt +++ b/src/test/kotlin/com/vauthenticator/server/account/emailverification/MailVerificationEndPointTest.kt @@ -22,11 +22,11 @@ import org.springframework.security.oauth2.server.resource.authentication.JwtAut import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status -import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup import java.time.Instant @ExtendWith(MockKExtension::class) -internal class MailVerificationEndPointTest { +class MailVerificationEndPointTest { private val objectMapper = ObjectMapper() lateinit var mokMvc: MockMvc @@ -38,18 +38,17 @@ internal class MailVerificationEndPointTest { lateinit var cientApplicationRepository: ClientApplicationRepository @BeforeEach - internal fun setUp() { - mokMvc = MockMvcBuilders.standaloneSetup( + fun setUp() { + mokMvc = standaloneSetup( MailVerificationEndPoint( PermissionValidator(cientApplicationRepository), sendVerifyEMailChallenge ) - ) - .build() + ).build() } @Test - internal fun `when a challenge is sent`() { + fun `when a challenge is sent`() { every { sendVerifyEMailChallenge.sendVerifyMail(EMAIL) } just runs val signedJWT = signedJWTFor(A_CLIENT_APP_ID, EMAIL, listOf(Scope.MAIL_VERIFY.content)) @@ -72,5 +71,48 @@ internal class MailVerificationEndPointTest { .andExpect(status().isNoContent) } + @Test + fun `when a challenge api without request body`() { + val signedJWT = signedJWTFor(A_CLIENT_APP_ID, EMAIL, listOf(Scope.MAIL_VERIFY.content)) + val principal = JwtAuthenticationToken( + Jwt( + SecurityFixture.simpleJwtFor(A_CLIENT_APP_ID), + Instant.now(), + Instant.now().plusSeconds(100), + signedJWT.header.toJSONObject(), + signedJWT.payload.toJSONObject() + ) + ) + + mokMvc.perform( + put("/api/verify-challenge") + .contentType(MediaType.APPLICATION_JSON) + .principal(principal) + ) + .andExpect(status().isBadRequest) + } + + @Test + fun `when a challenge api is bad used`() { + val signedJWT = signedJWTFor(A_CLIENT_APP_ID, EMAIL, listOf(Scope.MAIL_VERIFY.content)) + val principal = JwtAuthenticationToken( + Jwt( + SecurityFixture.simpleJwtFor(A_CLIENT_APP_ID), + Instant.now(), + Instant.now().plusSeconds(100), + signedJWT.header.toJSONObject(), + signedJWT.payload.toJSONObject() + ) + ) + + mokMvc.perform( + put("/api/verify-challenge") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsBytes(emptyMap())) + .principal(principal) + ) + .andExpect(status().isBadRequest) + } + } \ No newline at end of file diff --git a/src/test/kotlin/com/vauthenticator/server/ticket/TicketCreatorTest.kt b/src/test/kotlin/com/vauthenticator/server/ticket/TicketCreatorTest.kt index dcb59028..26bd9ba7 100644 --- a/src/test/kotlin/com/vauthenticator/server/ticket/TicketCreatorTest.kt +++ b/src/test/kotlin/com/vauthenticator/server/ticket/TicketCreatorTest.kt @@ -1,6 +1,53 @@ package com.vauthenticator.server.ticket +import com.vauthenticator.server.clientapp.ClientAppFixture +import com.vauthenticator.server.extentions.expirationTimeStampInSecondFromNow +import com.vauthenticator.server.support.AccountTestFixture +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.junit5.MockKExtension +import io.mockk.just +import io.mockk.runs +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import java.time.Clock +import java.time.Duration +import java.time.Instant +import java.time.ZoneId + +private const val TICKET_ID = "A_TICKET_ID" + +@ExtendWith(MockKExtension::class) class TicketCreatorTest { + private val ticketGenerator = { TICKET_ID } + private val now = Instant.now() + private val clock: Clock = Clock.fixed(now, ZoneId.systemDefault()) + + @MockK + private lateinit var ticketRepository: TicketRepository + + private val ticketFeatures: TicketFeatures = TicketFeatures(Duration.ofSeconds(100)) + private val clientAppId = ClientAppFixture.aClientAppId() + private val account = AccountTestFixture.anAccount() + private val ticket = Ticket( + TicketId(TICKET_ID), + account.email, + clientAppId.content, + ticketFeatures.ttl.expirationTimeStampInSecondFromNow(clock), + TicketContext.empty() + ) + + @Test + fun `happy path`() { + + val uut = TicketCreator(ticketGenerator, clock, ticketRepository, ticketFeatures) + + every { ticketRepository.store(ticket) } just runs + + val createTicketFor = + uut.createTicketFor(account, clientAppId, TicketContext.empty()) - //TODO + assertEquals(TICKET_ID, createTicketFor.content) + } } \ No newline at end of file