Microsoft Workloads on AWS

Embedding Amazon QuickSight analytics in .NET applications

In this blog post for .NET developers, we will discuss step-by-step instructions on how to embed Amazon QuickSight analytics in your .NET applications using QuickSight APIs and make them available for Amazon Cognito authenticated users.

Amazon QuickSight Embedded analytics is a feature of QuickSight that applies data analytics to the applications used by your end users, analysts, and business leaders. QuickSight Embedded provides a way to surface the right data insights at the right time on the right application, all without the need to context switch between applications. Embedded visuals and dashboards get updated automatically when the source data changes, giving a real-time experience to users.

QuickSight for Embedded analytics

QuickSight supports several ways to embed advanced analytics capabilities into your web applications.:

  • A full authoring experience for registered users by embedding the QuickSight console
  • By integrating existing QuickSight dashboards and visuals—for registered and anonymous users
  • Amazon QuickSight Q, a machine learning-based feature, to answer business questions—for registered and anonymous users

From a developer perspective, you have two options to embed analytics into your applications:

  • QuickSight APIs will give you the flexibility to share dashboards and visuals, provide the full functionality of the QuickSight console, and include the Amazon QuickSight Q search bar with authenticated internal users or anonymous public users.
  • One-click enterprise embedding will give you a static embed code that will let you share a QuickSight dashboard or a visual with authenticated internal users. We won’t be talking about this option in this post. You can go through Amazon QuickSight 1-click public embedding blog post to learn more about this feature.

In the following sections, we will discuss step-by-step instructions on how to use the AWS SDK for .NET to work with the QuickSight APIs to embed dashboards and visuals in your .NET application for authenticated users.

Embedding QuickSight dashboards into your .NET application for authenticated users

 Prerequisites

Embed dashboards for registered users

In this section, we will walk you through the steps of setting up and embedding QuickSight dashboards for authenticated users in your ASP.NET Core MVC web application. Embedding QuickSight visuals into your applications makes it convenient for your end users to analyze the data and make decisions without ever leaving the application. This provides a seamless user experience and avoids having to re-authenticate into any other applications using separate credentials.

By following the approach described in this post, you can use the QuickSight APIs to register QuickSight users at the point of access and generate a secure dashboard link unique to a user for embedding into your application web UI.

Setting up the permissions in IAM

Create an IAM role for accessing QuickSight

To access QuickSight APIs, we need to create an IAM role with the necessary permissions that your application can assume on behalf of the application user. This section provides guidance on setting up the role and associating the permissions.

The IAM role needs to grant permissions to list the existing QuickSight users (quicksight:ListUsers), provision first-time users in QuickSight (quicksight:RegisterUser), and retrieve the embedded dashboard URL for provisioned QuickSight users (quicksight:GenerateEmbedUrlForRegisteredUser).

The following is a sample policy that grants these permissions:

QuickEmbedRolePermissionPolicy.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "quicksight:DescribeUser",
                "quicksight:ListUsers",
                "quicksight:RegisterUser"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "quicksight:GenerateEmbedUrlForRegisteredUser",
            "Resource": [
                "arn:aws:quicksight:us-east-1:<Insert Account ID>:user/*",
                "arn:aws:quicksight:us-east-1:<Insert Account ID>:dashboard/<Insert Dashboard ID>",
                "arn:aws:quicksight:us-east-1:<Insert Account ID>:namespace/default"
            ]
        }
    ]
}

After creating the policy, you can create the IAM role via the AWS Management Console or the AWS Command Line Interface (AWS CLI), as shown below:

echo '{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "<Insert Account ID>"
            },
            "Action": "sts:AssumeRole",
            "Condition": {}
        }
    ]}' > trustpolicy.json
    
aws iam create-role --role-name QuickSightEmbedRole --assume-role-policy-document file://trustpolicy.json

You can then attach the permissions policy you created earlier to this role, as shown below:

aws iam attach-role-policy --role-name QuickSightEmbedRole  --policy-arn arn:aws:iam::<Insert Account ID>:policy/QuickEmbedRolePermissionPolicy

Create a policy and attach to Application Identity

Next, you will create a policy giving permission to assume the role QuickSightEmbedRole, which you created in the previous step.

The following is a sample policy that you will need:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::<Insert Account ID>: role/QuickSightEmbedRole"
        }
    ]
}

You can then attach this policy to your application’s IAM identity through the AWS CLI or the IAM console. Based on where you deploy the application, you may attach the policy to the roles associated with Amazon Elastic Compute Cloud (Amazon EC2) instance profile, AWS Elastic Beanstalk instance profile, Amazon Elastic Container Service (Amazon ECS) Task ,etc. For this example, we will host our ASP .NET application on Amazon EC2 instances and the role will be assumed by the instance profile.

By assuming the QuickSightEmbedRole role, your application can securely call the QuickSight APIs to retrieve the existing QuickSight users, create new users (if the authenticated user does not exist currently), and generate a dashboard URL unique to a single user.

Modify your .NET application code

Get the QuickSight dashboard URL on your application server

In your .NET solution, add the following two AWS SDK NuGet packages via the NuGet package manager:

  • AWSSDK.QuickSight
  • AWSSDK.SecurityToken

In the MVC project, add a controller (we are using QuickSightController in this example). In the default index action of the controller, add code that does the following:

Step 1: Assuming the IAM role

AssumeRoleAsync API is invoked passing the username and the ARN of the role to assume. The API allows the application to assume the IAM role created earlier (QuickSightEmbedRole) on the user’s behalf by invoking the AWS Security Token Service (AWS STS). The API call returns temporary credentials consisting of an access key ID, secret access key, and a security token, which your application will use for the rest of the QuickSight API operations mentioned below.

Step 2: Check if the user exists in QuickSight

Before loading the dashboard for the authenticated user, invoke the QuickSight ListUsersAsync API to retrieve the list of all QuickSight users and check if the application user already exists.

Step 3: Provision the QuickSight user

If the application user does not exist in the list of QuickSight users, you can do a just-in-time provisioning of the user by invoking the QuickSight RegisterUserAsync API. The username of the newly registered QuickSight user will be a combination of the IAM role name and the role session name. In this example, the username will be QuickSightEmbedRole/qsbloguser@example.com.

Step 4: Generate and retrieve the embedded URL

Finally, invoke the QuickSight GenerateEmbedUrlForRegisteredUserAsync API to get a signed URL to embed the QuickSight experience in your website. The API lets you specify the list of allowed domains where the generated URL can be embedded, which overrides the static domains that are configured in the QuickSight console.

Here is the example code that addresses these steps:

    public class QuickSightController : Controller
    {
        private static readonly Amazon.RegionEndpoint REGION = Amazon.RegionEndpoint.USEast1;//Region of your QuickSight account
        private static readonly string awsAccountID = "Insert Account ID here";
        private static readonly string qsNamespace = "default";
        private const int assumeRoleDuration = 1600;
        private static readonly string iamRole = "arn:aws:iam::" + "Insert Account ID here" + ":role/QuickSightEmbedRole";//you can use sdk api to fetch this


        [Authorize]
        [HttpGet]
        public IActionResult Index()
        {
            var model = new Models.QSDashboardModel();
            var userName = HttpContext.User.Claims.Where(c => c.Type == "cognito:username").FirstOrDefault().Value;

            // Step 1: Assume the role 
            var credentials = AssumeRole(userName, iamRole);
            var quicksight = new AmazonQuickSightClient(credentials, REGION);

            // Step 2: Retrieve the list of users
            var qsUserName = "QSEmbedRoleIAMUser/" + userName;
            var list = RetrieveListQSUsers(quicksight);
            if (list.Where(l => l.UserName == qsUserName).Count() > 0)
            {
                user = list.Where(l => l.UserName == qsUserName).FirstOrDefault();
            }
            else
            {
                /* Step 3: Provision the QuickSight user if the user does not exist */
                user = RegisterQSUser(quicksight, userName, iamRole);
            }

            /*step 4: Retrieve the Quicksight embed url*/
            model.embedURL = RetrieveQSEmbedURL(quicksight, user.Arn);
            return View(model);

        }


        public Credentials AssumeRole(string userName, string iamRole)
        {
            var assumeRoleReq = new AssumeRoleRequest()
            {
                DurationSeconds = assumeroleDuration, //the duration, in seconds, of the role session
                RoleSessionName = userName, //unique identifier for the assumed role session. In this example, qsbloguser@example.com
                RoleArn = iamRole //ARN of the IAM role to assume
            };

            // Application identity is attached to this client from your application configuration.
            var stsclient = new Amazon.SecurityToken.AmazonSecurityTokenServiceClient(REGION);
            var credentials = stsclient.AssumeRoleAsync(assumeRoleReq).Result.Credentials;
            return credentials;
        }

        /*Step 2: Retrieve list of users*/
        public List<User> RetrieveListQSUsers(AmazonQuickSightClient qsclient)
        {
            var userlistRequest = new ListUsersRequest
            {
                Namespace = qsNamespace,
                AwsAccountId = awsAccountID
            };
            var lstUsersResp = qsclient.ListUsersAsync(userlistRequest);
            var list = lstUsersResp.Result.UserList;
            return list;
        }

        /* Step 3: Provision the QuickSight user */
        public User RegisterQSUser(AmazonQuickSightClient qsclient, string userName, string iamRole)
        {
            var registerUserResp = qsclient.RegisterUserAsync(new RegisterUserRequest
            {
                Email = userName,
                IdentityType = IdentityType.IAM,
                UserRole = UserRole.READER,
                IamArn = iamRole//ARN of the IAM role - QuickSightEmbedRole
        SessionName = userName,//qsbloguser@example.com
                AwsAccountId = awsAccountID,
                Namespace = qsNamespace
            }).Result;
            var qsuser = registerUserResp.User;
            return qsuser;
        }

        /*Step 4: Retrieve the QuickSight embed url*/
        public string RetrieveQSEmbedURL(AmazonQuickSightClient qsclient, string userArn)
        {
            var registeredUserEmbeddingExperienceConfiguration = GetDashboardEmdeddingConfiguration("Insert Dashboard ID here");


            var allowedDomains = new string[] { "example.com" }; // pass the application domains here
            var embedURL = qsclient.GenerateEmbedUrlForRegisteredUserAsync(new GenerateEmbedUrlForRegisteredUserRequest
            {
                AwsAccountId = awsAccountID,
                ExperienceConfiguration = registeredUserEmbeddingExperienceConfiguration,
                UserArn = userArn,
                AllowedDomains = allowedDomains.ToList(),
                SessionLifetimeInMinutes = 100, //how many minutes the session is valid
            }).Result.EmbedUrl;
            return embedURL;
        }


        //Dashboard embedding experience
        public RegisteredUserEmbeddingExperienceConfiguration GetDashboardEmdeddingConfiguration(string DashboardId)
        {
            var config = new RegisteredUserDashboardEmbeddingConfiguration()
            {
                InitialDashboardId = DashboardId
            };
            RegisteredUserEmbeddingExperienceConfiguration registeredUserEmbeddingExperienceConfiguration
                     = new RegisteredUserEmbeddingExperienceConfiguration
                     {
                         Dashboard = config
                     };
            return registeredUserEmbeddingExperienceConfiguration;
        }

        //Fine grained visual embedding experience
        public RegisteredUserEmbeddingExperienceConfiguration GetVisualEmdeddingConfiguration(string DashboardID, string sheetID, string visualID)
        {
            var dashboardVisualId = new DashboardVisualId()
            {
                // The DashboardId, SheetId, and VisualId can be found in the IDs for developers section of the Embed visual pane of the visual's on-visual menu of the Amazon QuickSight console.
                DashboardId = DashboardID,
                SheetId = sheetID,
                VisualId = visualID
            };
            var config = new RegisteredUserDashboardVisualEmbeddingConfiguration()
            {
                InitialDashboardVisualId = dashboardVisualId
            };
            RegisteredUserEmbeddingExperienceConfiguration registeredUserEmbeddingExperienceConfiguration
                     = new RegisteredUserEmbeddingExperienceConfiguration
                     {
                         DashboardVisual = config
                     };
            return registeredUserEmbeddingExperienceConfiguration;
        }
    }

Embed the URL

You can use the QuickSight Embedding SDK to embed the dashboard URL generated in the previous section in your MVC HTML view.

The following code shows how to embed the URL:

function embedDashboard() {
        var containerDiv = document.getElementById("embeddingContainer");
        var inputURL = document.getElementById("embedURL").value;
                
        var options = {
                    
            url: inputURL, // replace this url with the one generated via embedding API
            container: containerDiv,
            parameters: {
                country: "United States"
            },
            scrolling: "no",
            height: "600px",
            width: "1000px",
            locale: "en-US",
            footerPaddingEnabled: true,
            defaultEmbeddingVisualType: "TABLE"
        };
        session = QuickSightEmbedding.embedDashboard(options);
        session.on("error", onError);
    }

Embedded QuickSight Dashboard

Figure 1: Sample Embedded QuickSight Dashboard

In this blog post, we have used the QuickSight .NET SDK to embed a full dashboard experience for its users, including the QuickSight controls, allowing them to interactively select the data being displayed in the visual, perform what-if analyses, and drill through from one visual to another.

Fine-grained visual embedding

You can use the same QuickSight API, GenerateEmbedUrlForRegisteredUserAsync, to embed individual visualizations from various QuickSight dashboards, thus delivering an integrated experience for your users. The API allows you to pass the visual ID and the dashboard ID of the dashboard visual as a RegisteredUserEmbeddingExperienceConfiguration parameter. (Refer to GetVisualEmdeddingConfiguration in the code sample in the previous section).

Pricing

The pricing for QuickSight depends on the subscription type, user type, and other features that you need for your use case. To learn more about how the pricing works with QuickSight, visit the pricing page for the service.

Cleanup

If you’ve followed along and created resources in your AWS account that you don’t want to retain, it is important to go back and delete them so you won’t incur any recurring charges. Here are the resources created in this example that you may need to delete:

  • QuickSight registered user(s). You can follow the instructions in the user guide to delete the user accounts.
  • Infrastructure where you deployed your .NET application.
  • Application user in Amazon Cognito. We are pointing this out to show an abundance of caution because you get free 50,000 monthly active users (MAU) with AWS Free Tierfor Amazon Cognito. Refer to the pricing docs for more detail.
  • Finally, if you don’t need the QuickSight subscription, consider deleting the account.

Conclusion

In this blog post, we have discussed how you can set up embedded dashboards and visuals for authenticated users of your .NET application. By embedding analytics into your applications, you can give the analysts and decision makers in your organization access to the right data and insights from the applications they use without having to switch between applications. Amazon QuickSight provides the flexible options you need to embed analytics in your web applications.

To learn more about developing with Amazon QuickSight, read the User Guide.


AWS can help you assess how your company can get the most out of cloud. Join the millions of AWS customers that trust us to migrate and modernize their most important applications in the cloud. To learn more on modernizing Windows Server or SQL Server, visit Windows on AWSContact us to start your modernization journey today.

Renuka Krishnan

Renuka Krishnan

Renuka Krishnan is a Partner Solutions Architect at Amazon Web Services in Atlanta, GA. She has over 15 years of experience architecting and implementing solutions with a focus on Microsoft technologies. She is passionate about helping partners and customers migrate, modernize and optimize their Microsoft workloads on AWS.

Jagadeesh Chitikesi

Jagadeesh Chitikesi

Jagadeesh is a Sr. Microsoft Specialist Solutions Architect at AWS. He worked as a developer and an architect with enterprises of all sizes across healthcare, finance, retail, utility, and government for the last 20 years. He is passionate about cloud and all the innovation happening at AWS.