feat: WebFingerのエンドポイントを追加

This commit is contained in:
usbharu 2023-09-24 10:33:43 +09:00
parent b36e79048a
commit 63cb3427e4
2 changed files with 51 additions and 20 deletions

View File

@ -12,10 +12,10 @@ import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Configuration
import org.springframework.core.annotation.Order import org.springframework.core.annotation.Order
import org.springframework.http.MediaType
import org.springframework.security.config.Customizer import org.springframework.security.config.Customizer
import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
import org.springframework.security.core.Authentication import org.springframework.security.core.Authentication
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.security.crypto.password.PasswordEncoder
@ -28,7 +28,6 @@ import org.springframework.security.oauth2.server.authorization.token.OAuth2Toke
import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher
import org.springframework.web.servlet.handler.HandlerMappingIntrospector import org.springframework.web.servlet.handler.HandlerMappingIntrospector
import java.security.KeyPairGenerator import java.security.KeyPairGenerator
import java.security.interfaces.RSAPrivateKey import java.security.interfaces.RSAPrivateKey
@ -36,6 +35,7 @@ import java.security.interfaces.RSAPublicKey
import java.util.* import java.util.*
@EnableWebSecurity(debug = true) @EnableWebSecurity(debug = true)
@EnableWebFluxSecurity()
@Configuration @Configuration
class SecurityConfig { class SecurityConfig {
@ -47,9 +47,8 @@ class SecurityConfig {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http) OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http)
http http
.exceptionHandling { .exceptionHandling {
it.defaultAuthenticationEntryPointFor( it.authenticationEntryPoint(
LoginUrlAuthenticationEntryPoint("/login"), LoginUrlAuthenticationEntryPoint("/login")
MediaTypeRequestMatcher(MediaType.TEXT_HTML)
) )
} }
.oauth2ResourceServer { .oauth2ResourceServer {
@ -58,29 +57,23 @@ class SecurityConfig {
return http.build() return http.build()
} }
@Bean @Bean
@Order(2) @Order(2)
fun defaultSecurityFilterChain(http: HttpSecurity, introspector: HandlerMappingIntrospector): SecurityFilterChain { fun defaultSecurityFilterChain(http: HttpSecurity, introspector: HandlerMappingIntrospector): SecurityFilterChain {
val builder = MvcRequestMatcher.Builder(introspector) val builder = MvcRequestMatcher.Builder(introspector)
http.authorizeHttpRequests {
it.requestMatchers(builder.pattern("/api/v1/**")).hasAnyAuthority("SCOPE_read", "SCOPE_read:accounts")
}
http
.authorizeHttpRequests {
it.requestMatchers(
builder.pattern("/inbox"),
builder.pattern("/api/v1/apps"),
builder.pattern("/api/v1/instance/**")
).permitAll()
}
http http
.authorizeHttpRequests { .authorizeHttpRequests {
it.requestMatchers(PathRequest.toH2Console()).permitAll() it.requestMatchers(PathRequest.toH2Console()).permitAll()
} it.requestMatchers(
http builder.pattern("/inbox"),
.authorizeHttpRequests { builder.pattern("/api/v1/apps"),
it.anyRequest().authenticated() builder.pattern("/api/v1/instance/**"),
builder.pattern("/.well-known/**")
).permitAll()
it.requestMatchers(builder.pattern("/api/v1/**")).hasAnyAuthority("SCOPE_read", "SCOPE_read:accounts")
it.anyRequest().denyAll()
} }
http http
.oauth2ResourceServer { .oauth2ResourceServer {

View File

@ -0,0 +1,38 @@
package dev.usbharu.hideout.controller.wellknown
import dev.usbharu.hideout.config.ApplicationConfig
import dev.usbharu.hideout.domain.model.wellknown.WebFinger
import dev.usbharu.hideout.service.api.WebFingerApiService
import dev.usbharu.hideout.util.AcctUtil
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import java.net.URL
@Controller
@RequestMapping("/.well-known")
class WebFingerController(
private val webFingerApiService: WebFingerApiService,
private val applicationConfig: ApplicationConfig
) {
@GetMapping("/webfinger")
suspend fun webfinger(@RequestParam resource: String): ResponseEntity<WebFinger> {
val acct = AcctUtil.parse(resource)
val user =
webFingerApiService.findByNameAndDomain(acct.username, acct.domain ?: URL(applicationConfig.url).host)
val webFinger = WebFinger(
"acct:${user.name}@${user.domain}",
listOf(
WebFinger.Link(
"self",
"application/activity+json",
applicationConfig.url + "/users/" + user.id
)
)
)
return ResponseEntity(webFinger, HttpStatus.OK)
}
}