In this article, we are going to implement Blazor WebAssembly cookie authentication with Facebook(external login provider).
Step3:
Step4:
Click here for - Part-1 Blazor WebAssembly authentication with .net core cookie.
Install Facebook NuGet In API Project:
Let's install the Microsoft Facebook Authentication package.
.NET CLI Command:
dotnet add package Microsoft.AspNetCore.Authentication.Facebook --version 6.0.3
dotnet add package Microsoft.AspNetCore.Authentication.Facebook --version 6.0.3
Package Manager:
Install-Package Microsoft.AspNetCore.Authentication.Facebook -Version 6.0.3
Install-Package Microsoft.AspNetCore.Authentication.Facebook -Version 6.0.3
Register API Wih Facebook:
To enable Facebook authentication we have to register our API project with Facebook. So following are facebook registration steps.
Step1:
Go to the Facebook Developer page at "https://developers.facebook.com/apps/".
Step2:
Go to the 'My Apps' menu and click on the 'Create App' button.
In the 'Create An App' section, choose the 'Consumer' option and then click on the 'Next' button.
In the 'Details' form, give a 'Display Name' and then click the 'Create App' button.
Step5:
On 'Add products to your app', click on the 'Setup' button on the 'Facebook Login' page.
Step 6:
The 'Facebook Login' menu is on the left-hand side, under it select the 'Settings' tab.
Step 7:
On 'Client OAuth Settings', add the 'Valid OAuth Redirect URLs' like '{domain}/signin-facebook'. Here 'signin-facebook' path is the default redirection path for the facebook provider.
Step 8:
Now left-side menu 'Settings' then select 'Basic' option, Here we 2 keys we need to configure into our API project like 'App ID', 'App Secret'.
Add Facebook Settings To API Project:
In our API project into the 'appsettings.Development.json' let's add our Facebook settings like 'AppId', and 'AppSecret'.
API_Project/appsettings.Development.json:
"FacebookSettings":{ "AppID":"00000000", "AppSecret":"0000000" }
Register Facebook Service In API Project:
Now register the Facebook service into the API project.
API_Project/Program.cs:
builder.Services.AddAuthentication( CookieAuthenticationDefaults.AuthenticationScheme ) .AddCookie() .AddFacebook(fb => { fb.AppId = builder.Configuration .GetSection("FacebookSettings").GetValue<string>("AppID"); fb.AppSecret = builder.Configuration .GetSection("FacebookSettings").GetValue<string>("AppSecret"); });
- (Line: 5-11) Register the 'AddFacebook' service and then configure 'AppId', 'AppSecret' into it.
Implement Facebook Authentication Logic In API Project:
Let's implement a private method that contains logic to fetch or create the user into our database while trying to authenticate with the external logins like 'Facebook', 'Google', 'Twitter', 'Microsoft' etc.
API_Project/Controllers/AuthController.cs:
private async Task<User> ManageExternalLoginUser(string email, string firstName, string lastName, string externalLoginName) { var user = await _cookieAuthContext .User.Where(_ => _.Email.ToLower() == email.ToLower() && _.ExternalLoginName.ToLower() == externalLoginName.ToLower()) .FirstOrDefaultAsync(); if (user != null) { return user; } var newUser = new User { Email = email, ExternalLoginName = externalLoginName, FirstName = firstName, LastName = lastName }; _cookieAuthContext.User.Add(newUser); await _cookieAuthContext.SaveChangesAsync(); return newUser; }
- (Line: 1-4) The 'ManageExternalLoginUser' method contains input parameter like 'email', 'firstName', 'lastName', 'externalLoginName'. These input parameter are taken from the Facebook claims which we are going to fetch or create an user into the database.
- (Line: 6-9) Fetching Facebook login user information from our database if we already stored them.
- (Line: 16-24) If the Facebook user information does not exist in our database, then we need to save it as a new user.
API_Project/Controllers/AuthController.cs:
private async Task RefreshExternalSignIn(User user) { var claims = new List<Claim> { new Claim("userid", user.Id.ToString()), new Claim(ClaimTypes.Email, user.Email) }; var claimsIdentity = new ClaimsIdentity( claims, CookieAuthenticationDefaults.AuthenticationScheme); var authProperties = new AuthenticationProperties(); HttpContext.User.AddIdentity(claimsIdentity); await HttpContext.SignOutAsync(); await HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties); }
- (Line: 3-7) Creating a collection of claims from our user information.
- (Line: 9-10) Initialized ClaimsIdentity object.
- (Line: 14) Updating the user context with a new claims identity.
- (Line: 16) SignOut from the default cookie.
- (Line: 18-21) Creating a new Sign-In cookie with our own user claims.
API_Project/Controllers/AuthController.cs:
[HttpGet] [Route("facebook-login")] public IActionResult FacebookLogin(string returnURL) { return Challenge( new AuthenticationProperties() { RedirectUri = Url.Action(nameof(FacebookLoginCallback), new { returnURL }) }, FacebookDefaults.AuthenticationScheme ); }
- (Line: 3) Here 'returnURL' query parameter will be our Blazor WebAssembly application URL.
- (Line: 5-11) The 'Challenge' method is to invoke the external authentication provider like 'Facebook'.
- (Line: 8) After successful authentication, the external provider will be redirected to our 'FacebookLoginCallbak' action method(which we will implement in the next step).
- (Line: 10) The 'Challenge()' method is a generic method so we have to specify the external authentication scheme like 'FacebookDefaults.AuthenticationScheme'.
API_Project/Controllers/AuthController.cs:
[HttpGet] [Route("facebook-login-callback")] public async Task<IActionResult> FacebookLoginCallback(string returnURL) { var authenticationResult = await HttpContext .AuthenticateAsync(FacebookDefaults.AuthenticationScheme); if (authenticationResult.Succeeded) { string email = HttpContext .User.Claims.Where(_ => _.Type == ClaimTypes.Email) .Select(_ => _.Value) .FirstOrDefault(); string firstName = HttpContext .User.Claims.Where(_ => _.Type == ClaimTypes.Name) .Select(_ => _.Value) .FirstOrDefault(); string lastName = HttpContext .User.Claims.Where(_ => _.Type == ClaimTypes.Surname) .Select(_ => _.Value) .FirstOrDefault(); var user = await ManageExternalLoginUser( email, firstName, lastName, "Facebook" ); await RefreshExternalSignIn(user); return Redirect($"{returnURL}?externalauth=true"); } return Redirect($"{returnURL}?externalauth=false"); }
- (Line: 3) The 'returnURL' is our Blazor WebAssembly URL.
- (Line: 5-6) Fetch the Facebook authentication status from the HttpContext.
- (Line: 7)Checks for the Facebook success status.
- (Line: 9-22) Fetching Facebook claims like 'email', 'name', 'surname'.
- (Line: 24-29) Invoking the 'ManageExternalLoginUser' method. This method creates a user that doesn't exist in the database and then returns the user as output.
- (Line: 31) Invoking the 'RefreshExternalSignIn()' method.
- (Line: 32) Redirecting to our Blazor WebAssembly application with query parameters like 'externalauth= true', this query parameter will be used by the Blazor WebAssembly application to set 'isauthenticated' local storage variable.
- (Line: 34) Redirecting to the Blazor WebAssembly application with parameters like 'externalauth=false', this query parameter notifies the Blazor WebAssembly application that Facebook authentication failed.
Update 'isauthenticated' Local Storage Variable On Success OF Facebook Authentication In Blazor App:
Recall Part-1 on successful .net core cookie authentication we have stored local storage variable 'isauthenticated'. Similarly, we have to do it for any external login provider authentication also.
BlazorWasm_Project/App.razor:(Code Part)
private async Task OnNavigateAsync(NavigationContext args) { var auth = await _localStorageService.GetItemAsync<string>("isauthenticated"); if (string.IsNullOrEmpty(auth) && args.Path.ToLower().Contains("externalauth=true")) { auth = "true"; await _localStorageService.SetItemAsStringAsync("isauthenticated","true"); } var user = (await (_authStateProvider as CustomAuthStateProvider) .GetAuthenticationStateAsync()).User; if (!string.IsNullOrEmpty(auth) && !user.Identity.IsAuthenticated) { var response = await _apiLogic.UserProfileAsync(); if (response.Message == "Success") { (_authStateProvider as CustomAuthStateProvider) .SetAuthInfo(response.UserProfile); } else if (response.Message == "Unauthorized") { await _localStorageService.RemoveItemAsync("isauthenticated"); } } }
- (Line: 5-9) Checking for 'externalauth=true' query parameter that represents the external login provider is successful, then we have to set the 'isauthenticated' local storage variable.
Add Facebook Link On Login.razor In Blazor WebAssembly App:
Now add a Facebook link or button in the Login.razor component.
Blazor_Wasm/Pages/Login.razor:
<div class="row"> <div class="col-md-6 offset-md-3"> <div> <a href="https://localhost:7235/auth/facebook-login?returnurl=https://localhost:7218/" class="nav-link btn btn-link"> Facebook </a> </div> </div> </div>
- Here URL is our Facebook API endpoint and the query parameter is our Blazor WebAssembly application URL
Hopefully, I think this article delivered some useful information about Blazor WebAssembly Cookie Authentication. using I love to have your feedback, suggestions, and better techniques in the comment section below.
Refer:
Part-1 Blazor WebAssembly Cookie Authentication[.NET 6]
Part-3 Blazor WebAssembly Cookie Authentication With Twitter
Part-3 Blazor WebAssembly Cookie Authentication With Twitter
Part-4 Blazor WebAssembly Cookie Authentication With Microsoft Account
Part-5 Blazor WebAssembly Cookie Authentication With Google Account
Part-5 Blazor WebAssembly Cookie Authentication With Google Account
Comments
Post a Comment