lucia-auth / lucia

Authentication, simple and clean
https://lucia-auth.com
BSD Zero Clause License
9.47k stars 486 forks source link

GetUserAttributes does not return data #1718

Closed Antc1993 closed 3 hours ago

Antc1993 commented 4 hours ago

Hello, I can't get the data I need for example username My config is Astro + D1 cloudflare + Lucia auth

Auth.js


import { Lucia } from "lucia";
import { D1Adapter } from "@lucia-auth/adapter-sqlite";
import { GitHub, Google } from "arctic";

export function initializeLucia(D1: D1Database) {
    const adapter = new D1Adapter(D1, {
        user: "user",
        session: "user_session",

    });
    return new Lucia(adapter,

        {
            sessionCookie: {
                attributes: {
                    secure: true,
                },
            },

            getUserAttributes: (attributes) => {
                console.log("user", attributes)
                return {
                    username: attributes.username,
                                       github_id: attributes.github_id
                };
            },
            getSessionAttributes: (attributes) =>{
                console.log("session", attributes)
                return {
                    expiresAt: attributes.expires_at
                };
            }

        });
}

declare module "lucia" {
    interface Register {
        Lucia: ReturnType<typeof initializeLucia>;
        DatabaseUserAttributes: DatabaseUserAttributes;
        DatabaseSessionAttributes: DatabaseSessionAttributes;
    }   
}

interface DatabaseUserAttributes {
    username: string;
    github_id: number;
}

interface DatabaseSessionAttributes {
    expires_at: BigInt;

}

export const github = new GitHub(
    import.meta.env.GITHUB_CLIENT_ID,
    import.meta.env.GITHUB_CLIENT_SECRET
);

export const google = new Google(
    import.meta.env.GOOGLE_CLIENT_ID,
    import.meta.env.GOOGLE_CLIENT_SECRET,
    "http://127.0.0.1:8788/login/auth/google/callback/"
);

Only get this in index.astro

const user = Astro.locals.user;

 console.log(user)

{
  expiresAt: 2024-11-21T01:18:39.000Z,
  id: 'asdasdwawd212312asdasdasdasd2',
  userId: 'asdwasdas2asd2',
  fresh: false
}

-- Migration number: 0001 2024-10-21T20:30:25.057Z DROP TABLE IF EXISTS user; CREATE TABLE IF NOT EXISTS user ( id text NOT NULL DEFAULT '', name text (256) DEFAULT NULL, email TEXT (256) DEFAULT NULL UNIQUE, emailVerified datetime DEFAULT NULL, image text DEFAULT NULL, hashed_password TEXT, username TEXT (256) UNIQUE, github_id NUMERIC UNIQUE, PRIMARY KEY (id));

-- Table: user_session DROP TABLE IF EXISTS user_session; CREATE TABLE IF NOT EXISTS user_session ( id VARCHAR (127) NOT NULL PRIMARY KEY, user_id VARCHAR (15) NOT NULL, expires_at BIGINT NOT NULL, FOREIGN KEY (user_id) REFERENCES user (id));

Antc1993 commented 3 hours ago
getUserAttributes: (attributes) => {
                console.log("user", attributes)
                return {
                    username: attributes.username,
                                       github_id: attributes.github_id
                };
            },

this show me user { name: null, email: null, emailVerified: null, image: null, hashed_password: null, username: 'Antc1993', github_id: 1231231 }

pilcrowonpaper commented 3 hours ago

How are you populating Astro.locals.user? You're probably mixing up session and users

Antc1993 commented 1 hour ago

This is callback from github

import { OAuth2RequestError } from "arctic";
import { generateId } from "lucia";
import { github, initializeLucia } from "../../../../../lib/auth";
import type { APIRoute, APIContext } from "astro";

export const GET: APIRoute = async (context: APIContext) => {

    const code = context.url.searchParams.get("code");
    const state = context.url.searchParams.get("state");
    const storedState = context.cookies.get("github_oauth_state")?.value ?? null;;

    if (!code || !state || !storedState || state !== storedState) {
        return new Response(null, {
            status: 400
        });
    }

    try {
        const tokens = await github.validateAuthorizationCode(code);
        let test = tokens.accessToken
        let headersList = {
            "Authorization": "Bearer " + test,
            "User-Agent": "Test-lucia-auth"
        }
        const githubUserResponse = await fetch("https://api.github.com/user", {
            method: "GET",
            headers: headersList
        });

        const githubUser  = await githubUserResponse.json();
        console.log(githubUser)
        const db = context.locals.runtime.env.DB
        const lucia = initializeLucia(db);

        const existingUser = await db.prepare("SELECT id FROM user WHERE github_id=?1").bind(githubUser.id).first()

        if (existingUser) {

            const session = await lucia.createSession(existingUser.id, {});
            const sessionCookie = lucia.createSessionCookie(session.id);

            context.cookies.set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
            return context.redirect("/", 302)
        }
        const userId = generateId(15);

        const resultInsert = await db.prepare("INSERT INTO user(id, github_id, username) VALUES(?1, ?2, ?3)")
            .bind(userId, githubUser.id, githubUser.login)
            .run()

        const session = await lucia.createSession(userId, {});
        const sessionCookie = lucia.createSessionCookie(session.id);
        context.cookies.set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);

        return context.redirect("/", 302)
    } catch (e) {
        // the specific error message depends on the provider
        if (e instanceof OAuth2RequestError) {
            // invalid code
            return new Response(e.message, {
                status: 400
            });
        }
        console.log(e.message)
        return new Response(e.message, {
            status: 500
        });
    }
}

interface GitHubUser {
    id: number;
    login: string;
}

Middleware

import { initializeLucia } from "../src/lib/auth";
import { defineMiddleware } from "astro:middleware";
export const onRequest = defineMiddleware(async (context, next) => {
    const lucia = initializeLucia(context.locals.runtime.env.DB)
    const sessionId = context.cookies.get(lucia.sessionCookieName)?.value ?? null;

    if (!sessionId) {
        context.locals.user = null;
        context.locals.session = null;
        return next();
    }

    const { session, user } = await lucia.validateSession(sessionId);
    if (session && session.fresh) {
        const sessionCookie = lucia.createSessionCookie(session.id);
        context.cookies.set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
    }
    if (!session) {
        const sessionCookie = lucia.createBlankSessionCookie();
        context.cookies.set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
    }
    context.locals.user = user;
    context.locals.user = session;
    return next();
});