From 120ea335470ee23ca98429d8836cc97f1e431b3e Mon Sep 17 00:00:00 2001 From: Jonas Lochmann Date: Mon, 18 Mar 2024 01:00:00 +0100 Subject: [PATCH] Add user agent info to login code mail headers --- src/api/auth.ts | 9 ++++++-- src/function/authentication/login-by-mail.ts | 8 ++++--- src/util/mail.ts | 22 ++++++++++++++------ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/api/auth.ts b/src/api/auth.ts index ae13b7e..f70fb17 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2021 Jonas Lochmann + * Copyright (C) 2019 - 2024 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -30,6 +30,10 @@ export const createAuthRouter = (database: Database) => { const router = Router() router.post('/send-mail-login-code-v2', json(), async (req, res, next) => { + const info = { + ua: req.headers['user-agent'] + } + try { if (!isSendMailLoginCodeRequest(req.body)) { throw new BadRequest() @@ -50,7 +54,8 @@ export const createAuthRouter = (database: Database) => { mail, deviceAuthToken: req.body.deviceAuthToken, locale: req.body.locale, - database + database, + info: Buffer.from(JSON.stringify(info), 'utf8') }) res.json({ mailLoginToken }) diff --git a/src/function/authentication/login-by-mail.ts b/src/function/authentication/login-by-mail.ts index c36be68..88f7b21 100644 --- a/src/function/authentication/login-by-mail.ts +++ b/src/function/authentication/login-by-mail.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2023 Jonas Lochmann + * Copyright (C) 2019 - 2024 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -23,11 +23,12 @@ import { checkMailSendLimit } from '../../util/ratelimit-authmail' import { generateAuthToken } from '../../util/token' import { createAuthTokenByMailAddress } from './index' -export const sendLoginCode = async ({ mail, deviceAuthToken, locale, database }: { +export const sendLoginCode = async ({ mail, deviceAuthToken, locale, database, info }: { mail: string deviceAuthToken?: string locale: string database: Database + info: Buffer // no transaction here because this is directly called from an API endpoint }): Promise<{ mailLoginToken: string }> => { let deviceName = null @@ -82,7 +83,8 @@ export const sendLoginCode = async ({ mail, deviceAuthToken, locale, database }: receiver: mail, code, locale, - deviceName + deviceName, + info }) await database.transaction(async (transaction) => { diff --git a/src/util/mail.ts b/src/util/mail.ts index 02e7e7a..4087e4a 100644 --- a/src/util/mail.ts +++ b/src/util/mail.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2023 Jonas Lochmann + * Copyright (C) 2019 - 2024 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -45,9 +45,10 @@ function createMailTemplateSender (templateName: string) { const textTemplate = compileTemplate('text.ejs') const htmlTemplate = compileTemplate('html.ejs') - const sendMail = async ({ receiver, params }: { + const sendMail = async ({ receiver, params, info }: { receiver: string params: object + info?: Buffer }) => { if (!mailTransport) { throw new Error('can not send mails without mail config and without NODE_ENV=development') @@ -56,6 +57,9 @@ function createMailTemplateSender (templateName: string) { const subject = subjectTemplate(params).replace(/\n/g, ' ') const text = textTemplate(params) const html = htmlTemplate(params) + const headers: {[key: string]: string} = info ? { + 'X-TlInfo': info.toString('base64') + } : {} await new Promise((resolve, reject) => { mailTransport.sendMail({ @@ -63,7 +67,8 @@ function createMailTemplateSender (templateName: string) { to: receiver, subject, text, - html + html, + headers }, (err, info) => { if (err) { reject(err) @@ -90,9 +95,13 @@ function createMailTemplateSender (templateName: string) { const loginMailSender = createMailTemplateSender('login') export const sendAuthenticationMail = async ({ - receiver, code, locale, deviceName + receiver, code, locale, deviceName, info }: { - receiver: string, code: string, locale: string, deviceName: string | null + receiver: string + code: string + locale: string + deviceName: string | null + info: Buffer }) => { await loginMailSender.sendMail({ receiver, @@ -105,7 +114,8 @@ export const sendAuthenticationMail = async ({ deviceName, deviceNameIntro: locale === 'de' ? 'Die Anmeldung wurde am Gerät' : 'The login was attempted at the device', deviceNameOutro: locale === 'de' ? 'versucht.' : '.' - } + }, + info }) }