Mastering BFF Patterns: How to Simplify Authentication for Secured User Experiences

Mastering BFF Patterns | Blog | Nitor Infotech
×

About the author

Nikhil Kulkarni
Architect
Nikhil Kulkarni is an Architect at Nitor Infotech with more than 9 years of experience. He plays a major role in full stack development. He ... Read More

Mobile App Development   |      22 Nov 2023   |     14 min  |

In the current landscape of commerce, software businesses are vigorously working towards achieving the goal of providing user experiences that are both seamless and secure. Thus, extending their efforts across a diverse array of platforms.

However, they often grapple with disjointed and vulnerable authentication processes moving ahead. This leads to – security risks, development complexities, and customer distrust.

Worry not, I’ve got you covered.

In this blog, I’ll help you understand authentication and explain why using the BFF Pattern is beneficial. Furthermore, I will guide you through the implementation process for authentication while offering additional insights on the subject.

Sounds exciting? Well then, keep reading!

Understanding Authentication

Authentication is the process of verifying the identity of a user or client application seeking access to a specific backend service. It ensures that only authorized users or applications can interact with the backend and access protected resources.

Authentication may include credential validation, token verification, and other security measures to establish trust and provide secure access.

While authentication is crucial, it can be complex to implement, especially in modern applications that span multiple devices and platforms.

The BFF pattern addresses this complexity.

How? Let’s understand from the next section.

Advantages of using BFF Pattern in Authentication

Here are the advantages of using the BFF Pattern in Authentication:

  1. Enhanced Security: By centralizing authentication logic in a dedicated BFF service, security measures like access control and encryption can be implemented more effectively, reducing vulnerabilities.
  2. Tailored User Experience: BFF allows developers to create a customized authentication flow for each frontend application, resulting in a seamless, user-friendly experience.
  3. Scalability: The BFF pattern optimizes authentication processes for scalability, making it ideal for applications with rapidly growing user bases.
  4. Flexibility: Different frontend applications may have varying authentication requirements. BFF offers the flexibility to cater to each application’s unique needs.
  5. Reduced Complexity: Separating authentication logic from the frontend simplifies the overall architecture, making it easier to manage and maintain.

Now that you’ve got the fundamentals of BFF in authentication under your belt, let’s explore how to put it into action using a real-world example.

Implementation of BFF for Authentication

Typically, token-based authentication is the norm, where tokens are generated on the front end using specific libraries. These tokens serve as keys to authenticate requests to the API backend. However, storing these tokens in the browser can pose security risks due to potential vulnerabilities.

Here comes BFF, with which we can eliminate the need for browser-stored tokens. Instead, we leverage cookies and shift the core token generation logic to the server side, specifically within the BFF layer.

This implementation can be seamlessly achieved using libraries like Duende.

In the following example, we’ll dive deeper into the BFF pattern, exploring its significance in simplifying authentication processes in 9 steps:

1. Set up the following configurations within your identity provider (we’ve utilized Auth0 in this instance):

Configuration Table

Get the below details from the Identity Provider after configuring the setup:

Authority
Client ID
Client Secret

2. Create a new project with the template “ASP.Net Core with Angular.”

ASP.Net Core with Angular

It will create a project with the below structure:

API Layer

This project is structured with an API layer (acting as the backend) and a ClientApp (serving as the Angular frontend).

3. Further, proceed with the installation of the “Duende.BFF” NuGet package.

installation of the _Duende.BFF_ NuGet package

4. Within the ClientApp directory, locate the “proxy.conf.js” file, and insert the following proxy URLs. These URLs facilitate the forwarding of HTTP requests to the BFF server in the backend.

const PROXY_CONFIG = [ 
{ 
context: [ 
"/weatherforecast", 
"/bff", 
"/signin-oidc", 
"/signout-callback-oidc" 
], 
target: target, 
secure: false, 
headers: { 
Connection: 'Keep-Alive' 
} 
}
]

5. Next, in Program.cs, configure authentication (as cookies) like this:

// Configure ASP.NET Authentication
.AddAuthentication(options =>
{ 
options.DefaultScheme = "Cookies"; 
options.DefaultChallengeScheme = "oidc"; 
options.DefaultSignOutScheme = "oidc";
})
// Configure ASP.NET Cookie Authentication
.AddCookie("Cookies", options =>
{ 
options.ExpireTimeSpan = TimeSpan.FromHours(8); 
options.SlidingExpiration = false; 
options.Cookie.Name = "BFF_Test_SPA"; 
// When the value is Strict the cookie will only be sent along with "same-site" requests. 
options.Cookie.SameSite = SameSiteMode.Strict;
})

6. Once done, setup the OpenID connect protocol configuration as mentioned:

