diff --git a/.env.dev b/.env.dev index c2d4f34..004c498 100644 --- a/.env.dev +++ b/.env.dev @@ -7,6 +7,11 @@ JWT_EXPIRATION="" GOOGLE_CLIENT_ID="" GOOGLE_CLIENT_SECRET="" GOOGLE_CALLBACK_URL="" +MICROSOFT_CLIENT_ID="" +MICROSOFT_CLIENT_SECRET="" +MICROSOFT_TENANT_ID="" +MICROSOFT_CALLBACK_URL="" +FRONTEND_URL="" # Estas etapas a baixo ainda nao sao necessarias # RABBIT_MQ_URI=amqp://admin:admin@rabbitmq:5672 diff --git a/package.json b/package.json index 882dd14..cddb0a4 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "passport": "^0.7.0", "passport-google-oauth20": "^2.0.0", "passport-jwt": "^4.0.1", + "passport-microsoft": "^2.1.0", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1" }, diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 00bd576..9b7fd38 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -7,19 +7,26 @@ import { UseGuards, Req, Res, + Logger, } from '@nestjs/common'; import { AuthService } from './auth.service'; import { LoginDto } from 'src/users/dtos/login.dto'; import { AuthGuard } from '@nestjs/passport'; import { Response, Request } from 'express'; +import { ConfigService } from '@nestjs/config'; @Controller('auth') export class AuthController { - constructor(private readonly authService: AuthService) {} + private readonly logger = new Logger(AuthController.name); + constructor( + private readonly authService: AuthService, + private readonly configService: ConfigService, + ) {} @Post('login') async login(@Body() loginDto: LoginDto) { - console.log('AuthController - Login Request:', loginDto); + this.logger.log('AuthController - Login Request:', loginDto); + const user = await this.authService.validateUser( loginDto.email, loginDto.password, @@ -33,13 +40,20 @@ export class AuthController { @Get('google') @UseGuards(AuthGuard('google')) async googleAuth() { - console.log('AuthController - Google Auth Initiated'); + this.logger.log( + `front url: ${this.configService.get('FRONTEND_URL')}`, + ); + this.logger.log('AuthController - Google Auth Initiated'); } @Get('google/callback') @UseGuards(AuthGuard('google')) googleAuthRedirect(@Req() req: Request, @Res() res: Response) { - console.log('AuthController - Google Callback Request:', req.user); + this.logger.log( + `front url: ${this.configService.get('FRONTEND_URL')}`, + ); + this.logger.log('AuthController - Google Callback Request:', req.user); + const user = req.user as any; const { access_token } = user || {}; @@ -49,4 +63,35 @@ export class AuthController { res.redirect('http://localhost:3000/login'); } } + + @Get('microsoft') + @UseGuards(AuthGuard('microsoft')) + async microsoftAuth() { + this.logger.log( + `front url: ${this.configService.get('FRONTEND_URL')}`, + ); + this.logger.log('AuthController - Microsoft Auth Initiated'); + } + + @Get('microsoft/callback') + @UseGuards(AuthGuard('microsoft')) + microsoftAuthRedirect(@Req() req: Request, @Res() res: Response) { + this.logger.log( + 'AuthController - Microsoft Callback Request:', + JSON.stringify(req.user), + ); + + const user = req.user as any; + const { access_token } = user || {}; + + if (access_token) { + res.redirect( + `${this.configService.get('FRONTEND_URL')}/oauth?token=${access_token}`, + ); + } else { + res.redirect( + `${this.configService.get('FRONTEND_URL')}/cadastro`, + ); + } + } } diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index 3589750..009bc5e 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -6,6 +6,8 @@ import { AuthService } from './auth.service'; import { AuthController } from './auth.controller'; import { JwtStrategy } from './strategies/jwt.strategy'; import { GoogleStrategy } from './strategies/google.strategy'; +import { MicrosoftStrategy } from './strategies/microsoft.strategy'; + @Module({ imports: [ PassportModule.register({ defaultStrategy: 'jwt' }), @@ -17,7 +19,7 @@ import { GoogleStrategy } from './strategies/google.strategy'; }), UsersModule, ], - providers: [AuthService, JwtStrategy, GoogleStrategy], + providers: [AuthService, JwtStrategy, GoogleStrategy, MicrosoftStrategy], controllers: [AuthController], exports: [JwtStrategy, PassportModule, AuthService], }) diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 2c616e2..141f678 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -1,10 +1,11 @@ -import { Injectable, UnauthorizedException } from '@nestjs/common'; +import { Injectable, Logger, UnauthorizedException } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { UsersService } from '../users/users.service'; import * as bcrypt from 'bcryptjs'; @Injectable() export class AuthService { + private readonly logger = new Logger(AuthService.name); constructor( private readonly usersService: UsersService, private readonly jwtService: JwtService, @@ -22,14 +23,19 @@ export class AuthService { async login(user: any) { const payload = { + id: user._id, + name: user.name, email: user.email, sub: user._id, role: user.role, }; const token = this.jwtService.sign(payload); - console.log('AuthService - Generated Token:', token); + this.logger.log('AuthService - Generated Token:', token); return { - access_token: token, + id: user._id, + name: user.name, + email: user.email, + accessToken: token, }; } diff --git a/src/auth/strategies/google.strategy.ts b/src/auth/strategies/google.strategy.ts index 90f1aa8..f254ed8 100644 --- a/src/auth/strategies/google.strategy.ts +++ b/src/auth/strategies/google.strategy.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { Strategy, Profile, VerifyCallback } from 'passport-google-oauth20'; import { UsersService } from 'src/users/users.service'; @@ -7,6 +7,7 @@ import { ConfigService } from '@nestjs/config'; @Injectable() export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { + private readonly logger = new Logger(GoogleStrategy.name); constructor( private readonly usersService: UsersService, private readonly authService: AuthService, @@ -26,7 +27,7 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { profile: Profile, done: VerifyCallback, ) { - console.log('GoogleStrategy - Profile:', profile); // Log do profile para verificar os dados + this.logger.log('GoogleStrategy - Profile:', profile); // Log do profile para verificar os dados const email = profile.emails[0].value; const name = profile.displayName; @@ -42,9 +43,15 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { }); } - const payload = { email: user.email, sub: user._id }; + const payload = { + id: user._id, + name: user.name, + email: user.email, + sub: user._id, + role: user.role, + }; const token = this.authService.getJwtService().sign(payload); - return done(null, { ...user.toObject(), access_token: token }); + return done(null, { ...user.toObject(), accessToken: token }); } } diff --git a/src/auth/strategies/microsoft.strategy.ts b/src/auth/strategies/microsoft.strategy.ts new file mode 100644 index 0000000..bc12d9a --- /dev/null +++ b/src/auth/strategies/microsoft.strategy.ts @@ -0,0 +1,58 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { PassportStrategy } from '@nestjs/passport'; +import { Strategy, Profile, VerifyCallback } from 'passport-microsoft'; +import { UsersService } from 'src/users/users.service'; +import { AuthService } from '../auth.service'; +import { ConfigService } from '@nestjs/config'; + +@Injectable() +export class MicrosoftStrategy extends PassportStrategy(Strategy, 'microsoft') { + private readonly logger = new Logger(MicrosoftStrategy.name); + + constructor( + private readonly usersService: UsersService, + private readonly authService: AuthService, + private readonly configService: ConfigService, + ) { + super({ + clientID: configService.get('MICROSOFT_CLIENT_ID'), + clientSecret: configService.get('MICROSOFT_CLIENT_SECRET'), + callbackURL: configService.get('MICROSOFT_CALLBACK_URL'), + scope: ['user.read'], + }); + } + + async validate( + accessToken: string, + refreshToken: string, + profile: Profile, + done: VerifyCallback, + ) { + this.logger.log('MicrosoftStrategy - Profile:', JSON.stringify(profile)); // Log do profile para verificar os dados + + const email = profile.emails[0].value; + const name = profile.displayName; + + let user = await this.usersService.findByEmail(email); + + if (!user) { + user = await this.usersService.createUserGoogle({ + name, + email, + username: email, + password: '', + }); + } + + const payload = { + id: user._id, + name: user.name, + email: user.email, + sub: user._id, + role: user.role, + }; + const token = this.authService.getJwtService().sign(payload); + + return done(null, { ...user.toObject(), accessToken: token }); + } +} diff --git a/src/main.ts b/src/main.ts index e0aab29..38aeacd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,6 +9,12 @@ const logger = new Logger('Main'); async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalPipes(new ValidationPipe()); + app.enableCors({ + origin: configService.get('FRONTEND_URL'), + credentials: true, + methods: ['GET', 'POST', 'PUT', 'DELETE'], + allowedHeaders: ['Content-Type', 'Authorization'], + }); await app.listen(configService.get('PORT')); logger.log(`Application listening on port ${configService.get('PORT')}`); } diff --git a/src/types/express.d.ts b/src/types/express.d.ts index 682c118..797600a 100644 --- a/src/types/express.d.ts +++ b/src/types/express.d.ts @@ -3,7 +3,7 @@ import { User } from 'src/users/interface/user.interface'; declare global { namespace Express { interface Request { - user?: User & { access_token?: string }; + user?: User & { accessToken?: string }; } } -} \ No newline at end of file +}