Hi,everyone
I am trying to make a small projects using fastapi ,Kratos,keto,auth and my ui instead of self service nodejs one that exist in example but l have a problem with the header cookies that comes from header which always is none , I installed Kratos and Keto locally and I am using the sdk register browser flow and for the frontend I am using jinja templates this is my error ;
ookie: {}
res: {'error': "(403)\nReason: Forbidden\nHTTP response headers: HTTPHeaderDict({'Cache-Control': 'private, no-cache, no-store, must-revalidate', 'Content-Type': 'application/json', 'Set-Cookie': 'csrf_token_806060ca5bf70dff3caa0e5c860002aade9d470a5a4dce73bcfa7ba10778f481=xPwrNnqn0H6UW/SwFeiLs9m2e4CWlwhNg0OKnGwNopg=; Path=/; Max-Age=31536000; HttpOnly; SameSite=Lax', 'Vary': 'Origin, Cookie', 'Date': 'Sun, 05 Jan 2025 23
2804 GMT', 'Content-Length': '794'})\nHTTP response body: error=GenericError(code=403, debug=None, details={'docs': '
https://www.ory.sh/kratos/docs/debug/csrf', 'hint': 'The anti-CSRF cookie was found but the CSRF token was not included in the HTTP request body (csrf_token) nor in the HTTP Header (X-CSRF-Token).', 'reject_reason': 'The HTTP Cookie Header was set and a CSRF token was sent but they do not match. We recommend deleting all cookies for this domain and retrying the flow.'}, id='security_csrf_violation', message='the request was rejected to protect you from Cross-Site-Request-Forgery', reason='Please retry the flow and optionally clear your cookies. The request was rejected to protect you from Cross-Site-Request-Forgery (CSRF) which could cause account takeover, leaking personal information, and other serious security issues.', request=None, status='Forbidden', additional_properties={}) additional_properties={}\n"}
Error during update_registration_flow: (403)
Reason: Forbidden
HTTP response headers: HTTPHeaderDict({'Cache-Control': 'private, no-cache, no-store, must-revalidate', 'Content-Type': 'application/json', 'Vary': 'Origin, Cookie', 'Date': 'Sun, 05 Jan 2025 23
2804 GMT', 'Content-Length': '794'})
HTTP response body: {"error":{"id":"security_csrf_violation","code":403,"status":"Forbidden","reason":"Please retry the flow and optionally clear your cookies. The request was rejected to protect you from Cross-Site-Request-Forgery (CSRF) which could cause account takeover, leaking personal information, and other serious security issues.","details":{"docs":"
https://www.ory.sh/kratos/docs/debug/csrf","hint":"The anti-CSRF cookie was found but the CSRF token was not included in the HTTP request body (csrf_token) nor in the HTTP Header (X-CSRF-Token).","reject_reason":"The HTTP Cookie Header was set and a CSRF token was sent but they do not match. We recommend deleting all cookies for this domain and retrying the flow."},"message":"the request was rejected to protect you from Cross-Site-Request-Forgery"}}
General Error: cannot access local variable 'update_response' where it is not associated with a value
INFO: 127.0.0.1:57930 - "POST /register HTTP/1.1" 400 Bad Request
WARNING: StatReload detected changes in 'main.py'. Reloading...
INFO: Shutting down
INFO: Waiting for application shutdown.
INFO: Application shutdown complete.
INFO: Finished server process [29984]
INFO: Started server process [30680]
INFO: Waiting for application startup.
INFO: Application startup complete.
WARNING: StatReload detected changes in 'main.py'. Reloading...
INFO: Shutting down
This is my function:
async def register(request: Request,
email: str = Form(...),
password: str = Form(...),
first_name: str = Form(...),
last_name: str = Form(...),
csrf_token: str = Form(...),
flow_id: str = Form(...)):
try:
# Log incoming data
print('====================register_api==========================')
print(f"request: {request}")
print(f"email: {email}")
print(f"password: {password}")
print(f"first_name: {first_name}")
print(f"last_name: {last_name}")
# Start the registration flow to get csrf_token and flow_id
registration_flow = frontend_api.create_browser_registration_flow()
flow_id = registration_flow.id
csrf_token = None
# Extract csrf_token from the flow
for node in registration_flow.ui.nodes:
attributes = getattr(node.attributes, 'actual_instance', None)
if attributes and hasattr(attributes, 'name') and attributes.name == "csrf_token":
csrf_token = attributes.value
break
# Ensure CSRF token and flow ID are present
if not csrf_token or not flow_id:
raise ValueError("CSRF token or Flow ID is missing.")
# Log the csrf_token
print(f"csrf_token: {csrf_token}")
# Prepare registration data using the correct Pydantic model
registration_data = UpdateRegistrationFlowBody(
actual_instance=UpdateRegistrationFlowWithPasswordMethod(
csrf_token=csrf_token,
password=password,
method="password",
traits={"email": email, "name": {"first": first_name, "last": last_name}},
transient_payload={},
)
)
# Validate the model before serialization
print('====================before model_validate==========================')
registration_data.model_validate(registration_data)
# Initialize the response variable
update_response = None
# Update the registration flow with serialized data
print('====================update_registration_flow==========================')
try:
print(f"Flow ID: {flow_id}")
print(f"CSRF Token from Body: {csrf_token}")
print(f"request.cookies Data: {request.cookies}")
print(f'request.cookies csrf_token Data: {request.cookies.get("csrf_token")}')
print(f'cookie: {request.headers.get("cookie")}')
update_response = frontend_api.update_registration_flow(
flow=flow_id,
update_registration_flow_body=registration_data,
cookie=request.cookies
)
print("API call successful:", update_response)
except Exception as e:
print("Error during update_registration_flow:", e)
raise HTTPException(status_code=400, detail=f"Error during registration update: {str(e)}")
# Log successful response and proceed with redirect
if update_response:
print(f"Registration successful: {update_response}")
return RedirectResponse(url="/login", status_code=303)
else:
raise HTTPException(status_code=400, detail="Registration flow update failed.")
except ValueError as ve:
print(f"Value Error: {ve}")
raise HTTPException(status_code=400, detail=f"Value Error: {ve}")
except AttributeError as ae:
print(f"Attribute Error: {ae}")
raise HTTPException(status_code=400, detail=f"Attribute Error: {ae}")
except Exception as e:
print(f"General Error: {e}")
raise HTTPException(status_code=400, detail=f"Data serialization error: {e}")
Thanks in advance