Browse Source

FEATURE | block ip if 2 many auth attemts

merge-requests/16/head
andrew_bashliy 3 years ago
parent
commit
fa8c9353ac
  1. 4
      src/core/namespaces/users.namespace.ts
  2. 21
      src/domain/users/services/users-auth.service.ts
  3. 9
      src/domain/users/services/users-confirmation-codes.service.ts
  4. 6
      src/rest/admin/auth/controllers/admin-auth.controller.ts
  5. 3
      src/rest/admin/auth/services/admin-auth.service.ts
  6. 10
      src/rest/app/auth/controllers/app-auth.controller.ts
  7. 8
      src/rest/app/auth/services/app-auth.service.ts

4
src/core/namespaces/users.namespace.ts

@ -135,6 +135,7 @@ export namespace Users { @@ -135,6 +135,7 @@ export namespace Users {
phoneNumber: string
deviceName: string
type: Sessions.SessionType
ip?: string
}
export interface ILoginWithPasswordPayload {
@ -143,6 +144,7 @@ export namespace Users { @@ -143,6 +144,7 @@ export namespace Users {
deviceName: string
type: Sessions.SessionType
role?: Role
ip: string
}
export interface IUsersAuthService {
@ -171,7 +173,7 @@ export namespace Users { @@ -171,7 +173,7 @@ export namespace Users {
* @param {string} code - Код
* @returns Повертає true, якщо код правильний
*/
checkCode(phoneNumber: string, code: string): Promise<boolean>
checkCode(phoneNumber: string, code: string, ip?: string): Promise<boolean>
loginWithPassword(payload: ILoginWithPasswordPayload): Promise<Sessions.ISession>
}

21
src/domain/users/services/users-auth.service.ts

@ -4,6 +4,7 @@ import { SESSIONS_SERVICE } from 'src/core/consts' @@ -4,6 +4,7 @@ import { SESSIONS_SERVICE } from 'src/core/consts'
import { InvalidCredentialsException } from 'src/shared'
import { USERS_REPOSITORY } from '../consts'
import { IUsersRepository } from '../interfaces'
import { UsersAuthAttemptionsService } from './users-auth-attemptions.service'
import { UsersConfirmationCodesService } from './users-confirmation-codes.service'
import { UsersPasswordsService } from './users-passwords.service'
@ -14,6 +15,7 @@ export class UsersAuthService implements Users.IUsersAuthService { @@ -14,6 +15,7 @@ export class UsersAuthService implements Users.IUsersAuthService {
@Inject(SESSIONS_SERVICE) private readonly sessionsService: Sessions.ISessionsService,
private readonly confirmationCodesService: UsersConfirmationCodesService,
private readonly passwordsService: UsersPasswordsService,
private readonly authAttemptionsService: UsersAuthAttemptionsService,
) {}
public async sendConfirmationCode(phoneNumber: string) {
@ -21,7 +23,11 @@ export class UsersAuthService implements Users.IUsersAuthService { @@ -21,7 +23,11 @@ export class UsersAuthService implements Users.IUsersAuthService {
}
public async confirmLoginCode(payload: Users.IConfirmCodePayload) {
await this.confirmationCodesService.confirmCode(payload.phoneNumber, payload.code)
await this.confirmationCodesService.confirmCode(
payload.phoneNumber,
payload.code,
payload.ip,
)
const user = await this.usersRepository.findOne({ phoneNumber: payload.phoneNumber })
@ -33,8 +39,12 @@ export class UsersAuthService implements Users.IUsersAuthService { @@ -33,8 +39,12 @@ export class UsersAuthService implements Users.IUsersAuthService {
})
}
public async checkCode(phoneNumber: string, code: string) {
return await this.confirmationCodesService.compareCode(phoneNumber, code)
public async checkCode(phoneNumber: string, code: string, ip?: string) {
const isCorrect = await this.confirmationCodesService.compareCode(phoneNumber, code)
if (!isCorrect) await this.authAttemptionsService.add(ip)
return isCorrect
}
public async loginWithPassword(payload: Users.ILoginWithPasswordPayload) {
@ -48,7 +58,10 @@ export class UsersAuthService implements Users.IUsersAuthService { @@ -48,7 +58,10 @@ export class UsersAuthService implements Users.IUsersAuthService {
payload.password,
)
if (!isCorrect) throw new InvalidCredentialsException()
if (!isCorrect) {
await this.authAttemptionsService.add(payload.ip)
throw new InvalidCredentialsException()
}
return await this.sessionsService.start({
userId: user.id,

9
src/domain/users/services/users-confirmation-codes.service.ts

@ -4,6 +4,7 @@ import { Sms, Users } from 'src/core' @@ -4,6 +4,7 @@ import { Sms, Users } from 'src/core'
import { SMS_SERVICE, USERS_SERVICE } from 'src/core/consts'
import { RedisService } from 'src/libs'
import { InvalidCredentialsException, WrongCodeException } from 'src/shared'
import { UsersAuthAttemptionsService } from './users-auth-attemptions.service'
@Injectable()
export class UsersConfirmationCodesService {
@ -12,6 +13,7 @@ export class UsersConfirmationCodesService { @@ -12,6 +13,7 @@ export class UsersConfirmationCodesService {
@Inject(SMS_SERVICE)
private readonly smsService: Sms.ISmsService,
@Inject(USERS_SERVICE) private readonly usersService: Users.IUsersService,
private readonly authAttemptionsService: UsersAuthAttemptionsService,
) {}
public async sendConfirmationCode(phoneNumber: string) {
@ -33,9 +35,12 @@ export class UsersConfirmationCodesService { @@ -33,9 +35,12 @@ export class UsersConfirmationCodesService {
await this.redisService.set(phoneNumber, code)
}
public async confirmCode(phoneNumber: string, code: string) {
public async confirmCode(phoneNumber: string, code: string, ip?: string) {
const isCorrect = await this.compareCode(phoneNumber, code)
if (!isCorrect) throw new WrongCodeException()
if (!isCorrect) {
await this.authAttemptionsService.add(ip)
throw new WrongCodeException()
}
await this.deleteCode(phoneNumber)

6
src/rest/admin/auth/controllers/admin-auth.controller.ts

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { Body, Controller, Post } from '@nestjs/common'
import { Body, Controller, Ip, Post } from '@nestjs/common'
import { ApiBody, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'
import { AdminLoginDto, TokenPairDto } from '../dto'
import { AdminAuthService } from '../services'
@ -16,7 +16,7 @@ export class AdminAuthController { @@ -16,7 +16,7 @@ export class AdminAuthController {
type: TokenPairDto,
})
@Post()
public async login(@Body() dto: AdminLoginDto) {
return await this.adminAuthService.signIn(dto)
public async login(@Ip() ip: string, @Body() dto: AdminLoginDto) {
return await this.adminAuthService.signIn(ip, dto)
}
}

3
src/rest/admin/auth/services/admin-auth.service.ts

@ -9,10 +9,11 @@ export class AdminAuthService { @@ -9,10 +9,11 @@ export class AdminAuthService {
@Inject(USERS_AUTH_SERVICE) private readonly usersAuthService: Users.IUsersAuthService,
) {}
public async signIn(dto: AdminLoginDto) {
public async signIn(ip: string, dto: AdminLoginDto) {
const session = await this.usersAuthService.loginWithPassword({
...dto,
role: Users.Role.Admin,
ip,
})
if (session) return { accessToken: session.accessToken, refreshToken: session.refreshToken }

10
src/rest/app/auth/controllers/app-auth.controller.ts

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { Body, Controller, Post } from '@nestjs/common'
import { Body, Controller, Ip, Post } from '@nestjs/common'
import { ApiBody, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'
import { AuthGuard } from 'src/domain/sessions/decorators'
import { ConfirmLoginCodePayloadDto, LoginPayloadDto, LogoutPayloadDto, TokenPairDto } from '../dto'
@ -37,8 +37,8 @@ export class AppAuthController { @@ -37,8 +37,8 @@ export class AppAuthController {
type: TokenPairDto,
})
@Post('confirm-code')
public async confirmCode(@Body() dto: ConfirmLoginCodePayloadDto) {
return await this.appAuthService.confirmCode(dto)
public async confirmCode(@Ip() ip: string, @Body() dto: ConfirmLoginCodePayloadDto) {
return await this.appAuthService.confirmCode(ip, dto)
}
@ApiOperation({ summary: 'Перевірка коду' })
@ -47,7 +47,7 @@ export class AppAuthController { @@ -47,7 +47,7 @@ export class AppAuthController {
type: Boolean,
})
@Post('check-code')
public async checkCode(@Body() dto: CheckCodePayloadDto) {
return await this.appAuthService.checkCode(dto)
public async checkCode(@Ip() ip: string, @Body() dto: CheckCodePayloadDto) {
return await this.appAuthService.checkCode(ip, dto)
}
}

8
src/rest/app/auth/services/app-auth.service.ts

@ -14,8 +14,8 @@ export class AppAuthService { @@ -14,8 +14,8 @@ export class AppAuthService {
return await this.usersAuthService.sendConfirmationCode(dto.phoneNumber)
}
public async confirmCode(dto: ConfirmLoginCodePayloadDto) {
const session = await this.usersAuthService.confirmLoginCode(dto)
public async confirmCode(ip: string, dto: ConfirmLoginCodePayloadDto) {
const session = await this.usersAuthService.confirmLoginCode({ ...dto, ip })
return {
accessToken: session.accessToken,
@ -23,8 +23,8 @@ export class AppAuthService { @@ -23,8 +23,8 @@ export class AppAuthService {
}
}
public async checkCode(dto: CheckCodePayloadDto) {
return await this.usersAuthService.checkCode(dto.phoneNumber, dto.code)
public async checkCode(ip: string, dto: CheckCodePayloadDto) {
return await this.usersAuthService.checkCode(dto.phoneNumber, dto.code, ip)
}
public async logout(dto: LogoutPayloadDto) {

Loading…
Cancel
Save