Open4
Swiftから呼び出すNextAuth.jsのCredentialsProviderのauthorizedが呼ばれない
Swift側からNextAuthのhttp://localhost:3000/api/auth/callback/credentials?を呼び出してauthorizeをさせる流れを作ろうとしていたが、どうもauthorizedが呼ばれない.
[...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で確認したところ、下記のような処理をしている様子。
と思って調べていくうちに、結論はCookieに古いcsrf-tokenがセットされていたことが原因になっている様子.
next-auth.csrf-token
next-auth.callback-url
などがCookieに入っており、これが/api/auth/csrfで取得した値と食い違ってたことが原因.
他に下記もPOST時のデータとして送っている. (Content-Typeはapplication/x-www-form-urlencoded)
試すだけのコードは下記のような形で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()
}