homemanager-be/src/shared/auth/auth.service.ts

76 lines
2.0 KiB
TypeScript

import { Inject, Injectable, UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { UserService } from 'src/objects/user/user.service';
import * as bcrypt from 'bcrypt';
import * as jwt from 'jsonwebtoken';
import { User } from 'src/objects/user/user.entity';
@Injectable()
export class AuthService {
public expiry = +this.config.get('TOKEN_EXPIRY');
private issuer = this.config.get('BACKEND_URL');
private audience = this.config.get('FRONTEND_URL');
constructor(
@Inject('JWT_PRIVATE_KEY')
private readonly privateKey: string,
@Inject('JWT_PUBLIC_KEY')
private readonly publicKey: string,
private readonly userService: UserService,
private readonly config: ConfigService,
) {}
async comparePassword(user: User, password: string) {
return bcrypt.compare(password, user.password);
}
async hashPassword(password: string) {
return bcrypt.hash(password, 12);
}
async issueJWT(user: User) {
return jwt.sign(
{
name: user.name,
email: user.email,
email_verified: user.emailVerified,
picture: user.picture,
updated_at: user.updatedAt.toISOString(),
},
this.privateKey,
{
algorithm: 'RS256',
audience: this.audience,
subject: user.sub,
expiresIn: this.expiry,
issuer: this.issuer,
},
);
}
async getUserFromJWT(token: string) {
let payload: jwt.JwtPayload;
try {
const data = jwt.verify(token, this.publicKey, {
algorithms: ['RS256'],
issuer: this.issuer,
audience: this.audience,
complete: true,
});
payload = data.payload as jwt.JwtPayload;
} catch {
throw new UnauthorizedException('Invalid token');
}
if (!payload || typeof payload === 'string') {
throw new UnauthorizedException('Invalid token');
}
const user = await this.userService.getUserBySub(payload.sub);
if (!user) throw new UnauthorizedException('Invalid token');
return user;
}
}