Skip to content

Commit

Permalink
tests for the child handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
mrFlick72 committed Oct 21, 2023
1 parent bf91477 commit 6d9485e
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 121 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package com.vauthenticator.server.config

import com.vauthenticator.server.account.repository.AccountRepository
import com.vauthenticator.server.login.CompositeLoginWorkflowEngine
import com.vauthenticator.server.login.LOGIN_ENGINE_BROKER_PAGE
import com.vauthenticator.server.login.userdetails.AccountUserDetailsService
import com.vauthenticator.server.login.workflow.CompositeLoginWorkflowEngine
import com.vauthenticator.server.login.workflow.LOGIN_ENGINE_BROKER_PAGE
import com.vauthenticator.server.mfa.MfaLoginWorkflowHandler
import com.vauthenticator.server.oauth2.clientapp.ClientApplicationRepository
import com.vauthenticator.server.oauth2.clientapp.Scope
import com.vauthenticator.server.oidc.logout.ClearSessionStateLogoutHandler
import com.vauthenticator.server.oidc.sessionmanagement.SessionManagementFactory
import com.vauthenticator.server.password.BcryptVAuthenticatorPasswordEncoder
import com.vauthenticator.server.password.changepassword.CHANGE_PASSWORD_URL
import com.vauthenticator.server.password.changepassword.ChangePasswordLoginWorkflowHandler
import org.slf4j.Logger
import org.slf4j.LoggerFactory
Expand Down Expand Up @@ -123,13 +124,19 @@ class WebSecurityConfig(
}

@Bean
fun loginWorkflowEngine(clientApplicationRepository: ClientApplicationRepository) =
fun loginWorkflowEngine(
accountRepository: AccountRepository,
clientApplicationRepository: ClientApplicationRepository
) =
CompositeLoginWorkflowEngine(
LOGIN_ENGINE_BROKER_PAGE,
listOf(
MfaLoginWorkflowHandler(clientApplicationRepository, "/mfa-challenge/send"),
ChangePasswordLoginWorkflowHandler("/change-password")
)
ChangePasswordLoginWorkflowHandler(
accountRepository,
SimpleUrlAuthenticationSuccessHandler(CHANGE_PASSWORD_URL)
)
),
SimpleUrlAuthenticationSuccessHandler(LOGIN_ENGINE_BROKER_PAGE)
)


