Open4

Swiftから呼び出すNextAuth.jsのCredentialsProviderのauthorizedが呼ばれない

Sarutabiko | さるたびこ | 猿田彦Sarutabiko | さるたびこ | 猿田彦

Swift側からNextAuthのhttp://localhost:3000/api/auth/callback/credentials?を呼び出してauthorizeをさせる流れを作ろうとしていたが、どうもauthorizedが呼ばれない.

Sarutabiko | さるたびこ | 猿田彦Sarutabiko | さるたびこ | 猿田彦

[...nextauth].jsの中は下記.

export const authOptions = {
  adapter: PrismaAdapter(prisma),
  debug: true,
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
           /**/
      },
      async authorize(credentials) {
         //come here
      },
    }),

  ],
  session: {
    strategy: "jwt",
  },
};

ただ、通常のWebのsigninページからは正しく入れているようなので、
WireSharkで確認したところ、下記のような処理をしている様子。

Sarutabiko | さるたびこ | 猿田彦Sarutabiko | さるたびこ | 猿田彦

と思って調べていくうちに、結論はCookieに古いcsrf-tokenがセットされていたことが原因になっている様子.

next-auth.csrf-token
next-auth.callback-url

などがCookieに入っており、これが/api/auth/csrfで取得した値と食い違ってたことが原因.

他に下記もPOST時のデータとして送っている. (Content-Typeはapplication/x-www-form-urlencoded)

Sarutabiko | さるたびこ | 猿田彦Sarutabiko | さるたびこ | 猿田彦

試すだけのコードは下記のような形でauthorizedまでひとまずは届く.
(XXX_CSRF_TOKEN_XXXを変える)

    func sendCredentials() {
        guard let url = URL(string: "http://localhost:3000/api/auth/callback/credentials?") else { return }

        // POST リクエストの設定
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")

        let cookieValue = "next-auth.csrf-token=XXX_CSRF_TOKEN_XXX; next-auth.callback-url=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fsignin"
        request.setValue(cookieValue, forHTTPHeaderField: "Cookie")

        // フォームの値を辞書に入れる
        let parameters: [String: Any] = [
            "callbackUrl":"http://localhost:3000/",
            "csrfToken":"XXX_CSRF_TOKEN_XXX",
            "json": true,
        ]

        // フォームの値をエンコードする関数
        func encodeParameters(_ parameters: [String: Any]) -> String {
            var components:[String] = []
            for (key, value) in parameters {
                let encodedKey = key.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
                let encodedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
                components.append("\(encodedKey)=\(encodedValue)")
            }
            return components.joined(separator: "&")
        }

        // エンコードしたフォームの値をデータに変換して、httpBodyに設定する
        let encodedParameters = encodeParameters(parameters)
        request.httpBody = encodedParameters.data(using: .utf8)
        
        // POST リクエストの送信
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let error = error {
                print(error.localizedDescription)
                return
            }
        }.resume()
}