Files
outline/server/queues/tasks/ValidateSSOAccessTask.ts
Tom Moor 728790e38f feat: Validate Google, Azure, OIDC SSO access (#3590)
* chore: Store expiresAt on UserAuthentications. This represents the time that the accessToken is no longer valid and should be exchanged using the refreshToken

* feat: Check and expire Google SSO

* fix: Better handling of multiple auth methods
Added more docs

* fix: Retry access validation with network errors

* Small refactor, add Azure token validation support

* doc

* test

* lint

* OIDC refresh support

* CheckSSOAccessTask -> ValidateSSOAccessTask
Added lastValidatedAt column
Skip checks if validated within 5min
Some edge cases around encrypted columns
2022-06-05 13:18:51 -07:00

56 lines
1.5 KiB
TypeScript

import { sequelize } from "@server/database/sequelize";
import Logger from "@server/logging/Logger";
import { User, UserAuthentication } from "@server/models";
import BaseTask, { TaskPriority } from "./BaseTask";
type Props = {
userId: string;
};
export default class ValidateSSOAccessTask extends BaseTask<Props> {
public async perform({ userId }: Props) {
await sequelize.transaction(async (transaction) => {
const userAuthentications = await UserAuthentication.findAll({
where: { userId },
transaction,
lock: transaction.LOCK.UPDATE,
});
if (userAuthentications.length === 0) {
return;
}
// Check the validity of all the user's associated authentications.
const valid = await Promise.all(
userAuthentications.map(async (authentication) =>
authentication.validateAccess({ transaction })
)
);
// If any are valid then we're done here.
if (valid.includes(true)) {
return;
}
// If all are invalid then we need to revoke the users Outline sessions.
const user = await User.findByPk(userId, {
transaction,
lock: transaction.LOCK.UPDATE,
});
Logger.info(
"task",
`Authentication token no longer valid for ${user?.id}`
);
await user?.rotateJwtSecret({ transaction });
});
}
public get options() {
return {
attempts: 2,
priority: TaskPriority.Background,
};
}
}