Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

signIn response object always showing values of status = 200 and ok = true even when client submits invalid credentials #10931

Open
stephendewyer opened this issue May 15, 2024 · 1 comment
Labels
bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.

Comments

@stephendewyer
Copy link

stephendewyer commented May 15, 2024

Environment

System:
OS: Windows 11 10.0.22631
CPU: (12) x64 13th Gen Intel(R) Core(TM) i7-1355U
Memory: 2.92 GB / 15.72 GB
Binaries:
Node: 20.8.1 - C:\Program Files\nodejs\node.EXE
npm: 10.1.0 - C:\Program Files\nodejs\npm.CMD
Browsers:
Edge: Chromium (123.0.2420.97)
Internet Explorer: 11.0.22621.3527
npmPackages:
@auth/core: ^0.31.0 => 0.31.0
@auth/sveltekit: ^1.1.0 => 1.1.0

Reproduction URL

https://github.com/stephendewyer/art-in-tech-services-2/blob/main/src/routes/login-client/%2Bpage.svelte

Describe the issue

I am creating a custom signin page for a project. The signIn function from @auth/sveltekit/client is returning an object that is always status = 200 and ok = true even when the client submits invalid credentials. As a result, I am unable to show users feedback after they submit their credentials. I've tried to find a workaround to no avail. In previous @auth/sveltekit versions (and earlier SvelteKit versions), the signIn function would return status = 400 and ok = false if the credentials submitted by the user were invalid.

How to reproduce

+page.svelte:

<script lang="ts">
    import { PUBLIC_DOMAIN } from "$env/static/public";
    import BannerImage from "$lib/images/Art_in_Tech_Services_banner_with_logo.jpg";
    import { page } from "$app/stores";
    // import PendingFlashMessage from "$lib/components/flashMessages/PendingFlashMessage.svelte";
    // import ErrorFlashMessage from "$lib/components/flashMessages/ErrorFlashMessage.svelte";
    // import SuccessFlashMessage from "$lib/components/flashMessages/SuccessFlashMessage.svelte";
    import EmailInput from "$lib/components/inputs/EmailInput.svelte";
    import PasswordInput from "$lib/components/inputs/PasswordInput.svelte";
    import SubmitButton from "$lib/components/buttons/SubmitButton.svelte";
    import CancelButton from "$lib/components/buttons/CancelButton.svelte";
    import ActionButtonSecondary from "$lib/components/buttons/ActionButtonSecondary.svelte";
    import { goto } from '$app/navigation';
    import { signIn } from "@auth/sveltekit/client";

    // receive form data from server

    let emailInputValue: string = "";
    let emailIsValid: boolean = true;

    let passwordInputValue: string = "";
    let passwordIsValid: boolean = true;

    let loginClientButtonDisabled: boolean = true;

    $: if (
        emailIsValid &&
        passwordIsValid &&
        (passwordInputValue !== "") &&
        (emailInputValue !== "")
    ) {
        loginClientButtonDisabled = false;
    } else {
        loginClientButtonDisabled = true;
    };

    let responseItem: ResponseObj = {
        success: "",
        error: "",
        status: null
    };

    $: if((responseItem.success) || (responseItem.error)) {
        setTimeout(() => {
            responseItem.success = "";
            responseItem.error = "";
            status: null;
        }, 4000)
    };

    const loginClientHandler = async () => {
        pending = true;
        try {
            const response = await signIn("credentials", {
                providerId: "client-login",
                email: emailInputValue,
                password: passwordInputValue,
                redirect: false,
                callbackUrl: "/authenticated-client/client"
            });
            if (response) {
                responseItem.success = "valid email and password";
                emailInputValue = "";
                passwordInputValue = "";
                goto(`/authenticated-client/client`)
            };
        } catch (error) {
            console.log(error);
        };
    };

    // $: console.log($page.data.session?.user?.email)

    let pending: boolean = false;

    $: if((responseItem.success) || (responseItem.error)) {
        pending = false;
    };

</script>

<svelte:head>
	<title>Art in Tech Services - login client</title>
	<meta name="description" content="login client" />
	<meta property="og:image" content={BannerImage} />
    <meta property="og:url" content={PUBLIC_DOMAIN+$page.url.pathname}/>
</svelte:head>

