Kratos注册时404错误求助:搭建仅用户名密码认证系统问题
问题:Next.js 13集成Kratos注册请求返回404错误
我是Kratos新手,想搭建一个仅用用户名密码完成注册/登录的简单认证系统,但在Next.js 13提交注册请求时收到404错误,提示"Unable to locate the resource"。以下是相关代码配置:
Next.js页面代码
"use client"; import { useEffect, useRef, useState } from "react"; import { useSearchParams } from "next/navigation"; import { Configuration, FrontendApi } from "@ory/client"; import { edgeConfig } from "@ory/integrations/next"; const ory = new FrontendApi(new Configuration(edgeConfig)); function getCsrfTokenFromApiResponse(response) { try { const csrfToken = response?.data?.ui?.nodes?.find( (node) => node.attributes?.name === "csrf_token" )?.attributes?.value; return csrfToken || null; } catch (error) { console.error("Error while parsing the API response:", error); return null; } } function getFlowIdFromApiResponse(response) { try { const flowId = response?.data?.id; return flowId || null; } catch (error) { console.error("Error while parsing the API response:", error); return null; } } export default function Register() { const searchParams = useSearchParams(); console.log(" searchParams", searchParams?.getAll); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const flow = useRef(""); const csrfToken = useRef(""); useEffect(() => { const fetchFlow = async () => { const data = await ory.createBrowserRegistrationFlow(); csrfToken.current = getCsrfTokenFromApiResponse(data); flow.current = getFlowIdFromApiResponse(data); console.log(data); }; fetchFlow(); }, []); const handleSubmit = async (event) => { event.preventDefault(); var myHeaders = new Headers(); myHeaders.append("Content-Type", "application/json"); myHeaders.append("X-CSRF-Token", csrfToken.current); var raw = JSON.stringify({ method: "password", traits: { username, }, password, csrf_token: csrfToken.current, }); var requestOptions = { method: "POST", headers: myHeaders, body: raw, redirect: "follow", }; fetch( `http://127.0.0.1:4433/self-service/registration?flow=${flow.current}`, requestOptions ) .then((response) => response.text()) .then((result) => console.log(result)) .catch((error) => console.log("error", error)); }; return ( <form onSubmit={handleSubmit}> <label> Username: <input type="text" value={username} onChange={(event) => setUsername(event.target.value)} /> </label> <br /> <label> Password: <input type="password" value={password} onChange={(event) => setPassword(event.target.value)} /> </label> <br /> <button type="submit">Register</button> </form> ); }
身份Schema
{ "$id": "https://schemas.ory.sh/presets/kratos/quickstart/username-password/identity.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "title": "UsernamePassword", "type": "object", "properties": { "traits": { "type": "object", "properties": { "username": { "type": "string", "format": "string", "title": "username", "minLength": 8, "maxLength": 30, "ory.sh/kratos": { "credentials": { "password": { "identifier": true } } } } }, "required": ["username"], "additionalProperties": false } } }
Kratos配置
version: v0.13.0 dsn: memory serve: public: base_url: http://127.0.0.1:4433/ cors: enabled: true allow_credentials: true allowed_origins: - http://127.0.0.1:4433 - http://*127.0.0.1:4433 - http://localhost:3000 - http://*.localhost:3000 allowed_methods: - POST - GET - PUT - PATCH - DELETE allowed_headers: - Authorization - Cookie - Content-Type - X-Session-Token - X-Csrf-Token exposed_headers: - Content-Type - Set-Cookie debug: true admin: base_url: http://0.0.0.0:4434/ selfservice: default_browser_return_url: http://localhost:3000/ allowed_return_urls: - http://localhost:3000 methods: password: enabled: true flows: login: ui_url: http://localhost:3000/auth/login registration: ui_url: http://localhost:3000/auth/registration settings: ui_url: http://localhost:3000/auth/settings recovery: enabled: false log: level: debug secrets: cookie: - PLEASE-CHANGE-ME-I-AM-VERY-INSECURE identity: default_schema_id: default schemas: - id: default url: file:///etc/config/kratos/identity.schema.json courier: smtp: connection_uri: smtps://test:test@mailslurper:1025/?skip_ssl_verify=true
我已按照Kratos文档添加了/api/.ory/[..path].ts,希望有人指出错误原因,并提供实现该系统的更好方案。
错误原因与优化方案
错误原因分析
- 请求路径错误:Kratos处理注册提交的正确端点是
/self-service/registration/flows/{flow-id},而非你当前使用的/self-service/registration,错误路径直接导致404。 - 直接调用Kratos API的风险:虽然配置了CORS,但前端直接调用Kratos公共API存在安全隐患,且没有利用已配置的Next.js API路由代理。
- Flow处理逻辑不严谨:未处理flow过期、获取失败等场景,可能导致使用无效flow ID发起请求。
修正后的实现方案
1. 修正注册请求端点
将handleSubmit中的fetch URL改为正确路径:
`http://127.0.0.1:4433/self-service/registration/flows/${flow.current}`
2. 利用Next.js API路由代理(推荐)
通过已配置的/api/.ory/[..path].ts代理请求,避免直接暴露Kratos地址:
fetch( `/api/.ory/self-service/registration/flows/${flow.current}`, requestOptions )
3. 优化Flow获取与错误处理
更新flow获取逻辑,增加错误处理:
useEffect(() => { const fetchFlow = async () => { try { const data = await ory.createBrowserRegistrationFlow(); csrfToken.current = getCsrfTokenFromApiResponse(data); flow.current = getFlowIdFromApiResponse(data); if (!flow.current) throw new Error("Failed to get valid flow ID"); } catch (error) { console.error("Failed to fetch registration flow:", error); // 可添加UI错误提示或重试逻辑 } }; fetchFlow(); }, []);
4. 使用Ory Client简化提交逻辑
无需手动构造fetch请求,直接调用Ory Client方法减少错误:
const handleSubmit = async (event) => { event.preventDefault(); try { await ory.updateRegistrationFlow({ flow: flow.current, updateRegistrationFlowBody: { method: "password", traits: { username }, password, csrf_token: csrfToken.current, }, }); window.location.href = "/"; // 注册成功后跳转 } catch (error) { console.error("Registration failed:", error); // 显示错误信息给用户 } };
5. 验证Kratos配置
确认Kratos服务正常运行在http://127.0.0.1:4433,且身份schema文件路径正确,确保Kratos能加载到schema。
内容的提问来源于stack exchange,提问作者zeak
相关产品推荐
相关产品推荐

