Created
July 29, 2024 22:13
-
-
Save infomiho/baf8330ce3733c64906173b1533f2f45 to your computer and use it in GitHub Desktop.
Custom login API endpoint
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
app apiAuth { | |
wasp: { | |
version: "^0.14.0" | |
}, | |
title: "api-auth", | |
auth: { | |
userEntity: User, | |
onAuthFailedRedirectTo: "/login", | |
onAuthSucceededRedirectTo: "/", | |
methods: { | |
usernameAndPassword: {} | |
} | |
} | |
} | |
route RootRoute { path: "/", to: MainPage } | |
page MainPage { | |
component: import { MainPage } from "@src/MainPage", | |
authRequired: true | |
} | |
route LoginRoute { path: "/login", to: Login } | |
page Login { | |
component: import { LoginPage } from "@src/auth" | |
} | |
route SignupRoute { path: "/signup", to: Signup } | |
page Signup { | |
component: import { SignupPage } from "@src/auth" | |
} | |
api customLogin { | |
httpRoute: (POST, "/api/custom-login"), | |
fn: import { customLogin } from "@src/api", | |
entities: [] | |
} | |
apiNamespace customApiNamespace { | |
middlewareConfigFn: import { getMiddleware } from "@src/api", | |
path: "/api" | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { CustomLogin } from "wasp/server/api"; | |
import { prisma } from "wasp/server"; | |
import { createSession } from "wasp/auth/session"; | |
import { deserializeAndSanitizeProviderData } from "wasp/auth/utils"; | |
import { verifyPassword } from "wasp/auth/password"; | |
import { MiddlewareConfigFn } from "wasp/server/middleware"; | |
type Params = {}; | |
type Response = | |
| { | |
sessionId: string; | |
} | |
| { | |
message: string; | |
}; | |
type Body = { | |
username: string; | |
password: string; | |
}; | |
export const customLogin: CustomLogin<Params, Response, Body> = async ( | |
req, | |
res | |
) => { | |
// 1. Receive username and password - ideally you'd validate this | |
const { username, password } = req.body; | |
// 2. Locate the user by username auth identity | |
const authIdentityWithUser = await prisma.authIdentity.findUnique({ | |
where: { | |
providerName_providerUserId: { | |
providerName: "username", | |
providerUserId: username, | |
}, | |
}, | |
include: { | |
auth: { | |
include: { | |
user: true, | |
}, | |
}, | |
}, | |
}); | |
// 3. If user not found, return 401 | |
if (!authIdentityWithUser) { | |
res.status(401).json({ message: "Invalid username or password" }); | |
return; | |
} | |
// 4. Grab the hashed password from the auth identity | |
const providerData = deserializeAndSanitizeProviderData<"username">( | |
authIdentityWithUser.providerData | |
); | |
try { | |
// 5. Verify the password | |
await verifyPassword(providerData.hashedPassword, password); | |
// 6a. If password verification succeeds, create a session | |
const session = await createSession(authIdentityWithUser.auth.id); | |
// 7. Return the session id - which can be used to authenticate the user in subsequent requests | |
// (by sending it in the Authorization header) | |
return res.json({ sessionId: session.id }); | |
} catch (e) { | |
// 6a. If password verification fails, return 401 | |
res.status(401).json({ message: "Invalid username or password" }); | |
} | |
}; | |
// Setting the default middleware for the /api endpoint | |
// This way we get CORS and JSON parsing out of the box | |
export const getMiddleware: MiddlewareConfigFn = (config) => { | |
// Logger is already applied to the POST /api/custom-login endpoint | |
config.delete("logger"); | |
return config; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment