Thursday, May 9, 2024

BFF Back-End for Front-End Architecture

AWS AppSync and Aurora Serverless let you easily build a GraphQL powered BFF to decouple your Front-End Clients from the complex “Deep Back-End”

What?

A BFF or Back-End for Front-End Architecture or Pattern basically means that you have a dedicated Back-End for the soul purpose of serving your Front-End in the most efficient and focused way.

Why?

Especially in enterprise application you notice that the traditional Back-End is moving extremely slow. Usually because it has grown to a very fragile complexity. Connecting the Front-End to it is often done with very monolithic endpoints which are equally fragile and complex.

But times have changed and product management expects much more from Front-Ends now. They need to be modern, agile, fast iterations following customer feedback and user research. And with modern Front-End technologies like React or Flutter it is easy to achieve this.

The roadblock is the traditional Back-End. It usually takes a long time to evolve and often doesn’t match exactly what the Front-End actually demands. Which ends up in slow over-fetching and lots of unnecessary untangling of data on the Client. Which all leads to extremely slow, messy and painful Front-End development even with the most modern Front-End technologies.

So?

BFF to the rescue. Imagine having a Back-End that is dedicated and owned by the Front-End. The Front-End can evolve and dictate exactly what it needs in which shape and form from the Back-End at any time.

To achieve this the Back-End must be owned by the Front-End (developers). Whenever the Front-End changes and needs a changed response from the Back-End the Front-End developers can just change the Back-End without having to ask for permission or wait for anybody else.

How?

Here is my very opinionated way of achieving all of this.

GraphQL is the perfect query language to interface between Front-End and Back-End. It allows the Front-End to specify the exact structure of the data and interaction it expects from the Back-End if form of a flexible Schema.

Cognito is a serverless service that provides us with very flexible User Authentication and Management.

AppSync is a serverless service that provides us with highly scalable GraphQL Endpoints.

Aurora is a serverless SQL database that provides us with highly scalable Database Clusters.

Pulumi is a framework that lets you create your infrastructure as code. This allows us to completely* automate and reproduce our BFF infrastructure across multiple teams, features, products and stages with continues deployment and DevOps procedures in mind.

“Wait, that’s all on AWS” I hear you saying! And right you are, as I said this is very opinionated and I believe it is currently the only way to achieve this completely serverless and automated at an enterprise scale.

Details?

Let’s start of with creating our desired infrastructure as code.

If you haven’t already, please create a free AWS account as well as follow the Pulumi Getting Started Instructions and Pulumi AWS Setup Instructions.

Now create a new empty folder for your project, cd into it and create a new Pulumi project.

mkdir mybff
cd mybff
pulumi new aws-javascript

Configure your project to use the right AWS region and profile by editing the mybff.dev.yaml file.

config:
aws:region: us-east-1
aws:profile: mybff-aws-profile

Awesome, now we are ready to go and add our first bit of infrastructure to the index.js file.

Let’s start with some boilerplate which imports the necessary Pulumi dependencies.

Now we can add the Cognito infrastructure. This will give you a Cognito User and Identity Pool with the ability to sign in with Federated Identity Providers like Google or Facebook.

Let’s create the Aurora Serverless Database Cluster.

To create the AppSync GraphQL API let’s first add some functionality to the top of the index.js.

Notice that this will load the GraphQL Schema from a file called schema.graphql. So we have to create it.

We can add the first part of our AppSync resources now.

And now we actually have to run

pulumi up

Because unfortunately at the moment Terraform and therefore Pulumi do not know how to create AppSync DataSources that connect to Aurora Serverless. So we have to do this step manually once at this point.

  1. Go to your AWS RDS console for your Aurora Database
  2. Select your newly created Database Cluster and press Modify
  3. Under Network & Security you have to check the Data API checkbox
  4. Press Continue
  5. Choose Apply Immediately and press Modify Cluster

Now that we have enabled the Data API for your Database Cluster we can create an AppSync DataSource for it.

  1. Go to your AWS AppSync console for your GraphQL API
  2. Click your newly created GraphQL API to edit it
  3. Click on Data Sources and then on Create data source
  4. For Data source name enter graphQLDataSource_manual
  5. For Data source type select Relational database
  6. For Region choose us-east-1
  7. Select your newly created Database Cluster from the dropdown
  8. Select your newly created Secret from the dropdown
  9. Choose Existing role and select your newly created “graphQLDataSourceServiceRole” role from the dropdown

Now we can add the last bit that dynamically creates the Resolvers for the Schema.

This will create resolvers for the files it finds in the graphql/resolvers/ folder. This assumes that the filename for each resolver is Type.property.js. For example, to add a resolver for the listPets property on the Query type we create a file called Query.listPets.js in the graphql/resolvers/ folder.

Now we can run

pulumi up

again and this will create the resolver resource for us.

From now on everytime you want to create/update/delete an AppSync GraphQL Resolver you just have to create/update/delete the resolver files in the resolvers folder and run “pulumi up” again ðŸŽ‰

Awesome, now what do we have achieved so far?

  • A Cognito User and Identity Pool that manages your users and allows us to get credentials to access the AppSync GraphQL API.
  • An Aurora Serverless Database Cluster that gives us a SQL database which only costs us money when there are actually users making requests and automatically scales to “infinity”.
  • A SigV4 protected, flexible GraphQL API which lets us evolve our schema and add new resolvers fully managed as part of our infrastructure code.

Why is this awesome?

  • Our BFF is completely* automated using infrastructure as code.
  • It can be deployed even into the most complex enterprise environments with the highest compliance restrictions thanks to the inbuilt compliance and scalability of AWS services.
  • Being infrastructure as code gives DevOps total control and visibility when it comes to versioning, deployment and integration using Git branches and PRs.
  • The BFF finally empowers the Front-End and UX to evolve fast without dependencies and clear boundaries.
  • Clear boundaries also provide clean and clear integration points between the BFF and the “deep” Back-End allowing improved architecture and security.
  • In an enterprise environment it allows your teams to own their features/products, to use Git branches for different stages and automatic continues deployment to development and test environments identically to the production environments.
  • It improves the overall architecture, resilience and scalability of the whole product.

Caveats?

  • For total automation without manual interference during the initial creation we need to wait until Terraform and Pulumi have support for AppSync DataSources to Aurora Serverless and the Aurora Serverless Data API to become generally available.
  • Currently we can only do all this on AWS, but Terraform and Pulumi are cross cloud and we can reproduce this with other clouds once they have similar services available.

What are the alternatives?

The closest alternative would be to use AWS Amplify Framework. But I personally find it way too opinionated and creating way too much noise. Most importantly Amplify uses CloudFormation and this is an absolute no go for me (at the moment). CloudFormation takes away all your control and you are in Gods hands if anything goes wrong. So if you are dependent on CloudFormation you better be married to a high ranking AWS Account Manager and have an equally high ranking AWS Solution Architect as your mistress. Otherwise God help your poor soul. (CloudFormation experience deserves its own article or even an epic series of novels about war, pain and suffering).

As of May 2019 I am not aware of any other cloud solution that provides a managed GraphQL API that integrates with a serverless SQL Database. (Why this obsession with SQL? Because often NOSQL just doesn’t match your business data).

You can build your own solution by combining several different services from different providers, but this would be to messy and not realistic for enterprise solutions in my opinion.

You can build it yourself using containers, Kubernetes and other database solutions, but the amount of infrastructure you have to build and manage would be way more complex, fragile, insecure and expensive I would guess.

If you know something similar or even better to achieve this kind of BFF please leave a comment in the article. I am always keen to learn more.

Where to from here?

Now that we’ve got our BFF, we can use the identity pool to create and manage users. Navigate to the hosted sign-in page:

https://your_domain/login?response_type=code&client_id=your_app_client_id&redirect_uri=your_callback_url

This will redirect with an authentication code grant that you can exchange for user credentials using the authorization_code grant type:

With the user token you can then get access credentials from the identity pool (https://cognito-identity.us-east-1.amazonaws.com) which will allow you to access the AppSync GraphQL API as well as any other SigV4 signed AWS Service.

You first get an identity pool identity using your user pool credentials:

fetch(cognitoIdentityPoolUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-amz-json-1.1',
'X-Amz-Target': 'AWSCognitoIdentityService.GetId',
},
body: JSON.stringify({
'IdentityPoolId': identityPoolId,
'Logins': {
[`cognito-idp.${region}.amazonaws.com/${userPoolId}`]: cognitoUserPoolTokens.id_token,
},
}),

Then you can get access credentials:

fetch(cognitoIdentityPoolUrl, {
'method': 'POST',
'headers': {
'Content-Type': 'application/x-amz-json-1.1',
'X-Amz-Target': 'AWSCognitoIdentityService.GetCredentialsForIdentity',
},
'body': JSON.stringify({
IdentityId: cognitoIdentityPoolIdentityId,
'Logins': {
[`cognito-idp.${region}.amazonaws.com/${userPoolId}`]: cognitoUserPoolTokens.id_token,
},
}),

And with those you can access any AWS Service by signing your request via SigV4.

Here is a little app to test the cognito bit of your BFF:

Another advantage of this over Amplify is, that you are not limited to the languages and frameworks that Amplify supports. For example I use this with Dart in my Flutter mobile apps as well and it works just great.

Any more questions?

Please don’t hesitate and post questions and improvements or alternatives to this in the comment section.

Enjoy your new BFF ðŸ˜‰

Backend for frontend using AppSync

 


Sunday, April 28, 2024

Modernize your API Stack with GraphQL and Azure API Management

 

In this article from our series from INTEGRATE 2022, Let's take a deep dive into the session on how to modernize your API stack with GraphQL using Azure API Management, as presented by Elizabeth Barnitt, a Program Manager in Microsoft for API Management.

Elizabeth started her session with a bunch of product updates, including some features available in Public Preview.

  • Authorizations: Managed Token Store and Token Mapping for OAuth2-Secured backends
  • Private Link Integration: Simple to set up secure inbound connectivity to API Gateways available in all-tier except consumption one.
  • Managed Certificate Support: Easily and quickly secure custom domains with free certificates automatically provisioned and renewed by API Management
  • Synthetic GraphQL APIs: Easily create a GraphQL API based on your existing HTTP (SOPA or REST) APIs

The following features are generally available with Azure API Management,

  • SOAP and XML request and response validation
  • Validate Content Policy now support SOAP and XML-based Payload
  • Schemas can now define as additional, service-level resources
  • Event Grid Integration
  • Subscribe to events from API Management in Event Grid to Automate workflows and process
  • Self-Hosted Gateway V2
  • Unified codebase, support for open Telemetry, new configuration endpoint
  • WebSocket APIs
  • Publish and mediate existing WebSocket APIs in API Management
  • Developer Portal
  • Inject custom HTML code into Managed Portal with the new widget
  • Improved OpenAPI support in API reference pages and revised code samples
  • Policy Fragments
  • Define complex policies once and re-use them anywhere
  • Power Platform Integration
  • Export APIs as custom connectors for use in Power Apps and Automated Flows
  • GraphQL APIs
  • Publish and mediate existing GraphQL APIs in API Management

Why GraphQL?

REST APIs have been with us for many years now. In that time, our expectations of client applications have grown. We expect client applications to run on mobile devices with low bandwidth, yet still, be responsive. Unfortunately, REST APIs restrict us in three basic ways:

  • It takes too many requests to fulfil the data needs for a single page.
  • The REST API returns too much data for the page being rendered.
  • The client application needs to poll to get new information.

No alt text provided for this image

Elizabeth showed a sample scenario with a Microsoft Store Page, which seemed relatively simple, but when analysed further, you realize you need to make so many REST calls to load this page. This is a major problem for all modern-day applications.

There have been various attempts to solve these issues, and the current favourite is GraphQL. GraphQL is a protocol specification that explicitly solves these issues. The client application can specify the data they need to render a page in a query document that is sent as a single request to the GraphQL service. A client application can also subscribe to changes in the data through a real-time WebSocket connection, allowing notifications to happen in a timely manner.

What is GraphQL?

  • A query language for your API
  • GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data.
  • A single call to a single endpoint
  • GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.
  • Helps to optimize the network bandwidth and reduces the number of calls to different API endpoints for different information
  • Authorization
  • Extremely secure, Instead of endpoint level authorization you can authorize at field level

No alt text provided for this image

Going back to the same example, but now with GraphQL, you can see that you are just running a single query to a single endpoint, and still get all of the data that’s needed to render the page.

Why do developers love GraphQL?

  • Introspection
  • This allows developers to discover the resources available to them in the GraphQL Schema. Developers can explore the schema, they can learn about different fields, queries and types.

This makes it easy for developers to onboard, explore and build on top of the existing queries that they are using.

  • Auto Backward Compatibility
  • The front end will not be broken when API gets updated. Rather than changing the endpoint itself and breaking the existing calls, it is much more focused on not making breaking changes by not changing the existing queries but rather adding new required queries.
  • Client Generation
  • Helps to send test queries via clients like Graphical or Insomnia.
  • Self-Documenting
  • All the queries, subscriptions, and types are automatically documented in the GraphQL Schema and when you generate a client this can be explored by developers.
  • Real-time updates
  • It does support real-time updates, for example whenever query results change server can return new results to the client

How do I implement GraphQL?

Elizabeth also touched upon how can you get started with implementing GraphQL.

No alt text provided for this image

  • GraphQL Server
  • Create a GraphQL Server using a tool like Apollo Server and create your schema and resources.
  • Combine REST endpoints
  • Aggregate multiple REST endpoints to Single Endpoint, by creating GraphQL Schema and mapping those endpoints' responses to GraphQL Schema resources so that data get served.
  • GraphQL Server + Augmentation
  • This is the combination of the first two options, relying on the existing GraphQL Server and extending the information from another REST point by attaching them to GraphQL Schema and resolving those using resolvers when queries get called for data.

Steps to Build GraphQL

No alt text provided for this image

  • Start with a Schema: It outlines different types, resources and how information gets processed
  • Define Resolvers: It helps to map the types and fields to the source of the information it can serve to. For example what endpoints or APIs serve the request.
  • Link resolvers to data sources: The actual implementation to link defined resolvers to the data sources.

GraphQL in Azure API Management

There are two ways to implement GraphQL via Azure APIM.

GraphQL Pass-through

No alt text provided for this image

You can use this when you already have an existing GraphQL API, which then you can plug in thru Azure APIM, leveraging all the existing benefits of API Management—including security, observability, and reduced latency—for their GraphQL APIs while also adding GraphQL-specific features such as a query test console, query validation, field-based authorization, and query depth and size restriction.

Synthetic GraphQL

No alt text provided for this image

With this second approach, Synthetic GraphQL allows you to easily create a GraphQL API based on your existing HTTP (SOAP or REST) APIs. This allows you to quickly upgrade your API to support modern client application development without affecting your existing infrastructure.

  • With this availability, you can:
  • Change your existing APIs into GraphQL to support modern client application development. Build a GraphQL API from existing SOAP, REST, and other HTTP APIs.
  • Augment your existing GraphQL API with third-party APIs such as Microsoft Graph, Dynamics, Shopify, and Zendesk.
  • Build your GraphQL API

With the preview GraphQL resolvers, you can remove the GraphQL backend completely and define a complete set of resolvers to fulfil any query. The resolvers can easily be written in Azure Functions or take advantage of REST APIs across M365, Azure, your own services, or third-party services such as Shopify, Marketo, or ServiceNow. The Synthetic GraphQL service will run all the required requests and combine the results into the response to the user.

No alt text provided for this image

After explaining the Synthetic GraphQL on Azure APIM, Elizabeth ran thru a really cool demo using SpaceX GraphQL APIs and Azure APIM. She also demonstrated how convenient it is to extend the existing GraphQL with additional HTTP requests.

API Management protects against the top 5 OWASP GraphQL security issues

Briefly, the top 5 security issues with GraphQL were discussed and she also showed how those issues can be mitigated with Azure APIM.

No alt text provided for this image

Key Takeaways / Cluster Take

  1. Use GraphQL to extend the features without losing your backend APIs investments
  2. Production GraphQL is easier and more secure with Azure API Management.
  3. Looking back at Toon Vanhoutte's session on APIM, he mentioned the Layered API pattern with an Experience layer that customises lower-level APIs for specific audiences and clients. Rather than hand-rolling these APIs, we can see great opportunities for organisations to leverage the newly-announced Synthetic GraphQL features of Azure APIM to build on existing investment in REST and SOAP APIs and expose a flexible single endpoint to API clients. Synthetic GraphQL APIs will allow API clients to query APIs in a self-service manner to retrieve just the data they need, all without compromising on governance or data security..

If you would like to schedule a workshop to learn more about how you can leverage the Azure APIM to connect with your existing APIs and build a GraphQL on top of them, please reach out to us via our LinkedIn Page or email us at cluster.uk.info@reply.com and we will be happy to guide you on your journey to Azure Adoption.

Your First Microservice in .NET 6

Very simple way to start writing microservices... It is just writing one service and don't cover communication of microservices  or  dep...