Merge pull request #1095 from gradido/login_call_unsecureLogin

Login call unsecure login
This commit is contained in:
Hannes Heine 2021-11-22 22:40:28 +01:00 committed by GitHub
commit c863501029
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 78 additions and 42 deletions

View File

@ -51,7 +51,6 @@ const email = {
EMAIL_PASSWORD: process.env.EMAIL_PASSWORD || 'xxx',
EMAIL_SMTP_URL: process.env.EMAIL_SMTP_URL || 'gmail.com',
EMAIL_SMTP_PORT: process.env.EMAIL_SMTP_PORT || '587',
EMAIL_LINK_VERIFICATION:
process.env.EMAIL_LINK_VERIFICATION || 'http://localhost/vue/checkEmail/$1',
}

View File

@ -2,9 +2,6 @@
import { AuthChecker } from 'type-graphql'
import CONFIG from '../../config'
import { apiGet } from '../../apis/HttpRequest'
import decode from '../../jwt/decode'
import encode from '../../jwt/encode'
@ -13,7 +10,7 @@ const isAuthorized: AuthChecker<any> = async (
) => {
if (context.token) {
const decoded = decode(context.token)
context.pubKey = decoded.pubKey
context.pubKey = Buffer.from(decoded.pubKey).toString('hex')
context.setHeaders.push({ key: 'token', value: encode(decoded.pubKey) })
return true
}

View File

@ -10,15 +10,17 @@ export class User {
@PrimaryGeneratedColumn()
id: number
*/
constructor(json: any) {
this.email = json.email
this.firstName = json.first_name
this.lastName = json.last_name
this.username = json.username
this.description = json.description
this.pubkey = json.public_hex
this.language = json.language
this.publisherId = json.publisher_id
constructor(json?: any) {
if (json) {
this.email = json.email
this.firstName = json.first_name
this.lastName = json.last_name
this.username = json.username
this.description = json.description
this.pubkey = json.public_hex
this.language = json.language
this.publisherId = json.publisher_id
}
}
@Field(() => String)

View File

@ -22,14 +22,14 @@ import {
} from '../../middleware/klicktippMiddleware'
import { CheckEmailResponse } from '../model/CheckEmailResponse'
import { UserSettingRepository } from '../../typeorm/repository/UserSettingRepository'
import { LoginUserRepository } from '../../typeorm/repository/LoginUser'
import { Setting } from '../enum/Setting'
import { UserRepository } from '../../typeorm/repository/User'
import { LoginUser } from '@entity/LoginUser'
import { LoginElopageBuys } from '@entity/LoginElopageBuys'
import { LoginUserBackup } from '@entity/LoginUserBackup'
import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
import { sendEMail } from '../../util/sendEMail'
import { LoginUserRepository } from '../../typeorm/repository/LoginUser'
import { LoginElopageBuysRepository } from '../../typeorm/repository/LoginElopageBuys'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const sodium = require('sodium-native')
@ -201,33 +201,32 @@ export class UserResolver {
@Ctx() context: any,
): Promise<User> {
email = email.trim().toLowerCase()
const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password })
// if there is no user, throw an authentication error
if (!result.success) {
throw new Error(result.data)
}
context.setHeaders.push({
key: 'token',
value: encode(result.data.user.public_hex),
// const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password })
// UnsecureLogin
const loginUserRepository = getCustomRepository(LoginUserRepository)
const loginUser = await loginUserRepository.findByEmail(email).catch(() => {
throw new Error('No user with this credentials')
})
const user = new User(result.data.user)
// Hack: Database Field is not validated properly and not nullable
if (user.publisherId === 0) {
user.publisherId = undefined
const passwordHash = SecretKeyCryptographyCreateKey(email, password) // return short and long hash
const loginUserPassword = BigInt(loginUser.password.toString())
if (loginUserPassword !== passwordHash[0].readBigUInt64LE()) {
throw new Error('No user with this credentials')
}
user.hasElopage = result.data.hasElopage
// read additional settings from settings table
// TODO: If user has no pubKey Create it again and update user.
const userRepository = getCustomRepository(UserRepository)
let userEntity: void | DbUser
userEntity = await userRepository.findByPubkeyHex(user.pubkey).catch(() => {
const loginUserPubKey = loginUser.pubKey
const loginUserPubKeyString = loginUserPubKey.toString('hex')
userEntity = await userRepository.findByPubkeyHex(loginUserPubKeyString).catch(() => {
// User not stored in state_users
// TODO: Check with production data - email is unique which can cause problems
userEntity = new DbUser()
userEntity.firstName = user.firstName
userEntity.lastName = user.lastName
userEntity.username = user.username
userEntity.email = user.email
userEntity.pubkey = Buffer.from(user.pubkey, 'hex')
userEntity.firstName = loginUser.firstName
userEntity.lastName = loginUser.lastName
userEntity.username = loginUser.username
userEntity.email = loginUser.email
userEntity.pubkey = loginUser.pubKey
userRepository.save(userEntity).catch(() => {
throw new Error('error by save userEntity')
@ -237,16 +236,28 @@ export class UserResolver {
throw new Error('error with cannot happen')
}
// Save publisherId if Elopage is not yet registered
const user = new User()
user.email = email
user.firstName = loginUser.firstName
user.lastName = loginUser.lastName
user.username = loginUser.username
user.description = loginUser.description
user.pubkey = loginUserPubKeyString
user.language = loginUser.language
// Elopage Status & Stored PublisherId
user.hasElopage = await this.hasElopage({ pubKey: loginUserPubKeyString })
if (!user.hasElopage && publisherId) {
user.publisherId = publisherId
// TODO: Check if we can use updateUserInfos
// await this.updateUserInfos({ publisherId }, { pubKey: loginUser.pubKey })
const loginUserRepository = getCustomRepository(LoginUserRepository)
const loginUser = await loginUserRepository.findOneOrFail({ email: userEntity.email })
loginUser.publisherId = publisherId
loginUserRepository.save(loginUser)
}
// coinAnimation
const userSettingRepository = getCustomRepository(UserSettingRepository)
const coinanimation = await userSettingRepository
.readBoolean(userEntity.id, Setting.COIN_ANIMATION)
@ -254,6 +265,12 @@ export class UserResolver {
throw new Error(error)
})
user.coinanimation = coinanimation
context.setHeaders.push({
key: 'token',
value: encode(loginUser.pubKey),
})
return user
}
@ -609,7 +626,8 @@ export class UserResolver {
return false
}
const elopageBuyCount = await LoginElopageBuys.count({ payerEmail: userEntity.email })
const loginElopageBuysRepository = getCustomRepository(LoginElopageBuysRepository)
const elopageBuyCount = await loginElopageBuysRepository.count({ payerEmail: userEntity.email })
return elopageBuyCount > 0
}
}

View File

@ -0,0 +1,5 @@
import { EntityRepository, Repository } from 'typeorm'
import { LoginElopageBuys } from '@entity/LoginElopageBuys'
@EntityRepository(LoginElopageBuys)
export class LoginElopageBuysRepository extends Repository<LoginElopageBuys> {}

View File

@ -2,4 +2,10 @@ import { EntityRepository, Repository } from 'typeorm'
import { LoginUser } from '@entity/LoginUser'
@EntityRepository(LoginUser)
export class LoginUserRepository extends Repository<LoginUser> {}
export class LoginUserRepository extends Repository<LoginUser> {
async findByEmail(email: string): Promise<LoginUser> {
return this.createQueryBuilder('loginUser')
.where('loginUser.email = :email', { email })
.getOneOrFail()
}
}

View File

@ -9,6 +9,15 @@ export class UserRepository extends Repository<User> {
.getOneOrFail()
}
async findByPubkeyHexBuffer(pubkeyHexBuffer: Buffer): Promise<User> {
const pubKeyString = pubkeyHexBuffer.toString('hex')
return await this.findByPubkeyHex(pubKeyString)
}
async findByEmail(email: string): Promise<User> {
return this.createQueryBuilder('user').where('user.email = :email', { email }).getOneOrFail()
}
async getUsersIndiced(userIds: number[]): Promise<User[]> {
if (!userIds.length) return []
const users = await this.createQueryBuilder('user')