<div class="page">
    <form class="form" on:submit|preventDefault={loginClientHandler}>
        <h1>login client</h1>
        <div class="input_row">
            <EmailInput
                bind:isValid={emailIsValid}
                placeholder="myEmail@myDomain.com"
                inputID="client_email"
                inputName="client_email"
                bind:emailInputValue={emailInputValue}
                inputLabel={true}
                required={true}
            >
                email:
            </EmailInput>
        </div>
        <div class="input_row">
            <PasswordInput
                bind:isValid={passwordIsValid}
                placeholder="myPassword"
                inputID="client_password"
                inputName="client_password"
                inputLabel={true}
                bind:passwordInputValue={passwordInputValue}
                required={true}
                passwordInputErrorMessage="password required"
            >
                password:
            </PasswordInput>
        </div>
        <div class="buttons_container">
            <SubmitButton 
                disable={loginClientButtonDisabled}
            >
                login
            </SubmitButton>
        </div>
    </form>
    <div class="login_helpers_container">
        <div class="login_helpers_column">
            <h4 class="login_helper_prompt">
                don't have an account?
            </h4>
            <a href="/create-a-client-account">
                <ActionButtonSecondary>
                    create a free account
                </ActionButtonSecondary>
            </a>
        </div>
        <div class="login_helpers_column">
            <h4 class="login_helper_prompt">
                forgot your password?
            </h4>
            <a href="/reset-client-password">
                <ActionButtonSecondary>
                    reset password
                </ActionButtonSecondary>
            </a>
        </div>
    </div>
    <a href="/" class="cancel_button_container">
        <CancelButton>
            cancel
        </CancelButton>
    </a>
</div>

auth.js

import { SvelteKitAuth, CredentialsSignin } from "@auth/sveltekit";
import Credentials from "@auth/core/providers/credentials";
import { AUTH_SECRET } from '$env/static/private';
import { clientAuthentication } from "$lib/server/authentication/client-authentication.js";

// class InvalidLoginError extends CredentialsSignin {
//     code = "invalid email and/or password"
// };

export const { handle, signIn, signOut } = SvelteKitAuth({
    providers: [
        Credentials({
            async authorize(credentials) {
                if (credentials.providerId === "client-login") {
                    // @ts-ignore
                    const response = await clientAuthentication(credentials);
                    if (response === null) {
                        return null;
                    } else if (response) {
                        const responseItem = await response;
                        return responseItem ?? null;
                    };
                } else {
                    return null;
                };
            }
        })
    ],
    secret: AUTH_SECRET,
    debug: true,
    session: {
        // maxAge: 1800, // 30 mins
        strategy: "jwt"
    },
    trustHost: true
});

hooks.server.js

import { redirect } from '@sveltejs/kit';
import { handle as authenticationHandle } from './auth';
import { sequence } from "@sveltejs/kit/hooks";

/** @type {import('@sveltejs/kit').Handle} */
const authorizationHandle = async ({event, resolve}) => {
    const session = await event.locals.auth();
    // redirect users to "/authenticated-client/client" if startsWith("/authenticated-client") is false

    if (
        !event.url.pathname.startsWith("/authenticated-client") &&
        session?.user?.name === "client"
    ) {
        throw redirect(303, "/authenticated-client/client");
    };

    // protect any routes under /authenticated-client

    if (event.url.pathname.startsWith("/authenticated-client")) {
        if (session?.user?.name !== "client") {
            throw redirect(303, "/login-client");
        };
    };

    if (
        !event.url.pathname.startsWith("/authenticated-administrator") &&
        session?.user?.name === "administrator"
    ) {
        throw redirect(303, "/authenticated-administrator/administrator");
    };

    if (event.url.pathname.startsWith("/authenticated-administrator")) {
        if (session?.user?.name !== "administrator") {
            throw redirect(303, "/login-administrator");
        };
    };
    // if still request, proceed as normal
    return await resolve(event);
}

export const handle = sequence(
    authenticationHandle,
    authorizationHandle
)

Expected behavior

The signIn function in login-client+page.svelte should return an object with status = 400 and ok = false if the user submits invalid credentials.

@stephendewyer stephendewyer added bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. labels May 15, 2024
@roberte777
Copy link
Contributor

I am experiencing virtually the exact same issue with the exact same setup, but in the Next.JS codebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.
Projects
None yet
Development

No branches or pull requests

2 participants