You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

89 lines
2.8 KiB

import PromiseRouter from "express-promise-router";
import ApiError from "@common/ApiError";
import { ErrorCode } from "@common/ErrorCode";
import * as httpApi from "@common/httpApi";
import * as authentication from "@server/authentication";
import { User } from "@server/entities";
import { verifyAuthorization } from "@server/express/verifyAuthorization";
import { ServerState } from "@server/state";
export function token(state: ServerState) {
const router = PromiseRouter();
async function passwordGrant(
body: httpApi.TokenGrantPasswordRequest,
res: Express.Response
): Promise<User> {
const { username, password } = body;
if (!body || !username || !password) {
throw new ApiError("Must specify username and password");
}
const user = await state.database.users.findByUsername(username);
if (!user) {
throw new ApiError("User does not exist");
}
const passwordMatches = await user.comparePassword(password);
if (passwordMatches) {
return user;
} else {
throw new ApiError("Invalid user credentials");
}
}
async function refreshGrant(
body: httpApi.TokenGrantRefreshRequest,
res: Express.Response
): Promise<User> {
const { refresh_token } = body;
if (!body || !refresh_token) {
throw new ApiError("Must specify a refresh_token", ErrorCode.BadToken);
}
const claims = await authentication.verifyToken(refresh_token);
if (claims.type !== "refresh") {
throw new ApiError("Not a refresh token", ErrorCode.BadToken);
}
const user = await state.database.users.findOne(claims.aud);
if (!user) {
throw new ApiError("User no longer exists", ErrorCode.BadToken);
}
return user;
}
router.post("/grant", async (req, res) => {
const body: httpApi.TokenGrantRequest = req.body;
let user: User;
if (body.grant_type === "password") {
user = await passwordGrant(body, res);
} else if (body.grant_type === "refresh") {
user = await refreshGrant(body, res);
} else {
throw new ApiError("Invalid grant_type");
}
// tslint:disable-next-line:variable-name
const [access_token, refresh_token] = await Promise.all([
await authentication.generateAccessToken(user),
await authentication.generateRefreshToken(user)
]);
const response: httpApi.TokenGrantResponse = {
access_token,
refresh_token
};
res.json(response);
});
router.post("/grant_device_reg", verifyAuthorization(), async (req, res) => {
// tslint:disable-next-line:no-shadowed-variable
const token = await authentication.generateDeviceRegistrationToken();
res.json({ token });
});
router.post("/verify", verifyAuthorization(), async (req, res) => {
res.json({
ok: true,
token: req.token
});
});
return router;
}