Expand Down Expand Up @@ -172,6 +179,7 @@ class WebSecurityConfig(
fun successHandler(): AuthenticationSuccessHandler {
return SavedRequestAwareAuthenticationSuccessHandler()
}

@Bean
fun nextHopeLoginWorkflowSuccessHandler(): AuthenticationSuccessHandler {
return SimpleUrlAuthenticationSuccessHandler(LOGIN_ENGINE_BROKER_PAGE)
Expand All @@ -181,7 +189,8 @@ class WebSecurityConfig(
fun mfaFailureHandler(): AuthenticationFailureHandler {
return SimpleUrlAuthenticationFailureHandler("/mfa-challenge?error")
}
@Bean

@Bean
fun changePasswordFailureHandler(): AuthenticationFailureHandler {
return SimpleUrlAuthenticationFailureHandler("/change-password?error")
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.vauthenticator.server.login.workflow

import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import jakarta.servlet.http.HttpSession
import org.springframework.security.core.Authentication
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
import java.util.*
import kotlin.jvm.optionals.getOrElse

interface LoginWorkflowEngine {
fun workflowsNextHop(session: HttpSession): LoginWorkflowHandler
}

class CompositeLoginWorkflowEngine(
private val handlers: List<LoginWorkflowHandler>,
private val defaultSuccessHandler: AuthenticationSuccessHandler
) : LoginWorkflowEngine, AuthenticationSuccessHandler {

override fun onAuthenticationSuccess(
request: HttpServletRequest,
response: HttpServletResponse,
authentication: Authentication
) {
SecurityContextHolder.getContext().authentication = authentication
this.defaultSuccessHandler.onAuthenticationSuccess(request, response, authentication)
}

override fun workflowsNextHop(session: HttpSession): LoginWorkflowHandler {
val index = Optional.ofNullable(session.getAttribute("CompositeLoginWorkflowEngine_index")).getOrElse { 0 } as Int
val nextHandlerIndex = index + 1

return if (nextHandlerIndex > handlers.size) {
DefaultLoginWorkflowHandler
} else {
session.setAttribute("CompositeLoginWorkflowEngine_index", nextHandlerIndex)
handlers[index]
}

}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.vauthenticator.server.login.workflow

import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import jakarta.servlet.http.HttpSession
import org.slf4j.LoggerFactory
import org.springframework.security.core.Authentication
import org.springframework.security.web.DefaultRedirectStrategy
import org.springframework.security.web.RedirectStrategy
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping

@Controller
class LoginWorkflowEngineController(private val engine: LoginWorkflowEngine) {

private val logger = LoggerFactory.getLogger(LoginWorkflowEngineController::class.java)

val defaultNextHope = SavedRequestAwareAuthenticationSuccessHandler()
private val redirectStrategy: RedirectStrategy = DefaultRedirectStrategy()

@GetMapping(LOGIN_ENGINE_BROKER_PAGE)
fun view(
session: HttpSession,
request: HttpServletRequest,
response: HttpServletResponse,
authentication: Authentication
) {
val workflowsNextHop = engine.workflowsNextHop(session)
logger.debug("workflowsNextHop: $workflowsNextHop")

if (workflowsNextHop.canHandle(request, response)) {
logger.debug("go to redirect on ${workflowsNextHop.view()}")
redirectStrategy.sendRedirect(request, response, workflowsNextHop.view())
} else {
defaultNextHope.onAuthenticationSuccess(request, response, authentication)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.vauthenticator.server.login.workflow

import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse


const val LOGIN_ENGINE_BROKER_PAGE = "/login-workflow"

interface LoginWorkflowHandler {

fun view(): String

fun canHandle(request: HttpServletRequest, response: HttpServletResponse): Boolean
}

object DefaultLoginWorkflowHandler : LoginWorkflowHandler {
override fun view() = ""

override fun canHandle(request: HttpServletRequest, response: HttpServletResponse) = false

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.vauthenticator.server.mfa

import com.vauthenticator.server.extentions.hasEnoughScopes
import com.vauthenticator.server.login.LoginWorkflowHandler
import com.vauthenticator.server.login.workflow.LoginWorkflowHandler
import com.vauthenticator.server.oauth2.clientapp.ClientAppId
import com.vauthenticator.server.oauth2.clientapp.ClientApplicationRepository
import com.vauthenticator.server.oauth2.clientapp.Scope
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RestController
@RestController
class ChangePasswordEndPoint(val changePassword: ChangePassword) {

@PutMapping("/api/password")
@PutMapping("/api/account/password")
fun sendVerifyMail(
@RequestBody request: Map<String, String>,
principal: JwtAuthenticationToken
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
package com.vauthenticator.server.password.changepassword

import com.vauthenticator.server.login.LoginWorkflowHandler
import com.vauthenticator.server.account.AccountMandatoryAction
import com.vauthenticator.server.account.repository.AccountRepository
import com.vauthenticator.server.login.workflow.LoginWorkflowHandler
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.web.authentication.AuthenticationSuccessHandler

class ChangePasswordLoginWorkflowHandler(val url: String) :
LoginWorkflowHandler {
const val CHANGE_PASSWORD_URL = "/change-password"

private val handler = SimpleUrlAuthenticationSuccessHandler(url)
class ChangePasswordLoginWorkflowHandler(
val accountRepository: AccountRepository,
val handler: AuthenticationSuccessHandler
) : LoginWorkflowHandler {

init {
handler.setAlwaysUseDefaultTargetUrl(true)
}

override fun view(): String = "/change-password"
override fun view(): String = CHANGE_PASSWORD_URL

override fun canHandle(
request: HttpServletRequest,
response: HttpServletResponse,
): Boolean {
return true
val username = SecurityContextHolder.getContext().authentication.name
return accountRepository.accountFor(username)
.map { account -> account.mandatoryAction == AccountMandatoryAction.RESET_PASSWORD }
.orElseGet { false }
}

}
Loading

0 comments on commit 6d9485e

Please sign in to comment.