diff --git a/src/intTest/kotlin/activitypub/inbox/InboxTest.kt b/src/intTest/kotlin/activitypub/inbox/InboxTest.kt index e58aedf3..92fe3aa2 100644 --- a/src/intTest/kotlin/activitypub/inbox/InboxTest.kt +++ b/src/intTest/kotlin/activitypub/inbox/InboxTest.kt @@ -18,7 +18,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders import org.springframework.transaction.annotation.Transactional import org.springframework.web.context.WebApplicationContext import util.TestTransaction -import util.WithHttpSignature +import util.WithMockHttpSignature @SpringBootTest(classes = [SpringApplication::class]) @AutoConfigureMockMvc @@ -49,7 +49,7 @@ class InboxTest { } @Test - @WithHttpSignature + @WithMockHttpSignature fun 有効なHttpSignatureでPOSTしたら202() { mockMvc .post("/inbox") { @@ -72,7 +72,7 @@ class InboxTest { } @Test - @WithHttpSignature + @WithMockHttpSignature fun 有効なHttpSignaturesでPOSTしたら202() { mockMvc .post("/users/hoge/inbox") { diff --git a/src/intTest/kotlin/util/WithHttpSignature.kt b/src/intTest/kotlin/util/WithHttpSignature.kt index 49e5ead4..ded96f4e 100644 --- a/src/intTest/kotlin/util/WithHttpSignature.kt +++ b/src/intTest/kotlin/util/WithHttpSignature.kt @@ -13,5 +13,8 @@ import java.lang.annotation.Inherited annotation class WithHttpSignature( @get:AliasFor( annotation = WithSecurityContext::class - ) val setupBefore: TestExecutionEvent = TestExecutionEvent.TEST_METHOD + ) val setupBefore: TestExecutionEvent = TestExecutionEvent.TEST_METHOD, + val keyId: String = "https://example.com/users/test-user#pubkey", + val url: String = "https://example.com/inbox", + val method: String = "GET" ) diff --git a/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt b/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt index 3ca3751c..6f73f4df 100644 --- a/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt +++ b/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt @@ -1,34 +1,42 @@ package util -import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureUser +import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureUserDetailsService +import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.httpsignature.common.HttpHeaders import dev.usbharu.httpsignature.common.HttpMethod import dev.usbharu.httpsignature.common.HttpRequest +import dev.usbharu.httpsignature.sign.RsaSha256HttpSignatureSigner +import dev.usbharu.httpsignature.verify.DefaultSignatureHeaderParser +import dev.usbharu.httpsignature.verify.RsaSha256HttpSignatureVerifier import org.springframework.security.core.context.SecurityContext import org.springframework.security.core.context.SecurityContextHolder import org.springframework.security.test.context.support.WithSecurityContextFactory import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken import java.net.URL -class WithHttpSignatureSecurityContextFactory : WithSecurityContextFactory { +class WithHttpSignatureSecurityContextFactory( + userQueryService: UserQueryService, + transaction: Transaction +) : WithSecurityContextFactory { private val securityContextStrategy = SecurityContextHolder.getContextHolderStrategy() + private val httpSignatureUserDetailsService: HttpSignatureUserDetailsService = HttpSignatureUserDetailsService( + userQueryService, + RsaSha256HttpSignatureVerifier(DefaultSignatureHeaderParser(), RsaSha256HttpSignatureSigner()), + transaction + ) + + override fun createSecurityContext(annotation: WithHttpSignature): SecurityContext { - val httpSignatureUser = HttpSignatureUser( - "user", - "example.com", - 12345, - true, - true, - mutableListOf() - ) val preAuthenticatedAuthenticationToken = PreAuthenticatedAuthenticationToken( - "user", HttpRequest( + annotation.keyId, HttpRequest( URL("https://example.com/inbox"), HttpHeaders(mapOf()), HttpMethod.GET ) ) + val httpSignatureUser = httpSignatureUserDetailsService.loadUserDetails(preAuthenticatedAuthenticationToken) preAuthenticatedAuthenticationToken.details = httpSignatureUser preAuthenticatedAuthenticationToken.isAuthenticated = true val emptyContext = securityContextStrategy.createEmptyContext() diff --git a/src/intTest/kotlin/util/WithMockHttpSignature.kt b/src/intTest/kotlin/util/WithMockHttpSignature.kt new file mode 100644 index 00000000..e5796f6c --- /dev/null +++ b/src/intTest/kotlin/util/WithMockHttpSignature.kt @@ -0,0 +1,23 @@ +package util + +import org.springframework.core.annotation.AliasFor +import org.springframework.security.test.context.support.TestExecutionEvent +import org.springframework.security.test.context.support.WithSecurityContext +import java.lang.annotation.Inherited + +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE) +@Retention(AnnotationRetention.RUNTIME) +@Inherited +@MustBeDocumented +@WithSecurityContext(factory = WithMockHttpSignatureSecurityContextFactory::class) +annotation class WithMockHttpSignature( + @get:AliasFor( + annotation = WithSecurityContext::class + ) val setupBefore: TestExecutionEvent = TestExecutionEvent.TEST_METHOD, + val username: String = "test-user", + val domain: String = "example.com", + val keyId: String = "https://example.com/users/test-user#pubkey", + val id: Long = 1234L, + val url: String = "https://example.com/inbox", + val method: String = "GET" +) diff --git a/src/intTest/kotlin/util/WithMockHttpSignatureSecurityContextFactory.kt b/src/intTest/kotlin/util/WithMockHttpSignatureSecurityContextFactory.kt new file mode 100644 index 00000000..29dda972 --- /dev/null +++ b/src/intTest/kotlin/util/WithMockHttpSignatureSecurityContextFactory.kt @@ -0,0 +1,39 @@ +package util + +import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureUser +import dev.usbharu.httpsignature.common.HttpHeaders +import dev.usbharu.httpsignature.common.HttpMethod +import dev.usbharu.httpsignature.common.HttpRequest +import org.springframework.security.core.context.SecurityContext +import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.security.test.context.support.WithSecurityContextFactory +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken +import java.net.URL + +class WithMockHttpSignatureSecurityContextFactory : + WithSecurityContextFactory { + + private val securityContextStrategy = SecurityContextHolder.getContextHolderStrategy() + + override fun createSecurityContext(annotation: WithMockHttpSignature): SecurityContext { + val preAuthenticatedAuthenticationToken = PreAuthenticatedAuthenticationToken( + annotation.keyId, HttpRequest( + URL(annotation.url), + HttpHeaders(mapOf()), HttpMethod.valueOf(annotation.method.uppercase()) + ) + ) + val httpSignatureUser = HttpSignatureUser( + annotation.username, + annotation.domain, + annotation.id, + true, + true, + mutableListOf() + ) + preAuthenticatedAuthenticationToken.details = httpSignatureUser + preAuthenticatedAuthenticationToken.isAuthenticated = true + val emptyContext = securityContextStrategy.createEmptyContext() + emptyContext.authentication = preAuthenticatedAuthenticationToken + return emptyContext + } +}