-
Notifications
You must be signed in to change notification settings - Fork 20
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
Lucia cookie example? #665
Comments
This is what I'm doing, and it seems to work. Not sure if it is the right approach. This is my api-definition for the login endpoint: Api.addEndpoint(
pipe(
Api.post("login", "/api/login"),
Api.setRequestBody(Schema.Array(ExternalExpense)),
Api.setRequestBody(LoginPayload),
Api.setResponseHeaders(
Schema.Struct({
"Set-Cookie": Schema.String,
})
)
)
) And here is the handler: RouterBuilder.handle("login", ({ body: { email, password } }) =>
Effect.gen(function* (_) {
const user = yield* UserService.login(email, password);
yield* Effect.logDebug("User logged in: ", user);
const lucia = yield* CookieService;
const session = yield* lucia.getUserSessions(user.id).pipe(
Effect.tap((sessions) =>
Effect.logDebug("User has sessions: ", sessions.length)
),
Effect.flatMap(A.head),
Effect.mapError(() => lucia.createSession(user.id, user))
);
const sessionCookie = lucia.createSessionCookie(session.id);
return yield* Effect.succeed({
status: 200,
headers: { "Set-Cookie": sessionCookie.serialize() },
} as const);
}).pipe(
Effect.catchTags({
UserNotFound: () =>
Effect.gen(function* (_) {
yield* Effect.logWarning("User not found", { email });
return yield* HttpError.unauthorized("Unauthorized");
}),
InvalidPassword: () =>
Effect.gen(function* (_) {
yield* Effect.logWarning("Invalid password", { email });
return yield* HttpError.unauthorized("Unauthorized");
}),
}),
Effect.withLogSpan("/api/login")
)
),
RouterBuilder.build
); The CookieService is just a wrapper around lucia. |
So, here is my approach to the cookie security: const cookie = pipe(
HttpServerRequest.schemaCookies(
Schema.Struct({ auth_session: Schema.String })
),
Effect.mapError(() =>
HttpError.unauthorized('Expected valid "auth_session" header')
),
Effect.flatMap((obj) =>
Effect.gen(function* (_) {
const x = yield* HttpServerRequest.schemaHeaders(
Schema.Struct({ origin: Schema.String, host: Schema.String })
);
const cookieService = yield* CookieService;
console.log(verifyRequestOrigin(x.origin, [x.host]));
yield* Effect.logDebug("Handling cookie security");
const session = yield* cookieService.validateSession(obj.auth_session);
if (!session.session) {
yield* Effect.logDebug("Invalid or expired session, clearing cookie");
return yield* HttpError.unauthorized("Unauthorized", {
headers: pipe(
Headers.empty,
Headers.set(
"Set-Cookie",
cookieService.lucia.createBlankSessionCookie().serialize()
)
),
});
}
if (session.session.fresh) {
/*
TODO: handle fresh session
return HttpServerResponse.empty().pipe(
HttpServerResponse.setCookie("session", session.session.id)
);
*/
}
return session.user;
})
)
);
export const cookieSecurity = Security.make(cookie, {
session: {
name: "auth_session",
type: "cookie",
in: "cookie",
},
}); As you can see, I'm still missing the ability to intercept the response and set additional headers to update the session cookie in case is needed. Is this a limitation of how security is supposed to be used? |
Hello again, donyou have an example of how to use Lucia with effect-http? I want to set the values Lucia returns from the createCookie method, wich has a name, value and attributes. Http platform has a function that almost marches this signature, but I don't know how to make it work with effect-http.
I also saw a todo comment on the security for the cookie auth, so an example for that will also be very appreciated.
Thank you!
The text was updated successfully, but these errors were encountered: