fix: Previously provisioned JWT's should be revoked on signout (#3639)

* feat: auth.delete endpoint

* test
This commit is contained in:
Tom Moor
2022-06-07 13:57:17 -07:00
committed by GitHub
parent 0de6650aa5
commit 56393f39b7
5 changed files with 62 additions and 2 deletions

View File

@ -253,6 +253,12 @@ export default class AuthStore {
@action
logout = async (savePath = false) => {
if (!this.token) {
return;
}
client.post(`/auth.delete`);
// remove user and team from localStorage
Storage.set(AUTH_STORE, {
user: null,

View File

@ -1,4 +1,4 @@
import { SaveOptions } from "sequelize";
import type { SaveOptions } from "sequelize";
import {
ForeignKey,
AfterSave,
@ -159,6 +159,7 @@ class Event extends IdModel {
"users.create",
"users.update",
"users.signin",
"users.signout",
"users.promote",
"users.demote",
"users.invite",

View File

@ -48,6 +48,30 @@ describe("#auth.info", () => {
});
});
describe("#auth.delete", () => {
it("should make the access token unusable", async () => {
const user = await buildUser();
const res = await server.post("/api/auth.delete", {
body: {
token: user.getJwtToken(),
},
});
expect(res.status).toEqual(200);
const res2 = await server.post("/api/auth.info", {
body: {
token: user.getJwtToken(),
},
});
expect(res2.status).toEqual(401);
});
it("should require authentication", async () => {
const res = await server.post("/api/auth.delete");
expect(res.status).toEqual(401);
});
});
describe("#auth.config", () => {
it("should return available SSO providers", async () => {
env.DEPLOYMENT = "hosted";

View File

@ -2,9 +2,10 @@ import invariant from "invariant";
import Router from "koa-router";
import { find } from "lodash";
import { parseDomain } from "@shared/utils/domains";
import { sequelize } from "@server/database/sequelize";
import env from "@server/env";
import auth from "@server/middlewares/authentication";
import { Team, TeamDomain } from "@server/models";
import { Event, Team, TeamDomain } from "@server/models";
import { presentUser, presentTeam, presentPolicies } from "@server/presenters";
import ValidateSSOAccessTask from "@server/queues/tasks/ValidateSSOAccessTask";
import providers from "../auth/providers";
@ -125,4 +126,31 @@ router.post("auth.info", auth(), async (ctx) => {
};
});
router.post("auth.delete", auth(), async (ctx) => {
const { user } = ctx.state;
await sequelize.transaction(async (transaction) => {
await user.rotateJwtSecret({ transaction });
await Event.create(
{
name: "users.signout",
actorId: user.id,
userId: user.id,
teamId: user.teamId,
data: {
name: user.name,
},
ip: ctx.request.ip,
},
{
transaction,
}
);
});
ctx.body = {
success: true,
};
});
export default router;

View File

@ -13,6 +13,7 @@ export type UserEvent =
| {
name: "users.create" // eslint-disable-line
| "users.signin"
| "users.signout"
| "users.update"
| "users.suspend"
| "users.activate"