Path: blob/master/src/packages/next/pages/api/v2/auth/sign-in.ts
5994 views
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45/*6Sign in works as follows:781. Query the database for the account_id and password_hash9with the given username.10112. Use the password-hash library to determine whether or12not the given password hashes properly. If so, create and13set a secure remember_me http cookie confirming that the14client is that user and tell user they are now authenticated.15If not, send an error back.16*/17import { Request, Response } from "express";1819import getPool from "@cocalc/database/pool";20import { recordFail, signInCheck } from "@cocalc/server/auth/throttle";21import getParams from "lib/api/get-params";22import { verify } from "password-hash";23import { MAX_PASSWORD_LENGTH } from "@cocalc/util/auth";24import setSignInCookies from "@cocalc/server/auth/set-sign-in-cookies";2526export default async function signIn(req: Request, res: Response) {27let { email, password } = getParams(req);2829email = email.toLowerCase().trim();3031const check: string | undefined = await signInCheck(email, req.ip);32if (check) {33res.json({ error: check });34return;35}36let account_id: string;3738try {39// Don't bother checking reCaptcha for *sign in* for now, since it causes trouble40// when large classes all sign in from one point. Also, it's much less important41// for sign in, than for sign up and payment.42// await reCaptcha(req);43account_id = await getAccount(email, password);44} catch (err) {45res.json({ error: `Problem signing into account -- ${err.message}.` });46recordFail(email, req.ip);47return;48}4950await signUserIn(req, res, account_id);51}5253export async function getAccount(54email_address: string,55password: string,56): Promise<string> {57if (password.length > MAX_PASSWORD_LENGTH) {58throw new Error(59`The password must be shorter than ${MAX_PASSWORD_LENGTH} characters.`,60);61}6263const pool = getPool();64const { rows } = await pool.query(65"SELECT account_id, password_hash, banned FROM accounts WHERE email_address=$1",66[email_address],67);68if (rows.length == 0) {69throw Error(`no account with email address '${email_address}'`);70}71const { account_id, password_hash, banned } = rows[0];72if (banned) {73throw Error(74`'${email_address}' is banned -- if you think this is a mistake, please email [email protected] and explain.`,75);76}77if (!verify(password, password_hash)) {78throw Error(`password for '${email_address}' is incorrect`);79}80return account_id;81}8283export async function signUserIn(84req,85res,86account_id: string,87opts?: { maxAge?: number },88): Promise<void> {89try {90await setSignInCookies({91req,92res,93account_id,94maxAge: opts?.maxAge,95});96} catch (err) {97res.json({ error: `Problem setting auth cookies -- ${err}` });98return;99}100res.json({ account_id });101}102103104