1
1
package com .bitscoderdotcom .link_generator_system .security .service ;
2
2
3
- import com .bitscoderdotcom .link_generator_system .dto .ApiResponse ;
4
- import com .bitscoderdotcom .link_generator_system .dto .EmailDetails ;
5
- import com .bitscoderdotcom .link_generator_system .dto .SignInRequest ;
6
- import com .bitscoderdotcom .link_generator_system .dto .UserRegistrationRequest ;
3
+ import com .bitscoderdotcom .link_generator_system .dto .*;
7
4
import com .bitscoderdotcom .link_generator_system .entities .Company ;
5
+ import com .bitscoderdotcom .link_generator_system .entities .UserTOTP ;
6
+ import com .bitscoderdotcom .link_generator_system .entities .Validation ;
8
7
import com .bitscoderdotcom .link_generator_system .repository .CompanyRepository ;
8
+ import com .bitscoderdotcom .link_generator_system .repository .UserTOTPRepository ;
9
9
import com .bitscoderdotcom .link_generator_system .security .jwt .JwtUtils ;
10
10
import com .bitscoderdotcom .link_generator_system .service .EmailService ;
11
+ import com .google .zxing .BarcodeFormat ;
12
+ import com .google .zxing .client .j2se .MatrixToImageWriter ;
13
+ import com .google .zxing .common .BitMatrix ;
14
+ import com .google .zxing .qrcode .QRCodeWriter ;
15
+ import com .warrenstrange .googleauth .GoogleAuthenticator ;
16
+ import com .warrenstrange .googleauth .GoogleAuthenticatorKey ;
17
+ import com .warrenstrange .googleauth .GoogleAuthenticatorQRGenerator ;
18
+ import jakarta .servlet .ServletOutputStream ;
19
+ import jakarta .servlet .http .HttpServletResponse ;
11
20
import lombok .AllArgsConstructor ;
21
+ import lombok .SneakyThrows ;
12
22
import lombok .extern .slf4j .Slf4j ;
13
23
import org .springframework .http .HttpStatus ;
14
24
import org .springframework .http .ResponseEntity ;
22
32
import org .springframework .transaction .annotation .Transactional ;
23
33
import org .springframework .web .server .ResponseStatusException ;
24
34
35
+ import java .io .ByteArrayOutputStream ;
36
+ import java .io .File ;
37
+ import java .io .FileOutputStream ;
25
38
import java .time .LocalDateTime ;
39
+ import java .util .Base64 ;
26
40
import java .util .UUID ;
27
41
28
42
@ Service
@@ -32,10 +46,12 @@ public class AuthService {
32
46
33
47
private AuthenticationManager authenticationManager ;
34
48
private CompanyRepository companyRepository ;
49
+ private UserTOTPRepository userTOTPRepository ;
35
50
private PasswordEncoder passwordEncoder ;
36
51
private JwtUtils jwtUtils ;
37
52
private UserDetailsServiceImpl userDetailsService ;
38
53
private EmailService emailService ;
54
+ private final GoogleAuthenticator gAuth ;
39
55
40
56
@ Transactional
41
57
public String register (UserRegistrationRequest request ) {
@@ -58,19 +74,31 @@ public String register(UserRegistrationRequest request) {
58
74
return "Email Address already in use!" ;
59
75
}
60
76
77
+
78
+ log .info ("Company registered successfully with username: {}" , username );
79
+
80
+ GoogleAuthenticatorKey key = generate2faKey (username );
81
+
82
+ UserTOTP userTOTP = new UserTOTP ();
83
+ userTOTP .setUsername (username );
84
+ userTOTP .setSecretKey (key .getKey ());
85
+ userTOTPRepository .save (userTOTP );
86
+
61
87
Company company = new Company ();
62
88
company .setUserName (request .getName ());
63
89
company .setCompanyName (request .getCompanyName ());
64
90
company .setCompanyEmail (request .getEmail ());
65
91
company .setPassword (passwordEncoder .encode (request .getPassword ()));
92
+ company .setUserTOTP (userTOTP );
66
93
companyRepository .save (company );
67
94
68
- log .info ("Company registered successfully with username: {}" , username );
69
-
70
95
EmailDetails emailDetails = new EmailDetails ();
71
96
emailDetails .setRecipient (company .getCompanyEmail ());
72
97
emailDetails .setSubject ("Account Registration Confirmation" );
73
- emailDetails .setMessageBody ("Your account has been registered on our platform" );
98
+ emailDetails .setMessageBody ("Your account has been registered on our platform.\n " +
99
+ "Please scan the following QR code with your Google Authenticator app to enable 2FA.\n " +
100
+ "Key: " + key .getKey ());
101
+ emailDetails .setAttachment (generateQRCode (username , key ));
74
102
emailService .sendEmail (emailDetails );
75
103
76
104
return "Company registered successfully" ;
@@ -98,13 +126,64 @@ public ResponseEntity<ApiResponse<SignInRequest.Response>> signIn(SignInRequest
98
126
jwtUtils .getJwtExpirationDate ()
99
127
);
100
128
101
- return createSuccessResponse ("Company signed in successfully " , response );
129
+ return createSuccessResponse ("2FA required " , response );
102
130
} catch (BadCredentialsException e ) {
103
131
log .info ("Invalid email or password for email: {}" , request .getEmail ());
104
132
return createBadRequestResponse ("Invalid email or password" , null );
105
133
}
106
134
}
107
135
136
+ // @SneakyThrows
137
+ // public File generate2fa(String username) {
138
+ // final GoogleAuthenticatorKey key = gAuth.createCredentials(username);
139
+ //
140
+ // UserTOTP userTOTP = new UserTOTP();
141
+ // userTOTP.setUsername(username);
142
+ // userTOTP.setSecretKey(key.getKey());
143
+ // userTOTPRepository.save(userTOTP);
144
+ //
145
+ // QRCodeWriter qrCodeWriter = new QRCodeWriter();
146
+ // String otpAuthURL = GoogleAuthenticatorQRGenerator.getOtpAuthTotpURL("Link Generation App", username, key);
147
+ // BitMatrix bitMatrix = qrCodeWriter.encode(otpAuthURL, BarcodeFormat.QR_CODE, 200, 200);
148
+ //
149
+ // File qrFile = File.createTempFile("qrcode", ".png");
150
+ // FileOutputStream pngOutputStream = new FileOutputStream(qrFile);
151
+ // MatrixToImageWriter.writeToStream(bitMatrix, "PNG", pngOutputStream);
152
+ // pngOutputStream.close();
153
+ //
154
+ // return qrFile;
155
+ // }
156
+ @ SneakyThrows
157
+ public GoogleAuthenticatorKey generate2faKey (String username ) {
158
+ return gAuth .createCredentials (username );
159
+ }
160
+
161
+ @ SneakyThrows
162
+ public File generateQRCode (String username , GoogleAuthenticatorKey key ) {
163
+ String otpAuthURL = GoogleAuthenticatorQRGenerator .getOtpAuthTotpURL ("Link Generation App" , username , key );
164
+ BitMatrix bitMatrix = new QRCodeWriter ().encode (otpAuthURL , BarcodeFormat .QR_CODE , 200 , 200 );
165
+
166
+ File qrFile = File .createTempFile ("qrcode" , ".png" );
167
+ try (FileOutputStream pngOutputStream = new FileOutputStream (qrFile )) {
168
+ MatrixToImageWriter .writeToStream (bitMatrix , "PNG" , pngOutputStream );
169
+ }
170
+
171
+ return qrFile ;
172
+ }
173
+
174
+ public ResponseEntity <ApiResponse <SignInRequest .Response >> validate2FA (ValidateCodeDto body ) {
175
+ log .info ("validate2FA method called with username: {}" , body .getUsername ());
176
+
177
+ UserTOTP userTOTP = userTOTPRepository .findByUsername (body .getUsername ());
178
+
179
+ if (userTOTP == null || !gAuth .authorizeUser (body .getUsername (), body .getVerificationCode ())) {
180
+ log .info ("Invalid 2FA code for username: {}" , body .getUsername ());
181
+ return createBadRequestResponse ("Invalid 2FA code" , null );
182
+ }
183
+
184
+ return createSuccessResponse ("User authenticated successfully" , null );
185
+ }
186
+
108
187
public <T > ResponseEntity <ApiResponse <T >> createSuccessResponse (String message , T data ) {
109
188
return ResponseEntity .ok (new ApiResponse <>(
110
189
LocalDateTime .now (),
0 commit comments