Adiciona primeiras partes da autenticacao
This commit is contained in:
18
src/auth/auth.controller.spec.ts
Normal file
18
src/auth/auth.controller.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AuthController } from './auth.controller';
|
||||
|
||||
describe('AuthController', () => {
|
||||
let controller: AuthController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [AuthController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<AuthController>(AuthController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
29
src/auth/auth.controller.ts
Normal file
29
src/auth/auth.controller.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Controller, Post, Body, HttpCode, HttpStatus } from '@nestjs/common';
|
||||
|
||||
import LoginResponseDto from './dto/loginResponse.dto';
|
||||
|
||||
import { AuthService } from './auth.service';
|
||||
import { LoginDto } from './dto/login.dto';
|
||||
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
constructor(private readonly authService: AuthService) {}
|
||||
|
||||
@Post('login')
|
||||
async login(@Body() loginDto: LoginDto): Promise<LoginResponseDto> {
|
||||
return this.authService.login(loginDto);
|
||||
}
|
||||
|
||||
@Post('logout')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async logout(@Body() body: { refreshToken: string }): Promise<void> {
|
||||
return this.authService.logout(body.refreshToken);
|
||||
}
|
||||
|
||||
@Post('refresh-token')
|
||||
async refreshToken(
|
||||
@Body() body: { refreshToken: string },
|
||||
): Promise<LoginResponseDto> {
|
||||
return this.authService.refreshToken(body.refreshToken);
|
||||
}
|
||||
}
|
||||
10
src/auth/auth.module.ts
Normal file
10
src/auth/auth.module.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AuthController } from './auth.controller';
|
||||
|
||||
@Module({
|
||||
controllers: [AuthController],
|
||||
providers: [AuthService],
|
||||
exports: [AuthService],
|
||||
})
|
||||
export class AuthModule {}
|
||||
18
src/auth/auth.service.spec.ts
Normal file
18
src/auth/auth.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
describe('AuthService', () => {
|
||||
let service: AuthService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [AuthService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<AuthService>(AuthService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
103
src/auth/auth.service.ts
Normal file
103
src/auth/auth.service.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import axios, { isAxiosError } from 'axios';
|
||||
|
||||
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
|
||||
import { LoginDto } from './dto/login.dto';
|
||||
|
||||
import LoginResponseDto from './dto/loginResponse.dto';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
private readonly keycloakUrl =
|
||||
'https://auth.clipperia.com.br/realms/clipperia/protocol/openid-connect';
|
||||
private readonly clientId = 'usuarios';
|
||||
private readonly clientSecret = process.env.KEYCLOAK_CLIENT_SECRET;
|
||||
|
||||
private readonly keycloakApi = axios.create({
|
||||
baseURL: this.keycloakUrl,
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
});
|
||||
|
||||
async login(loginDto: LoginDto) {
|
||||
try {
|
||||
const params = new URLSearchParams({
|
||||
client_id: this.clientId,
|
||||
grant_type: 'password',
|
||||
username: loginDto.username,
|
||||
password: loginDto.password,
|
||||
});
|
||||
|
||||
if (this.clientSecret) {
|
||||
params.append('client_secret', this.clientSecret);
|
||||
}
|
||||
|
||||
const { data } = await this.keycloakApi.post<LoginResponseDto>(
|
||||
'/token',
|
||||
params,
|
||||
);
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
if (isAxiosError(error)) {
|
||||
console.error(error.response?.data);
|
||||
throw new UnauthorizedException(error.response?.data);
|
||||
}
|
||||
|
||||
throw new UnauthorizedException('Usuário ou senha inválidos');
|
||||
}
|
||||
}
|
||||
|
||||
async logout(refreshToken: string): Promise<void> {
|
||||
try {
|
||||
const data = new URLSearchParams({
|
||||
client_id: this.clientId,
|
||||
refresh_token: refreshToken,
|
||||
});
|
||||
|
||||
if (this.clientSecret) {
|
||||
data.append('client_secret', this.clientSecret);
|
||||
}
|
||||
|
||||
await this.keycloakApi.post('/logout', data);
|
||||
} catch (error) {
|
||||
if (isAxiosError(error)) {
|
||||
console.error(error.response?.data);
|
||||
throw new UnauthorizedException(error.response?.data);
|
||||
}
|
||||
|
||||
throw new UnauthorizedException('Erro ao deslogar usuário');
|
||||
}
|
||||
}
|
||||
|
||||
async refreshToken(refreshToken: string) {
|
||||
console.log(refreshToken);
|
||||
|
||||
try {
|
||||
const params = new URLSearchParams({
|
||||
client_id: this.clientId,
|
||||
grant_type: 'refresh_token',
|
||||
refresh_token: refreshToken,
|
||||
});
|
||||
|
||||
if (this.clientSecret) {
|
||||
params.append('client_secret', this.clientSecret);
|
||||
}
|
||||
|
||||
const { data } = await this.keycloakApi.post<LoginResponseDto>(
|
||||
'/token',
|
||||
params,
|
||||
);
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
if (isAxiosError(error)) {
|
||||
console.error(error.response?.data);
|
||||
throw new UnauthorizedException(error.response?.data);
|
||||
}
|
||||
|
||||
throw new UnauthorizedException('Erro ao renovar token');
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/auth/dto/login.dto.ts
Normal file
16
src/auth/dto/login.dto.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
|
||||
|
||||
export class LoginDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
username: string;
|
||||
|
||||
@IsString()
|
||||
@IsEmail()
|
||||
@IsNotEmpty()
|
||||
email: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
password: string;
|
||||
}
|
||||
8
src/auth/dto/loginResponse.dto.ts
Normal file
8
src/auth/dto/loginResponse.dto.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export default class LoginResponseDto {
|
||||
access_token: string;
|
||||
refresh_token: string;
|
||||
token_type: string;
|
||||
expires_in: number;
|
||||
refresh_expires_in: number;
|
||||
scope: string;
|
||||
}
|
||||
Reference in New Issue
Block a user