Skip to content

Commit

Permalink
Regression: Fix account service login expiration (#24920)
Browse files Browse the repository at this point in the history
  • Loading branch information
sampaiodiego authored Mar 23, 2022
1 parent d2a3537 commit 353ff53
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 26 deletions.
45 changes: 38 additions & 7 deletions ee/server/services/account/Account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const removeSession = async (uid: string, loginToken: string): Promise<void> =>
);
};

const loginViaResume = async (resume: string): Promise<false | ILoginResult> => {
const loginViaResume = async (resume: string, loginExpiration: number): Promise<false | ILoginResult> => {
const Users = await getCollection<IUser>(Collections.User);
const hashedToken = _hashLoginToken(resume);

Expand All @@ -58,8 +58,7 @@ const loginViaResume = async (resume: string): Promise<false | ILoginResult> =>

const { when } = user.services?.resume?.loginTokens?.find((token) => token.hashedToken === hashedToken) || {};

const tokenExpires = when && _tokenExpiration(when);

const tokenExpires = when && _tokenExpiration(when, loginExpiration);
if (tokenExpires && new Date() >= tokenExpires) {
throw new MeteorError(403, 'Your session has expired. Please log in again.');
}
Expand All @@ -73,7 +72,11 @@ const loginViaResume = async (resume: string): Promise<false | ILoginResult> =>
};
};

const loginViaUsername = async ({ username }: { username: string }, password: string): Promise<false | ILoginResult> => {
const loginViaUsername = async (
{ username }: { username: string },
password: string,
loginExpiration: number,
): Promise<false | ILoginResult> => {
const Users = await getCollection<IUser>(Collections.User);
const user = await Users.findOne<IUser>({ username }, { projection: { 'services.password.bcrypt': 1 } });
if (!user) {
Expand All @@ -95,21 +98,40 @@ const loginViaUsername = async ({ username }: { username: string }, password: st
uid: user._id,
token: newToken.token,
hashedToken: hashedToken.hashedToken,
tokenExpires: _tokenExpiration(newToken.when),
tokenExpires: _tokenExpiration(newToken.when, loginExpiration),
type: 'password',
};
};

export class Account extends ServiceClass implements IAccount {
protected name = 'accounts';

private loginExpiration = 90;

constructor() {
super();

this.onEvent('watch.settings', async ({ clientAction, setting }): Promise<void> => {
if (clientAction === 'removed') {
return;
}
const { _id, value } = setting;
if (_id !== 'Accounts_LoginExpiration') {
return;
}
if (typeof value === 'number') {
this.loginExpiration = value;
}
});
}

async login({ resume, user, password }: { resume: string; user: { username: string }; password: string }): Promise<false | ILoginResult> {
if (resume) {
return loginViaResume(resume);
return loginViaResume(resume, this.loginExpiration);
}

if (user && password) {
return loginViaUsername(user, password);
return loginViaUsername(user, password, this.loginExpiration);
}

return false;
Expand All @@ -118,4 +140,13 @@ export class Account extends ServiceClass implements IAccount {
async logout({ userId, token }: { userId: string; token: string }): Promise<void> {
return removeSession(userId, token);
}

async started(): Promise<void> {
const Settings = await getCollection<any>(Collections.Settings);

const expiry = await Settings.findOne({ _id: 'Accounts_LoginExpiration' }, { projection: { value: 1 } });
if (expiry?.value) {
this.loginExpiration = expiry.value;
}
}
}
4 changes: 2 additions & 2 deletions ee/server/services/account/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ export const _hashStampedToken = (stampedToken: IStampedToken): IHashedStampedTo
export const validatePassword = (password: string, bcryptPassword: string): Promise<boolean> =>
bcrypt.compare(getPassword(password), bcryptPassword);

const expiryDaysInMS = 15 * 60 * 60 * 24 * 1000;
export const _tokenExpiration = (when: string | Date): Date => new Date(new Date(when).getTime() + expiryDaysInMS);
export const _tokenExpiration = (when: string | Date, expirationInDays: number): Date =>
new Date(new Date(when).getTime() + expirationInDays * 60 * 60 * 24 * 1000);
38 changes: 21 additions & 17 deletions ee/server/services/ddp-streamer/configureServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,24 +65,28 @@ server.publish(autoUpdateCollection, function () {

server.methods({
async 'login'({ resume, user, password }: { resume: string; user: { username: string }; password: string }) {
const result = await Account.login({ resume, user, password });
if (!result) {
throw new MeteorError(403, "You've been logged out by the server. Please log in again");
try {
const result = await Account.login({ resume, user, password });
if (!result) {
throw new MeteorError(403, "You've been logged out by the server. Please log in again");
}

this.userId = result.uid;
this.userToken = result.hashedToken;

this.emit(DDP_EVENTS.LOGGED);

server.emit(DDP_EVENTS.LOGGED, this);

return {
id: result.uid,
token: result.token,
tokenExpires: result.tokenExpires,
type: result.type,
};
} catch (error) {
throw error;
}

this.userId = result.uid;
this.userToken = result.hashedToken;

this.emit(DDP_EVENTS.LOGGED);

server.emit(DDP_EVENTS.LOGGED, this);

return {
id: result.uid,
token: result.token,
tokenExpires: result.tokenExpires,
type: result.type,
};
},
async 'logout'() {
if (this.userToken && this.userId) {
Expand Down

0 comments on commit 353ff53

Please sign in to comment.