A free security tool called Google Authenticator creates special codes for two-factor authentication (2FA). By forcing users to submit two pieces of evidence—something they know, like a password, and something they have, like a smartphone—2FA adds an extra layer of protection to the authentication process.
The Google Authenticator app generates a time-based one-time password (TOTP) valid for a short period, typically 30 seconds. This code can be used as the second factor in a 2FA setup, along with a password or other first factor.
To use Google Authenticator, you must first enable 2FA on your account or app. Then, download and install the Google Authenticator app on your smartphone or tablet. When you log in to your account or app, you will be prompted to enter the unique code generated by the app along with your password. This ensures that even if someone knows your password, they cannot log in without access to the second-factor code generated by the Google Authenticator app.
Overall, 2FA adds an extra layer of security to your online accounts and helps protect you against various online attacks, such as phishing and password theft.
To implement 2-Factor Google Authenticator using ASP Net Core and Angular, you can follow the below steps.
Step 1. Install the Google Authenticator NuGet package.
1 | <span class="token maybe-class-name">Install</span><span class="token operator">-</span><span class="token maybe-class-name">Package</span> <span class="token maybe-class-name">GoogleAuthenticator</span> |
Step 2. In the Asp Net Core application, create a class named “TwoFactorAuthenticatorService” and add the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token keyword keyword-using">using</span> <span class="token namespace">Google<span class="token punctuation">.</span>Authenticator</span><span class="token punctuation">;</span> <span class="token keyword keyword-using">using</span> <span class="token namespace">System</span><span class="token punctuation">;</span> <span class="token keyword keyword-using">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Collections<span class="token punctuation">.</span>Generic</span><span class="token punctuation">;</span> <span class="token keyword keyword-using">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Linq</span><span class="token punctuation">;</span> <span class="token keyword keyword-using">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Threading<span class="token punctuation">.</span>Tasks</span><span class="token punctuation">;</span> <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-class">class</span> <span class="token class-name">TwoFactorAuthenticatorService</span> <span class="token punctuation">{</span> <span class="token keyword keyword-public">public</span> <span class="token return-type class-name"><span class="token keyword keyword-string">string</span></span> <span class="token function">GenerateQrCodeUri</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword keyword-string">string</span></span> email<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword keyword-string">string</span></span> secretKey<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> tfa <span class="token operator">=</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">TwoFactorAuthenticator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword keyword-return">return</span> tfa<span class="token punctuation">.</span><span class="token function">GenerateQrCodeUri</span><span class="token punctuation">(</span>email<span class="token punctuation">,</span> secretKey<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword keyword-public">public</span> <span class="token return-type class-name"><span class="token keyword keyword-bool">bool</span></span> <span class="token function">ValidateTwoFactorPin</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword keyword-string">string</span></span> secretKey<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword keyword-string">string</span></span> twoFactorCode<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> tfa <span class="token operator">=</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">TwoFactorAuthenticator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword keyword-return">return</span> tfa<span class="token punctuation">.</span><span class="token function">ValidateTwoFactorPIN</span><span class="token punctuation">(</span>secretKey<span class="token punctuation">,</span> twoFactorCode<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword keyword-public">public</span> <span class="token return-type class-name"><span class="token keyword keyword-string">string</span></span> <span class="token function">GenerateNewSecretKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> tfa <span class="token operator">=</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">TwoFactorAuthenticator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> setupCode <span class="token operator">=</span> tfa<span class="token punctuation">.</span><span class="token function">GenerateSetupCode</span><span class="token punctuation">(</span><span class="token string">"My App"</span><span class="token punctuation">,</span> <span class="token string">"My User"</span><span class="token punctuation">,</span> <span class="token string">"mysecretkey"</span><span class="token punctuation">,</span> <span class="token number">300</span><span class="token punctuation">,</span> <span class="token number">300</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword keyword-return">return</span> setupCode<span class="token punctuation">.</span>Secret<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Step 3. In the Angular application, create a component named “TwoFactorAuthenticatorComponent” and add the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <span class="token keyword keyword-import">import</span> <span class="token punctuation">{</span> Component <span class="token punctuation">}</span> <span class="token keyword keyword-from">from</span> <span class="token string">'@angular/core'</span><span class="token punctuation">;</span> <span class="token keyword keyword-import">import</span> <span class="token punctuation">{</span> HttpClient <span class="token punctuation">}</span> <span class="token keyword keyword-from">from</span> <span class="token string">'@angular/common/http'</span><span class="token punctuation">;</span> <span class="token decorator"><span class="token at operator">@</span><span class="token function">Component</span></span><span class="token punctuation">(</span><span class="token punctuation">{</span> selector<span class="token operator">:</span> <span class="token string">'app-two-factor-authenticator'</span><span class="token punctuation">,</span> templateUrl<span class="token operator">:</span> <span class="token string">'./two-factor-authenticator.component.html'</span><span class="token punctuation">,</span> styleUrls<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'./two-factor-authenticator.component.css'</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword keyword-export">export</span> <span class="token keyword keyword-class">class</span> <span class="token class-name">TwoFactorAuthenticatorComponent</span> <span class="token punctuation">{</span> email<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span> secretKey<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span> qrCode<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span> twoFactorCode<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span> <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token keyword keyword-private">private</span> http<span class="token operator">:</span> HttpClient<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token function">generateSecretKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword keyword-this">this</span><span class="token punctuation">.</span>http<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/api/twofactorauthenticator/generatesecretkey'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token punctuation">(</span>result<span class="token operator">:</span> <span class="token builtin">any</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword keyword-this">this</span><span class="token punctuation">.</span>secretKey <span class="token operator">=</span> result<span class="token punctuation">;</span> <span class="token keyword keyword-this">this</span><span class="token punctuation">.</span>qrCode <span class="token operator">=</span> <span class="token string">'https://chart.googleapis.com/chart?chs=300x300&chld=M|0&cht=qr&chl='</span> <span class="token operator">+</span> <span class="token function">encodeURIComponent</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">validateTwoFactorCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword keyword-this">this</span><span class="token punctuation">.</span>http<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/api/twofactorauthenticator/validatetwofactorcode'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> secretKey<span class="token operator">:</span> <span class="token keyword keyword-this">this</span><span class="token punctuation">.</span>secretKey<span class="token punctuation">,</span> twoFactorCode<span class="token operator">:</span> <span class="token keyword keyword-this">this</span><span class="token punctuation">.</span>twoFactorCode <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token punctuation">(</span>result<span class="token operator">:</span> <span class="token builtin">any</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword keyword-if">if</span> <span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'Valid code!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword keyword-else">else</span> <span class="token punctuation">{</span> <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'Invalid code!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Step 4. In the Angular application, create a template for the “TwoFactorAuthenticatorComponent” component and add the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token operator"><</span>div<span class="token operator">></span> <span class="token operator"><</span>label<span class="token operator">></span><span class="token maybe-class-name">Email</span><span class="token operator">:</span><span class="token operator"><</span><span class="token operator">/</span>label<span class="token operator">></span> <span class="token operator"><</span>input type<span class="token operator">=</span><span class="token string">"text"</span> <span class="token punctuation">[</span><span class="token punctuation">(</span>ngModel<span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token operator">=</span><span class="token string">"email"</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token operator"><</span>div<span class="token operator">></span> <span class="token operator"><</span><span class="token function">button</span> <span class="token punctuation">(</span>click<span class="token punctuation">)</span><span class="token operator">=</span><span class="token string">"generateSecretKey()"</span><span class="token operator">></span><span class="token maybe-class-name">Generate</span> <span class="token maybe-class-name">Secret</span> <span class="token maybe-class-name">Key</span><span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token operator"><</span>div <span class="token operator">*</span>ngIf<span class="token operator">=</span><span class="token string">"secretKey"</span><span class="token operator">></span> <span class="token operator"><</span>img <span class="token punctuation">[</span>src<span class="token punctuation">]</span><span class="token operator">=</span><span class="token string">"qrCode"</span><span class="token operator">></span> <span class="token operator"><</span>p<span class="token operator">></span><span class="token maybe-class-name">Secret</span> <span class="token maybe-class-name">Key</span><span class="token operator">:</span> <span class="token punctuation">{</span><span class="token punctuation">{</span> secretKey <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token operator"><</span>div<span class="token operator">></span> <span class="token operator"><</span>label<span class="token operator">></span><span class="token maybe-class-name">Two</span> <span class="token maybe-class-name">Factor</span> <span class="token maybe-class-name">Code</span><span class="token operator">:</span><span class="token operator"><</span><span class="token operator">/</span>label<span class="token operator">></span> <span class="token operator"><</span>input type<span class="token operator">=</span><span class="token string">"text"</span> <span class="token punctuation">[</span><span class="token punctuation">(</span>ngModel<span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token operator">=</span><span class="token string">"twoFactorCode"</span><span class="token operator">></span> <span class="token operator"><</span><span class="token function">button</span> <span class="token punctuation">(</span>click<span class="token punctuation">)</span><span class="token operator">=</span><span class="token string">"validateTwoFactorCode()"</span><span class="token operator">></span><span class="token maybe-class-name">Validate</span> <span class="token maybe-class-name">Two</span> <span class="token maybe-class-name">Factor</span> <span class="token maybe-class-name">Code</span><span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> |
Step 5. In the Asp Net Core application, create a controller named “TwoFactorAuthenticatorController” and add the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | <span class="token keyword keyword-using">using</span> <span class="token namespace">Microsoft<span class="token punctuation">.</span>AspNetCore<span class="token punctuation">.</span>Mvc</span><span class="token punctuation">;</span> <span class="token keyword keyword-using">using</span> <span class="token namespace">QRCoder</span><span class="token punctuation">;</span> <span class="token keyword keyword-using">using</span> <span class="token namespace">System</span><span class="token punctuation">;</span> <span class="token keyword keyword-using">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Drawing</span><span class="token punctuation">;</span> <span class="token keyword keyword-using">using</span> <span class="token namespace">TwoFactorAuthenticator</span><span class="token punctuation">;</span> <span class="token keyword keyword-namespace">namespace</span> <span class="token namespace">YourNamespace<span class="token punctuation">.</span>Controllers</span> <span class="token punctuation">{</span> <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-class">class</span> <span class="token class-name">TwoFactorAuthenticatorController</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">Controller</span></span> <span class="token punctuation">{</span> <span class="token comment">// Action method to generate the QR code for the user to scan and set up their Two-Factor Authentication</span> <span class="token keyword keyword-public">public</span> <span class="token return-type class-name">IActionResult</span> <span class="token function">GenerateQRCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Generate the Two-Factor Authentication secret key</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> secretKey <span class="token operator">=</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">Base32Encoder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Encode</span><span class="token punctuation">(</span>Encoding<span class="token punctuation">.</span>ASCII<span class="token punctuation">.</span><span class="token function">GetBytes</span><span class="token punctuation">(</span>Guid<span class="token punctuation">.</span><span class="token function">NewGuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Replace</span><span class="token punctuation">(</span><span class="token string">"-"</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Substring</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Generate the QR code for the user to scan</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> qrCodeGenerator <span class="token operator">=</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">QRCodeGenerator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> qrCodeData <span class="token operator">=</span> qrCodeGenerator<span class="token punctuation">.</span><span class="token function">CreateQrCode</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"otpauth://totp/YourAppName:YourUserName?secret=</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">secretKey</span><span class="token punctuation">}</span></span><span class="token string">&issuer=YourAppName"</span></span><span class="token punctuation">,</span> QRCodeGenerator<span class="token punctuation">.</span>ECCLevel<span class="token punctuation">.</span>Q<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> qrCode <span class="token operator">=</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">QRCode</span><span class="token punctuation">(</span>qrCodeData<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> qrCodeImage <span class="token operator">=</span> qrCode<span class="token punctuation">.</span><span class="token function">GetGraphic</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Return the QR code image to the user</span> <span class="token keyword keyword-return">return</span> <span class="token function">File</span><span class="token punctuation">(</span>qrCodeImage<span class="token punctuation">,</span> <span class="token string">"image/png"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Action method to verify the user's Two-Factor Authentication code</span> <span class="token punctuation">[</span>HttpPost<span class="token punctuation">]</span> <span class="token keyword keyword-public">public</span> <span class="token return-type class-name">IActionResult</span> <span class="token function">VerifyCode</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword keyword-string">string</span></span> code<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Get the user's Two-Factor Authentication secret key from the database or other storage location</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> secretKey <span class="token operator">=</span> <span class="token string">"yourSecretKey"</span><span class="token punctuation">;</span> <span class="token comment">// Verify the One-Time Password (OTP) entered by the user</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> tfa <span class="token operator">=</span> <span class="token keyword keyword-new">new</span> <span class="token constructor-invocation class-name">TwoFactorAuthenticator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> result <span class="token operator">=</span> tfa<span class="token punctuation">.</span><span class="token function">ValidateTwoFactorPIN</span><span class="token punctuation">(</span>secretKey<span class="token punctuation">,</span> code<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// If the OTP is valid, redirect the user to their account or other authorized page</span> <span class="token keyword keyword-if">if</span> <span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword keyword-return">return</span> <span class="token function">RedirectToAction</span><span class="token punctuation">(</span><span class="token string">"Index"</span><span class="token punctuation">,</span> <span class="token string">"Home"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword keyword-else">else</span> <span class="token punctuation">{</span> <span class="token comment">// If the OTP is invalid, return an error message to the user</span> ModelState<span class="token punctuation">.</span><span class="token function">AddModelError</span><span class="token punctuation">(</span><span class="token string">"code"</span><span class="token punctuation">,</span> <span class="token string">"The code entered is invalid."</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword keyword-return">return</span> <span class="token function">View</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Summary
This article discusses the implementation of a 2-Factor Google Authenticator using ASP Net Core and Angular in detail.
ASP.NET 8.0.4 Hosting Recommendation
ASP.NET is a powerful platform for creating web applications and services. You must be comfortable with JavaScript, HTML, CSS, and C# before developing a web application in ASP.NET. On the market, there are thousands of web hosting companies providing ASP.NET Hosting. But, only very few web hosting companies could provide high quality ASP.NET hosting solution.
ASP.NET is the best development language in Windows platform, which is released by Microsoft and widely used to build all types of dynamic Web sites and XML Web services. With this article, we’re going to help you to find the best ASP.NET Hosting solution in Europe based on reliability, features, price, performance and technical support. After we reviewed about 30+ ASP.NET hosting providers in Europe, our Best ASP.NET Hosting Award in Europe goes to HostForLIFE.eu, one of the fastest growing private companies and one of the most reliable hosting providers in Europe.