// Configure OpenID Connect
.AddOpenIdConnect("oidc", options =>
{ 
options.Authority = builder.Configuration["Auth0:Authority"]; 
options.ClientId = builder.Configuration["Auth0:ClientId"]; 
options.ClientSecret = builder.Configuration["Auth0:ClientSecret"]; 

options.ResponseType = OpenIdConnectResponseType.Code; 
options.ResponseMode = OpenIdConnectResponseMode.Query; 

// Go to the user info endpoint to retrieve additional claims after creating an identity from the id_token 
options.GetClaimsFromUserInfoEndpoint = true; 
// Store access and refresh tokens in the authentication cookie 
options.SaveTokens = true; 

options.Scope.Clear(); 
options.Scope.Add("openid"); 
options.Scope.Add("profile"); 
options.Scope.Add("offline_access");
});

In this scenario, we are using Auth0 as the identity provider for authentication. You can obtain essential configuration values such as “Authority,” “ClientId,” and “ClientSecret” from there.

The code snippet within the OpenIdConnectEvent is designed to facilitate a secure logout process from the Identity server while also clearing cookies in the browser.

options.Events = new Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectEvents
{ 
OnRedirectToIdentityProviderForSignOut = (context) => 
{ 
// Set PlusAuth logout endpoint 
var logoutUri = $"{builder.Configuration["Auth0:Authority"]}/oidc/logout?client_id={builder.Configuration["Auth0:ClientId"]}"; 

var postLogoutUri = context.Properties.RedirectUri; 
if (!string.IsNullOrEmpty(postLogoutUri)) 
{ 
if (postLogoutUri.StartsWith("/")) 
{ 
postLogoutUri = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + postLogoutUri; 
} 
// Return index page after logout 
logoutUri += $"&post_logout_redirect_uri={Uri.EscapeDataString(postLogoutUri)}"; 
} 

context.Response.Redirect(logoutUri); 
context.HandleResponse(); 

return Task.CompletedTask; 
}
};

7. Next up, register for BFF services:

// Register BFF services and configure the BFF middleware
builder.Services.AddBff();
builder.Services.AddAuthorization(); 

// configure below steps after builder.Build()
app.UseAuthentication();
app.UseBff();
app.UseAuthorization();
app.MapBffManagementEndpoints();

8. In the frontend application, offer the URL “/bff/login” to initiate the login process. When a user selects “login,” they will be directed to the Auth0 login page for authentication.

Upon successful authentication, browser cookies will be added.

browser cookies

When utilizing these cookies to make an API call within our solution, the outcome is as follows:

API call

This occurs because we must include ‘X-Csrf = 1’ in our request header. ‘X-Csrf’ stands for Cross-Site Request Forgery, and we need to set its value to ‘true’ to verify that the request is originating from an authorized source.

setting value to 'true'

9. Now to make API calls from our frontend application, we must create an interceptor responsible for including this in the request header. This is how you can do it:

@Injectable()
export class CsrfHeaderInterceptor implements HttpInterceptor { 

constructor() {} 

intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { 
if (!request.headers.has("X-CSRF")) { 
request = request.clone({ 
headers: request.headers.set("X-CSRF", "1"), 
}); 
} 

return next.handle(request); 
}
}

By doing this, requests from the frontend app will be authorized and carry cookies, allowing for authentication and appropriate responses.

Note: The Duende library offers an endpoint at “/bff/user” for retrieving user session details.

authorization

After a user logs out from the system, they will be directed to the Identity Provider’s logout page to complete the logout process. Also, browser cookies will also be cleared:

Identity Provider's logout page

This way we can leverage the Duende library for implementing authentication using the BFF pattern.

Onwards to some of the best practices!

Best Practices for BFF Authentication

While BFF simplifies authentication, adhering to best practices is essential to maximize its effectiveness and security:

  1. Use Secure Protocols: Implement HTTPS to encrypt data in transit, safeguarding user credentials and sensitive information from eavesdropping.
  2. Strong Password Policies: Enforce strong password policies to enhance user account security.
  3. Multi-Factor Authentication: Encourage or require users to enable multi-factor authentication for an additional layer of protection.
  4. Regular Security Audits: Conduct periodic security audits and penetration testing to identify vulnerabilities and weaknesses in the authentication process.
  5. Keep Software Updated: Ensure that all software components, including the BFF service, libraries, and frameworks, stay up to date with the latest security patches.
  6. User Education: Educate users about security and encourage them to follow best practices, such as password hygiene and account protection.

So, by following these best practices and implementing BFF effectively, developers can create user-friendly and secure authentication experiences. Thus, instilling confidence in users and strengthening the applications built by them.

Learn how we helped an insurance company develop a mobile app for easy access to digital medical cards.

To align your organization with cutting-edge technologies,  connect with Nitor Infotech. We’re here to help you embrace the future.

subscribe image

Subscribe to our
fortnightly newsletter!

we'll keep you in the loop with everything that's trending in the tech world.

We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it.