spring-securityでpermitAllが効かずAPIのレスポンスが401になる

# はじめに

以下の書籍の7章でspring-securityを学習していた際につまづいたのでまとめます

https://www.amazon.co.jp/Kotlin-%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%B5%E3%82%A4%E3%83%89%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%AE%9F%E8%B7%B5%E9%96%8B%E7%99%BA-%E7%AB%B9%E7%AB%AF-%E5%B0%9A%E4%BA%BA/dp/4297118599/ref=sr_1_4?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=3BKKUHRVV08G4&keywords=kotlin&qid=1673771738&sprefix=kotlin%2Caps%2C177&sr=8-4

# spring-securityの学習について

そもそもspring-securityをどのように使うのかは書籍と以下のサイトが参考になりました
注意としては書籍のspring-securityのバージョンは古く、現在のバージョン6で大きく書き方が変わっているので注意が必要です

https://qiita.com/rubytomato@github/items/6c6318c948398fa62275

https://stackoverflow.com/questions/75047817/spring-in-kotlin-from-5-3-to-6-0-security-configuration

# 問題

以下のAPIを作成しました

```kotlin:ToDoController.kt
package com.example.auth.presentation.controller

import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping

@Controller
class ToDoController() {
   @GetMapping("/hello")
   fun hello(): String {
       return "Hello"
   }
}
```

そしてspring-securityの設定ファイルを作成しました
ここでは`/hello`というアクセスは認証なしにアクセスできるように設定しました

```kotlin:SecurityConfig.kt
package com.example.auth.presentation.config

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.web.SecurityFilterChain

@Configuration
@EnableWebSecurity
class SecurityConfig {

    @Bean
    fun configureHttpSecurity(httpSecurity: HttpSecurity): SecurityFilterChain {
        httpSecurity
            .authorizeHttpRequests()
            .requestMatchers("/hello").permitAll()
            .and()
            .csrf().disable()
        return httpSecurity.build()
    }
}
```

しかしこの状態で

```
$ curl http://localhost:8080/hello
```

にアクセスすると

```
HTTP/1.1 401 
Set-Cookie: JSESSIONID=98C4234BA2E22192C36A48E2D07D1D43; Path=/; HttpOnly
WWW-Authenticate: Basic realm="Realm"
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
WWW-Authenticate: Basic realm="Realm"
Content-Length: 0
Date: Sun, 15 Jan 2023 08:20:12 GMT
```

と認証エラーが発生してしまいます。認証する設定にしていないはずなのに、、、

画面にアクセスすると以下の画面がでて、エラーページを表示しようとしています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/428a1292-7068-965f-5d0a-cdac0816d877.png)


# 解決方法

まずはspring-securityの依存をすべてコメントにしてAPIが正しく動くか試しました
すると以下のエラーが発生

```
HTTP/1.1 401 
Set-Cookie: JSESSIONID=98C4234BA2E22192C36A48E2D07D1D43; Path=/; HttpOnly
WWW-Authenticate: Basic realm="Realm"
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
WWW-Authenticate: Basic realm="Realm"
Content-Length: 0
Date: Sun, 15 Jan 2023 08:20:12 GMT
```

先程と同じエラーが発生しました
てことはspring-securityの設定は関係ないということがわかりました

このページは`Controller`に問題があるときにでるようなので確認してみると

```kotlin:ToDoContoroller
@Controller
class ToDoController() {
```

となっていました。今回の場合`@Contoroller`でなく`@RestController`でないとだめでした

https://anveloper.com/2021/01/25/controller%E3%80%81%EF%BC%A0restcontroller%E9%81%95%E3%81%84/

@Controllerの場合はViewが必要になるのが原因でした

```kotlin:ToDoContoroller
@RestController
class ToDoController() {
```

と修正したところしっかり認証無しでAPIがたたけるようになりました

# おわりに

問題を特定するまでにかなり時間がかかってしまいました
そもそもspring-securityのせいだと思い込み調べまくっていたのがよくなかったです


# 参考

https://qiita.com/rubytomato@github/items/6c6318c948398fa62275

https://stackoverflow.com/questions/75047817/spring-in-kotlin-from-5-3-to-6-0-security-configuration

https://anveloper.com/2021/01/25/controller%E3%80%81%EF%BC%A0restcontroller%E9%81%95%E3%81%84/