I am new to Svelte flow and I can't figure out how can I auth from front-end using svelte-kit and POST action form... from next/react all works perfect, same backend code. This is my +page.server.js
import { fail, redirect } from '@sveltejs/kit';
/** @type {import('./$types').Actions} */
export const actions = {
default: async ({ fetch, cookies, request }) => {
const data = await request.formData();
const username = data.get('username');
const password = data.get('password');
if (!username || !password) {
return fail(400, { username, password, missing: true })
}
const response = await fetch(`${api_url}/login`, {
method: "POST",
headers: {
'Content-Type': 'application/json',
"WWW-Authenticate": "Bearer",
'Accept': 'application/json'
},
body: JSON.stringify({username, password})
})
const json = await response.json();
if (response.status === 200) {
cookies.set('token', json.access_token, {
path: '/',
httpOnly: true,
sameSite: 'strict',
maxAge: 60 * 60 * 24 * 1000
});
throw redirect(302, "/");
} else {
return fail(422, { errors: json });
}
}
}
I just follow the tutorial in fastapi for 0auth2 authentication, but this errors come only in svelte-kit, where is the mistake? I think the problem is inside fetch call body? Server say the username and password cannot be empty
msg: "field required"
type: "value_error.missing"
my +page.svelte is this:
<script>
import { enhance } from '$app/forms';
/** @type {import('./$types').ActionData} */
export let form;
</script>
<!-- component -->
<div class="w-full min-h-screen bg-cyan-950 text-white flex flex-col sm:justify-center items-center pt-6 sm:pt-0">
<div class="w-full sm:max-w-md p-5 mx-auto">
<h2 class="mb-12 text-center text-5xl font-extrabold">Accedi</h2>
{#if form?.errors}<p class="error">{console.log(form.errors)}</p>{/if}
<form method="POST" use:enhance>
<div class="mb-4">
<label class="block mb-1" for="email">Username</label>
<input id="username" type="text" name="username" class="text-gray-700 py-2 px-3 border border-gray-300 focus:border-red-300 focus:outline-none focus:ring focus:ring-red-200 focus:ring-opacity-50 rounded-md shadow-sm disabled:bg-gray-100 mt-1 block w-full" />
</div>
<div class="mb-4">
<label class="block mb-1" for="password">Password</label>
<input id="password" type="password" name="password" class="text-gray-700 py-2 px-3 border border-gray-300 focus:border-red-300 focus:outline-none focus:ring focus:ring-red-200 focus:ring-opacity-50 rounded-md shadow-sm disabled:bg-gray-100 mt-1 block w-full" />
</div>
<div class="mt-6 flex items-center justify-between">
<div class="flex items-center">
<input id="remember_me" type="checkbox" class="border border-gray-300 text-red-600 shadow-sm focus:border-red-300 focus:ring focus:ring-red-200 focus:ring-opacity-50" />
<label for="remember_me" class="ml-2 block text-sm leading-5 text-gray-200"> Ricordami </label>
</div>
</div>
<div class="mt-6">
<button class="w-full inline-flex items-center justify-center px-4 py-2 bg-cyan-600 border border-transparent rounded-md font-semibold capitalize text-white hover:bg-cyan-800 active:bg-red-700 focus:outline-none focus:border-red-700 focus:ring focus:ring-red-200 disabled:opacity-25 transition">Accedi</button>
</div>
</form>
</div>
</div>
and my fastapi code:
@router.post("/login", response_model=Token, tags=["Auth"])
async def login_for_access_token(
form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
):
user = authenticate_user(form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user.username}, expires_delta=access_token_expires
)
return {"access_token": access_token, "token_type": "bearer"}