使用ORY托管服务及控制台创建Identity时遇Kratos CORS问题
问题现象
使用Ory Kratos的API和SDK时,无论管理控制台还是托管版Kratos都无法获取数据,一直触发CORS错误——甚至服务器关闭时也会报相同错误。
错误信息:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://ory.project.oryapis.com/admin/identities. (Reason: CORS request did not succeed). Status code: (null).
已确认情况:
- 托管版Kratos控制台显示无需手动配置CORS
- Insomnia可正常调用同一API及托管版接口,排除服务端接口本身问题
- 怀疑问题出在前端代码(使用
axios),但未发现明显错误
相关代码与配置
Axios 请求代码
const axiosClient = axios.create({ headers: { 'Content-type': 'application/json' }, withCredentials: true }); export async function createIdentity(email) { try { const { data } = await axiosClient.post('http://127.0.0.1:4434/identities', { traits: { email: email } }); console.log(data); } catch (error) { console.log(error); } }
Ory SDK 请求代码
const identity = new IdentityApi( new Configuration({ basePath: `https://pedantic.projects.oryapis.com`, accessToken: 'Bearer My_token', baseOptions: { withCredentials: true } }) ); export async function createIdentity(email: string) { return await identity .createIdentity({ createIdentityBody: { schema_id: 'preset://email', traits: { email: email } } }) .then(({ data }) => data); }
本地Kratos(v0.11.0)配置
serve: public: base_url: http://127.0.0.1:4433/ host: 127.0.0.1 cors: enabled: true allowed_origins: - 'http://localhost:5000' - 'http://localhost:3000' allowed_methods: - POST - GET - PUT - PATCH - DELETE allowed_headers: - Authorization - Access-Control-Allow-Origin - Cookie - Content-Type exposed_headers: - Content-Type - Set-Cookie admin: base_url: http://kratos:4434/ host: 127.0.0.1
日志信息
INFO[2022-12-20T15:47:41+10:00] completed handling request http_request=map[headers:map[accept:*/* accept-encoding:gzip, deflate, br accept-language:en-US,en;q=0.5 access-control-request-headers:content-type access-control-request-method:POST connection:keep-alive origin:http://127.0.0.1:5000 referer:http://127.0.0.1:5000/ sec-fetch-dest:empty sec-fetch-mode:cors sec-fetch-site:same-site user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0] host:127.0.0.1:4434 method:OPTIONS path:/admin/identities query:<nil> remote:127.0.0.1:38972 scheme:http] http_response=map[headers:map[location:/admin/identities] size:0 status:307 text_status:Temporary Redirect took:100.3µs]
解决办法
1. 给Admin接口补上CORS配置
你的配置仅给public接口添加了CORS规则,但调用的是admin接口(/admin/identities),admin服务完全没有CORS相关设置。浏览器发送OPTIONS预检请求时,Kratos返回307重定向,直接导致CORS验证失败。
修改Kratos配置,给admin服务添加CORS规则:
serve: # 保留原有public配置 admin: base_url: http://127.0.0.1:4434/ host: 127.0.0.1 cors: enabled: true allowed_origins: - 'http://localhost:5000' - 'http://localhost:3000' - 'http://127.0.0.1:5000' # 注意:前端实际用的IP/域名必须全加进去 allowed_methods: - POST - GET - PUT - PATCH - DELETE - OPTIONS # 必须允许OPTIONS方法,满足浏览器预检请求要求 allowed_headers: - Authorization - Content-Type - Cookie exposed_headers: - Content-Type - Set-Cookie allow_credentials: true # 配合axios的withCredentials使用
2. 修正Admin接口的base_url
日志显示OPTIONS请求返回307重定向,原因是admin的base_url配置为http://kratos:4434/,但实际请求地址是http://127.0.0.1:4434,Kratos会强制重定向到配置的域名,跨域场景下浏览器会拦截该重定向。
将admin的base_url改为与实际请求一致的地址:
admin: base_url: http://127.0.0.1:4434/ host: 127.0.0.1 # 加上上述CORS配置
3. 严格匹配Origin与允许列表
localhost:5000和127.0.0.1:5000属于两个不同的Origin,如果前端实际使用的是127.0.0.1:5000,但配置仅添加了localhost:5000,浏览器会判定Origin不被允许,直接触发CORS错误。
需将前端实际使用的所有域名/IP都加入allowed_origins列表。
4. 托管版Kratos的处理
托管版Kratos需在Ory Console中配置CORS允许列表:
- 进入Ory Console -> 目标项目 -> Settings -> Security -> CORS Origins
- 添加前端实际使用的域名(如
http://localhost:5000)
另外注意:Ory官方不建议直接从前端调用admin接口,admin操作应放在后端服务中执行,避免暴露admin权限。若必须从前端调用,除配置CORS外,还需确保access_token具备足够权限。
内容的提问来源于stack exchange,提问作者MJEND

