<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stefan Weber</title>
    <description>The latest articles on DEV Community by Stefan Weber (@stefan76).</description>
    <link>https://dev.to/stefan76</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1150061%2F08c05ef6-8ffe-4a8f-96e6-1d579d6bad79.jpeg</url>
      <title>DEV Community: Stefan Weber</title>
      <link>https://dev.to/stefan76</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stefan76"/>
    <language>en</language>
    <item>
      <title>Get Started with OutSystems and Amazon Bedrock</title>
      <dc:creator>Stefan Weber</dc:creator>
      <pubDate>Fri, 03 Nov 2023 05:43:09 +0000</pubDate>
      <link>https://dev.to/aws-builders/get-started-with-outsystems-and-amazon-bedrock-3ebi</link>
      <guid>https://dev.to/aws-builders/get-started-with-outsystems-and-amazon-bedrock-3ebi</guid>
      <description>&lt;p&gt;In this guide, we will explore the essential steps it takes to build your first or next Generative AI application with Amazon Bedrock in OutSystems. Specifically, you will learn how to set up Amazon Bedrock and your OutSystems application to utilize one or more Foundational Models for Text-to-Text and Text-to-Image generation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Amazon Bedrock
&lt;/h2&gt;

&lt;p&gt;Amazon Bedrock is a fully AWS managed service that gives you unified access to a selection of foundation models (FMs) from leading AI companies. By the time of writing Bedrock features models from &lt;a href="https://www.ai21.com/"&gt;AI21 Labs&lt;/a&gt;, &lt;a href="https://www.anthropic.com/"&gt;Anthropic&lt;/a&gt;, &lt;a href="https://cohere.com/"&gt;Cohere&lt;/a&gt;, &lt;a href="https://stability.ai/"&gt;Stability AI&lt;/a&gt;, and &lt;a href="https://aws.amazon.com/bedrock/titan/"&gt;Amazon&lt;/a&gt; and you can expect more models to be added over time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/bedrock/"&gt;Build Generative AI Applications with Foundation Models – Amazon Bedrock – AWS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Amazon Bedrock provides lots of additional and easy to use features. The possibility of privately customizing (fine-tune) any foundation model with your own data without writing a single line of code is just one example. Find out more about Amazon Bedrock features, foundation models and use-cases by clicking on the link above.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;that at the time of writing not all additional features are yet available.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Preparations
&lt;/h2&gt;

&lt;p&gt;Before we delve into the technical aspects, there are some preliminary tasks that need to be addressed.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS Bedrock Runtime Forge component and Demo application
&lt;/h3&gt;

&lt;p&gt;Download and install my AWS Bedrock Runtime Integration component from OutSystems Forge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.outsystems.com/forge/component-overview/16561/aws-bedrock-runtime"&gt;AWS Bedrock Runtime - Overview | OutSystems&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure that you also download the attached Demo application, which we will use to walk through the technical implementation of the Integration component.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Identity and Access Management (IAM) User
&lt;/h3&gt;

&lt;p&gt;To interact with an Amazon Bedrock Foundation Model we need an IAM user account with permission to invoke model APIs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the AWS console switch to &lt;strong&gt;Identity and Access Management&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new policy &lt;strong&gt;BedrockInvokeModel&lt;/strong&gt; with the following permissions&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VisualEditor0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bedrock:InvokeModel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:bedrock:*::foundation-model/*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This grants permission to invoke any Foundation Model in any region. In a production environment you may want to further restrict this to only specific models and regions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a new user &lt;strong&gt;os-bedrock&lt;/strong&gt; (programmatic access only) and attach the &lt;strong&gt;BedrockInvokeModel&lt;/strong&gt; policy directly to the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next &lt;strong&gt;Create an Access Key&lt;/strong&gt; for the &lt;strong&gt;os-bedrock&lt;/strong&gt;. Make sure to copy the &lt;strong&gt;Access Key&lt;/strong&gt; and &lt;strong&gt;Secret Access Key&lt;/strong&gt; before you proceed. We will need both in a bit.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Amazon Bedrock
&lt;/h3&gt;

&lt;p&gt;Before you can use a Foundation Model of Amazon Bedrock you need to explicitly request access to a model.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In AWS console switch to &lt;strong&gt;Amazon Bedrock&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;All features of Amazon Bedrock are made available first in US East N. Virginia (us-east-1) region.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the left menu select Model Access&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;strong&gt;Edit&lt;/strong&gt; and select all Foundation Models you want to request access to.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To try out all examples from the demo application you need to request access to the following models&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Amazon Titan Embeddings G1 — Text&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anthropic Claude&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stability AI Stable Diffusion XL&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; that it can take up to 24 hours until access to a specific model is granted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h1Rjc3CN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ccx2n8qrw8z01qxtke.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h1Rjc3CN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ccx2n8qrw8z01qxtke.png" alt="Model Access" width="800" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo Application
&lt;/h3&gt;

&lt;p&gt;Make sure that you have downloaded the Demo application that is attached to the &lt;strong&gt;AWS Bedrock Runtime&lt;/strong&gt; Forge component.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Open &lt;strong&gt;Service Center&lt;/strong&gt; and under &lt;strong&gt;Factory — Modules&lt;/strong&gt; open the &lt;strong&gt;AWSBedrockDemoApplication&lt;/strong&gt; module.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Switch to the &lt;strong&gt;Site Properties&lt;/strong&gt; tab and fill in the values for &lt;strong&gt;AWSAccessKey&lt;/strong&gt;, &lt;strong&gt;AWSSecretAccessKey&lt;/strong&gt; and &lt;strong&gt;AWSRegion&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure to use the &lt;strong&gt;system name of the region&lt;/strong&gt; where you provisioned the foundation models (e.g. us-east-1 for US East N. Virginia).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As usual the security reminder here&lt;/strong&gt;: Secrets shouldn’t be stored in site properties but instead in a secure credentials management solution like AWS Secrets Manager or Hashicorp Vault.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Try the Demo
&lt;/h2&gt;

&lt;p&gt;With all preparational steps completed you should now be able to try out the demo application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For now, the demo application allows you to try out Text-To-Text generation with Anthropics Claude Version 2 and Cohere Command models, Text-to-Image generation with Stability.AIs Stable Diffusion XL model and Text-to-Embeddings with Amazons Titan Embeddings G1 model.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Start with asking Anthropic Claude Version 2 something. For example, &lt;em&gt;“Human: Why is OutSystems the leading Low-Code application platform on the market.&lt;br&gt;&lt;br&gt;
Assistant:”.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure to read the &lt;strong&gt;Prompt Design&lt;/strong&gt; Section of Anthropic Claude documentation on how to construct prompts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://docs.anthropic.com/claude/docs/introduction-to-prompt-design"&gt;Introduction to Prompt Design (&lt;/a&gt;&lt;a href="http://anthropic.com"&gt;anthropic.com&lt;/a&gt;&lt;a href="https://docs.anthropic.com/claude/docs/introduction-to-prompt-design"&gt;)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6OacKwYu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/flyu24irqwstz09rliwy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6OacKwYu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/flyu24irqwstz09rliwy.png" alt="Anthropic Claude" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next generate an image from text with the &lt;a href="http://Stability.AI"&gt;Stability.AI&lt;/a&gt; Stable Diffusion XL model. I used &lt;em&gt;“Debris floating in space”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v9T9uvsI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/88mvie0viq6egoxhk9e6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v9T9uvsI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/88mvie0viq6egoxhk9e6.png" alt="Image Generation" width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lastly turn text into vector embeddings of 1536 dimension with Amazons Titan Embeddings G1 model. I used the following text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Amazon Bedrock is a fully managed service that offers a choice of high-performing foundation models (FMs) from leading AI companies like AI21 Labs, Anthropic, Cohere, Meta, Stability AI, and Amazon via a single API, along with a broad set of capabilities you need to build generative AI applications, simplifying development while maintaining privacy and security. With Amazon Bedrock’s comprehensive capabilities, you can easily experiment with a variety of top FMs, privately customize them with your data using techniques such as fine-tuning and retrieval augmented generation (RAG), and create managed agents that execute complex business tasks—from booking travel and processing insurance claims to creating ad campaigns and managing inventory—all without writing any code. Since Amazon Bedrock is serverless, you don't have to manage any infrastructure, and you can securely integrate and deploy generative AI capabilities into your applications using the AWS services you are already familiar with.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Lky9wdQr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f5tfl16kbklzxsdx5gtn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lky9wdQr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f5tfl16kbklzxsdx5gtn.png" alt="Embeddings" width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The demo outputs only the first ten dimensions. Titan Embeddings G1 generate vector embeddings with a fixed length of 1536 dimension.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vector embeddings are essential for adding semantic search and Retrieval Augmented Generation. You can read more about the two topics in my articles&lt;/p&gt;

&lt;p&gt;&lt;a href="https://itnext.io/outsystems-with-openai-embeddings-and-qdrant-vector-database-find-similar-fbd9a5e4760a"&gt;OutSystems, OpenAI Embeddings and Qdrant Vector Database — Find Similar | by Stefan Weber | Aug, 2023 | Medium | ITNEXT&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://itnext.io/outsystems-openai-embeddings-and-qdrant-vector-database-answer-right-5b511764e6fa"&gt;OutSystems, OpenAI Embeddings and Qdrant Vector Database — Answer Right | by Stefan Weber | Aug, 2023 | ITNEXT&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Walkthrough
&lt;/h2&gt;

&lt;p&gt;One of the major advantages of Amazon Bedrock is that it unifies accessing multiple foundation models. If you know how to interact with one model, you know how to interact with all models — besides some model specific parameters.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;AWS Bedrock Runtime&lt;/strong&gt; Forge component abstracts the unified model invocation API of Bedrock making it extremely simple to use a foundation model.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Open the Demo application in Service Studio&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the Logic Tab under Server Actions open the &lt;strong&gt;AnthropicClaudePrompt&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;AnthropicClaudePrompt&lt;/strong&gt; server action wraps the &lt;strong&gt;Anthropic_Claude_TextToText&lt;/strong&gt; server action from the AWS Bedrock Runtime component (&lt;em&gt;AWS_BedrockRuntime_IS&lt;/em&gt; module).&lt;/p&gt;

&lt;p&gt;We use this one as an example as all other server actions from the AWS_BedrockRuntime_IS follow the same approach.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8wtyew1S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yynrtjj1gkv4tw3k63cg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8wtyew1S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yynrtjj1gkv4tw3k63cg.png" alt="Claude Text-To-Text Wrapper" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The wrapper server action takes a single input parameter Prompt which is the text you entered in the default screen of the demo application and outputs a Result which is the generated text displayed next to the textarea.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The wrapper executes the &lt;strong&gt;Anthropic_Claude_TextToText&lt;/strong&gt; server action from the &lt;strong&gt;AWS_BedrockRuntime_IS&lt;/strong&gt; module first which in turn invokes the corresponding Bedrock API.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xSIoigzL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gpqva84n90qsggnpojd5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xSIoigzL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gpqva84n90qsggnpojd5.png" alt="Claude Text-To-Text" width="773" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All model operations from the &lt;strong&gt;AWS Bedrock Runtime&lt;/strong&gt; Forge component need your AWS credentials to authorize your request. You can choose between&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;IAM credentials&lt;/strong&gt; — &lt;strong&gt;AccessKey&lt;/strong&gt; and &lt;strong&gt;SecretAccessKey&lt;/strong&gt; from a created IAM user account with programmatic access.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;STS credentials&lt;/strong&gt; — Temporary credentials by assuming an IAM role with &lt;strong&gt;AccessKey&lt;/strong&gt;, &lt;strong&gt;SecretAccessKey&lt;/strong&gt; and &lt;strong&gt;SessionToken&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;STS credentials are a more advanced topic, but strongly recommended. My Forge Component &lt;strong&gt;AWS Security Token Service&lt;/strong&gt; can be used to assume a role and retrieve temporary credentials.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.outsystems.com/forge/component-overview/14555/aws-security-token-service"&gt;AWS Security Token Service - Overview | OutSystems&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition, you must specify the &lt;strong&gt;Region&lt;/strong&gt; where you provisioned Foundation Models. The AWS Bedrock Runtime Forge component contains a static entity to select the region.&lt;/p&gt;

&lt;p&gt;The Model input parameter specifies which Claude Version to use. For Anthropic Claude models you can specify one of the following values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;claude-v2:1&lt;/li&gt;
&lt;li&gt;claude-v2&lt;/li&gt;
&lt;li&gt;claude-v1&lt;/li&gt;
&lt;li&gt;claude-instant-v1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All model specific parameters can be found in the &lt;strong&gt;Request&lt;/strong&gt; structure. Parameters differ from model to model, and you will find information about the various parameters in the AWS Bedrock documentation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters.html"&gt;Inference parameters for foundation models - Amazon Bedrock&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The rest of the wrapping server action should be self-explaining.&lt;/p&gt;

&lt;p&gt;Next open the &lt;strong&gt;PromptOnClick&lt;/strong&gt; client action of the &lt;strong&gt;Demo&lt;/strong&gt; screen that calls the wrapper.&lt;/p&gt;

&lt;p&gt;The form value of the text area is passed as an input parameter and the result of the server action is then assigned to the Result attribute of the form structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model Values
&lt;/h2&gt;

&lt;p&gt;Some of the server actions accept a specific model version as input parameters. Here is a complete list of all possible values&lt;/p&gt;

&lt;p&gt;Anthropic_Claude_TextToText&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;claude-v2:1&lt;/li&gt;
&lt;li&gt;claude-v2&lt;/li&gt;
&lt;li&gt;claude-v1&lt;/li&gt;
&lt;li&gt;claude-instant-v1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI21_Jurassic_TextToText&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;j2-ultra-v1&lt;/li&gt;
&lt;li&gt;j2-mid-v1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Amazon_Titan_TextToText&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;titan-text-lite-v1&lt;/li&gt;
&lt;li&gt;titan-text-express-v1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cohere_Command_TextToText&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;command-text-v14&lt;/li&gt;
&lt;li&gt;command-light-text-v14&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meta_Llama_TextToText&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;llama2-13b-chat-v1&lt;/li&gt;
&lt;li&gt;llama2-70b-chat-v1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stability_StableDiffusion_TextToImage&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stable-diffusion-xl-v0&lt;/li&gt;
&lt;li&gt;stability.stable-diffusion-xl-v1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cohere_Command_TextToEmbeddings&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;embed-english-v3&lt;/li&gt;
&lt;li&gt;embed-multilingual-v3&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Amazon Bedrock together with the AWS Bedrock Runtime Forge component provides easy access to multiple foundation modules. With only a few preparational steps you are up and running in minutes to build your own Generative AI application.&lt;/p&gt;

&lt;p&gt;You can expect that both the Integration Forge component and the Demo application evolve over time.&lt;/p&gt;

&lt;p&gt;Thank you for reading. I hope you liked it and that i have explained the important parts well. Let me know if not 😊&lt;/p&gt;

&lt;p&gt;If you have difficulties in getting up and running, please use the &lt;a href="https://www.outsystems.com/forums"&gt;&lt;strong&gt;OutSystems Forum&lt;/strong&gt;&lt;/a&gt; to get help. Suggestions on how to improve this article are very welcome. Send me a message via my &lt;a href="https://www.outsystems.com/profile/0qginuc0j5/overview"&gt;&lt;strong&gt;OutSystems Profile&lt;/strong&gt;&lt;/a&gt; or write a comment.&lt;/p&gt;

</description>
      <category>outsystems</category>
      <category>generativeai</category>
      <category>awsbedrock</category>
    </item>
    <item>
      <title>Fine Grained Authorization in OutSystems with Amazon Verified Permissions</title>
      <dc:creator>Stefan Weber</dc:creator>
      <pubDate>Wed, 01 Nov 2023 06:25:40 +0000</pubDate>
      <link>https://dev.to/aws-builders/fine-grained-authorization-in-outsystems-with-amazon-verified-permissions-2gaf</link>
      <guid>https://dev.to/aws-builders/fine-grained-authorization-in-outsystems-with-amazon-verified-permissions-2gaf</guid>
      <description>&lt;p&gt;A couple of months ago, I had the chance to participate in a project where we implemented a front-end application on top of a document management system. The document management system used had a very sophisticated permission system, where you could set permissions for users and groups on a hierarchical level with inheritance, on an object level, and additionally based on specific metadata bound to an object. I then wondered how this could be done in OutSystems and experimented with building a central authorization system as a service application. After a while, I came to the conclusion that it was a huge effort to build it, and with a growing number of securables and especially hierarchical permission inheritance, it was no longer performant, so I stopped working on it. Later in the year, I noticed that Amazon released a new service called Amazon Verified Permissions, which seemed like a perfect solution for a fine-grained authorization system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Amazon Verified Permissions
&lt;/h2&gt;

&lt;p&gt;Verified Permissions is a policy-based authorization service. At a glance, it checks a &lt;em&gt;principal&lt;/em&gt;'s request to act (&lt;em&gt;action&lt;/em&gt;) on a &lt;em&gt;resource&lt;/em&gt; against one or more authorization policies.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Principal&lt;/strong&gt; - A principal represents a role, user, service, or any other identity that can request to perform an &lt;em&gt;action.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Action&lt;/strong&gt; - For example a server or service action of your OutSystems application or service. In other words - an operation that is requested by a &lt;em&gt;principal&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource&lt;/strong&gt; - Something that can be accessed or modified by the specified &lt;em&gt;action&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Policies are written in Cedar, a language specifically designed for defining permissions as policies. Originally developed by AWS, the Cedar specification and reference implementation is an Apache 2.0 open-source project. At the time of writing, Cedar has already been adopted by other vendors and open-source projects.&lt;/p&gt;

&lt;p&gt;Cedar is easy to learn and simple to read, yet it still allows for the definition of complex role-based or attribute-based authorization models.&lt;/p&gt;

&lt;h2&gt;
  
  
  When and Why You Should Care
&lt;/h2&gt;

&lt;p&gt;By default, the only built-in authorization method in OutSystems is application roles. User accounts can be associated either directly with roles or multiple roles can be assigned to user groups. Roles can then be used to protect screens, and you can use the predefined role actions in server actions to check if a user is associated with a specific role.&lt;/p&gt;

&lt;p&gt;It becomes more challenging when you need finer-grained authorization control over resources, such as a record in one of your entities. The OutSystems documentation suggests implementing an &lt;a href="https://success.outsystems.com/documentation/best_practices/architecture/use_access_control_list_to_set_up_permission_based_access_to_data/"&gt;ACL (Access Control List) based access system&lt;/a&gt;. However, this can lead to varying implementations in different applications and services, making maintenance and tracing of access rights more tedious - and may increase your Application Object count drastically.&lt;/p&gt;

&lt;p&gt;Additionally, you must implement all aspects within your business logic. To track how a user gains access to a specific resource, you would need to examine your code. Even the slightest change to your authorization logic would require a code modification and redeployment.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Considering complex authorization logic, such as nested group structures, attribute-based conditions, or a combination of "allow" and "deny" access controls, there is a possibility that implementing the authorization logic may take longer to develop than the actual application itself. Additionally, you may experience a significant performance decrease due solely to authorization checks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Using Amazon Verified Permissions or any other external authorization decision management solution can be extremely beneficial in this situation. It can considerably reduce the effort needed to create and maintain fine-grained authorization logic. Moreover, Amazon Verified Permissions and the Cedar policy are designed for rapid evaluation of access controls, thereby ensuring consistently high performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cedar Policy Language
&lt;/h2&gt;

&lt;p&gt;Before exploring how to integrate Verified Permissions with OutSystems, let's take a closer look at the Cedar policy language.&lt;/p&gt;

&lt;p&gt;💡&lt;br&gt;
We'll keep this section brief, as the focus of this article is on integrating OutSystems with Amazon Verified Permissions. Cedar is an incredibly potent expression language. For a more in-depth tutorial on Cedar policies in Verified Permissions, refer to the &lt;a rel="noopener noreferrer nofollow" href="https://dev.to/aws-builders/authorization-and-cedar-a-new-way-to-manage-permissions-part-i-1nid"&gt;tutorial series by my fellow AWS Community Builder Daniel Aniszkiewicz&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Policies
&lt;/h3&gt;

&lt;p&gt;Below is a very simple policy. If a request satisfies the expression between the brackets the policy returns true, otherwise false. The example expression is satisfied when&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;principal&lt;/em&gt; is an entity of type &lt;strong&gt;User&lt;/strong&gt; and has an &lt;strong&gt;ID&lt;/strong&gt; of 56 and&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The requested &lt;em&gt;action&lt;/em&gt; to perform is an entity of type &lt;strong&gt;Action&lt;/strong&gt; with an ID of &lt;strong&gt;Edit&lt;/strong&gt; and&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;resource&lt;/em&gt; that is targeted by the action is an entity of type &lt;strong&gt;Case&lt;/strong&gt; and has an &lt;strong&gt;ID&lt;/strong&gt; of 155&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The term entity describes the combination of a namespace (CaseManager), a type (e.g. User) and a unique identifier (e.g. 56).&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;permit(
  principal == CaseManager::User::"56",
  action in [CaseManager::Action::"Edit"],
  resource == CaseManager::Case::"155"
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Policies can either permit or deny (forbid) a request, with deny policies taking precedence over permit policies.&lt;/p&gt;

&lt;p&gt;💡&lt;br&gt;
You can have an unlimited number of policies, and Verified Permissions ensures that all applicable policies are evaluated before returning the final result of either Allow or Deny.&lt;/p&gt;

&lt;p&gt;The following example incorporates an extra condition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;permit(
  principal == CaseManager::User::"56",
  action in [CaseManager::Action::"Edit"],
  resource == CaseManager::Case::"155"
) unless {
  resource.IsSensitive == true
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This policy evaluates as true unless the resource - an entity of type case with ID 155 - has the attribute "IsSensitive" set to true. Quite simple to understand, isn't it?&lt;/p&gt;

&lt;p&gt;Let us see what a policy could look like to check if a principal belongs to a group.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;permit(
  principal in CaseManager::Group::"Counsel",
  action,
  resource
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the "&lt;strong&gt;in&lt;/strong&gt;" operator following the principal. The "in" operator instructs Cedar to determine if the principal is a member of another entity's hierarchy. In our case, it refers to the entity of type Group with the ID "Counsel".&lt;/p&gt;

&lt;p&gt;💡&lt;br&gt;
Hierarchy, in this context, refers to a user who is either a member of the "Counsel" group or a member of a group that is a member of the "Counsel" group asf.&lt;/p&gt;

&lt;p&gt;Both &lt;em&gt;action&lt;/em&gt; and &lt;em&gt;resource&lt;/em&gt; do not have a following operator which means any action on any resource.&lt;/p&gt;

&lt;h3&gt;
  
  
  Evaluation Data and Relations for Authorization Checks
&lt;/h3&gt;

&lt;p&gt;But how does Cedar determine the hierarchy?&lt;/p&gt;

&lt;p&gt;Well, we must inform Cedar about the relationships between these entities whenever we check authorization. Additionally, we need to provide any entities and essential entity attributes and their corresponding values required for policy evaluation.&lt;/p&gt;

&lt;p&gt;Consider the following example Cedar policy&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;permit(
  principal in CaseManager::Group::"Counsel",
  action in [CaseManager::Action::"Edit"],
  resource == CaseManager::Case::"155"
) unless {
  resource.IsSensitive == true
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our scenario, a user with an ID of 25 is a member of the Counsel Group, and we want to determine if that user is permitted to edit Case 155. As mentioned earlier, we need to provide all relevant data and relationships to Verified Permissions, which are necessary for evaluating one or more applicable policies. Here we would pass to the IsAuthorized operation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;principal&lt;/em&gt; set to CaseManager::User::"25", which is our User entity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;action&lt;/em&gt; set to CaseManager::Action::"Edit"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;resource&lt;/em&gt; set to CaseManager::Case::"155"&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, we need to provide two additional information&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;for the &lt;strong&gt;User&lt;/strong&gt; entity we have to define a parent relation with the CaseManager::Group::"Counsel" entity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;for the &lt;strong&gt;Case&lt;/strong&gt; entity we have to add an attribute IsSensitive set to false (to satisfy the policy condition)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Strict Mode with Schema
&lt;/h3&gt;

&lt;p&gt;The next question we address is: what happens if you fail to provide additional data that is crucial for authorization checks? Imagine having thousands of policies created using various entity attributes for conditional checks, and you want to ensure that those attributes are always present during an authorization check.&lt;/p&gt;

&lt;p&gt;Although not mandatory, you can set a Policy Store in Amazon Verified Permission to Strict mode and establish a Schema.&lt;/p&gt;

&lt;p&gt;The Schema defines all valid entities, entity relations, and attributes. Applying a schema ensures that:&lt;/p&gt;

&lt;p&gt;1. You can only create a policy using entities and attributes defined in your schema, thus preventing the creation of policies that would never apply due to missing data.&lt;/p&gt;

&lt;p&gt;2. Authorization checks include all essential data necessary to determine applicable policies and perform policy evaluation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Template Linked Policies
&lt;/h3&gt;

&lt;p&gt;Let's say you created thousands of policies for a specific principal-action-resource combination individually and now you have a requirement to change or add an attribute condition. In that case, you would have to iterate over all those policies and change them one by one. Furthermore, it is sometimes not that easy to identify all applicable policies that need to be changed.&lt;/p&gt;

&lt;p&gt;Fortunately, Amazon Verified Permissions offers the ability to create Policy templates and then generate policies linked to a specific template. If you need to change a condition, you can simply modify the template, which will immediately impact all policies associated with that template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;permit(
  principal in CaseManager::Group::"Clerk",
  action in [CaseManager::Action::"Edit",CaseManager::Action::"View"],
  resource == ?resource
) unless {
  resource.IsSensitive == true
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above is a sample template. &lt;em&gt;principal&lt;/em&gt; and &lt;em&gt;action&lt;/em&gt; are static while &lt;em&gt;resource&lt;/em&gt; is compared with ?resource. The question mark in front indicates that this parameter must be given when creating a policy based on this template.&lt;/p&gt;

&lt;p&gt;Now if you want to change the condition resource.IsSensitive later on to compare with false then all bound policies would be changed at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  More on Cedar and Amazon Verified Permissions
&lt;/h2&gt;

&lt;p&gt;In this section, we just tipped the iceberg. I recommend reading the following articles and documentation before you proceed&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/aws-builders/authorization-and-cedar-a-new-way-to-manage-permissions-part-i-1nid"&gt;Authorization and Cedar: A New Way to Manage&lt;/a&gt; - Tutorial Series by Daniel Aniszkiewicz&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/what-is-avp.html"&gt;Amazon Verified Permissions Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.cedarpolicy.com/"&gt;Cedar Policy Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Preparations
&lt;/h2&gt;

&lt;p&gt;Now that you have a basic understanding of Cedar and Amazon Verified Permissions, we can begin exploring how to integrate with OutSystems. Let's start by tackling some preparatory tasks.&lt;/p&gt;

&lt;p&gt;💡&lt;br&gt;
You need permission to manage Amazon Verified Permissions within an AWS account, as well as permission to create an IAM Policy and User.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create and Configure AVP Policy Store&lt;/strong&gt; - Create an Amazon Verified Permissions (AVP) Policy Store, import a schema, and establish baseline policies and policy templates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create IAM Policy and User&lt;/strong&gt; - Create an IAM User with programmatic access and an associated policy that grants access to Amazon Verified Permissions operations. This account will be used for interacting with AVP from OutSystems.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Download and install Forge components&lt;/strong&gt; - Install the AVP Forge component and the accompanying demo application for this article.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add a Group to OutSystems User Provider&lt;/strong&gt; - Create Group in the OutSystems User Provider and assign user accounts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configure Demo application&lt;/strong&gt; - Configure site properties of the Demo application.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Create and Configure AVP Policy Store
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Go to the AWS console and log in. Make sure that your preferred region is selected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the Search box search for Amazon Verified Permissions and browse to the service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;strong&gt;"View Policy Stores"&lt;/strong&gt; and then "&lt;strong&gt;Create new policy store"&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select "&lt;strong&gt;Empty policy store&lt;/strong&gt;" from the options then click on "&lt;strong&gt;Create policy store&lt;/strong&gt;"&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After successful creation copy the value on the left under "&lt;strong&gt;Current policy store&lt;/strong&gt;". We will need this &lt;strong&gt;Policy Store Identifier&lt;/strong&gt; later.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the menu on the left select "&lt;strong&gt;Schema&lt;/strong&gt;", then click on "&lt;strong&gt;Create schema&lt;/strong&gt;"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Switch to JSON mode and paste the following schema, replacing the current JSON. Then click "&lt;strong&gt;Save changes&lt;/strong&gt;".&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "CaseManager": {
        "entityTypes": {
            "Case": {
                "shape": {
                    "type": "Record",
                    "attributes": {
                        "AssignedTo": {
                            "name": "User",
                            "required": true,
                            "type": "Entity"
                        },
                        "IsSensitive": {
                            "required": true,
                            "type": "Boolean"
                        }
                    }
                },
                "memberOfTypes": []
            },
            "Application": {
                "shape": {
                    "attributes": {},
                    "type": "Record"
                },
                "memberOfTypes": []
            },
            "Group": {
                "shape": {
                    "attributes": {},
                    "type": "Record"
                },
                "memberOfTypes": []
            },
            "User": {
                "shape": {
                    "attributes": {},
                    "type": "Record"
                },
                "memberOfTypes": [
                    "Group"
                ]
            }
        },
        "actions": {
            "AddCase": {
                "memberOf": [],
                "appliesTo": {
                    "principalTypes": [
                        "User"
                    ],
                    "resourceTypes": [
                        "Application"
                    ],
                    "context": {
                        "type": "Record",
                        "attributes": {}
                    }
                }
            },
            "GetCase": {
                "memberOf": [],
                "appliesTo": {
                    "resourceTypes": [
                        "Case"
                    ],
                    "context": {
                        "type": "Record",
                        "attributes": {}
                    },
                    "principalTypes": [
                        "User"
                    ]
                }
            },
            "AssignCase": {
                "memberOf": [],
                "appliesTo": {
                    "context": {
                        "type": "Record",
                        "attributes": {}
                    },
                    "resourceTypes": [
                        "Case"
                    ],
                    "principalTypes": [
                        "User"
                    ]
                }
            },
            "ToggleSensitivity": {
                "appliesTo": {
                    "context": {
                        "attributes": {},
                        "type": "Record"
                    },
                    "principalTypes": [
                        "User"
                    ],
                    "resourceTypes": [
                        "Case"
                    ]
                },
                "memberOf": []
            },
            "DeleteCase": {
                "appliesTo": {
                    "resourceTypes": [
                        "Case"
                    ],
                    "principalTypes": [
                        "User"
                    ],
                    "context": {
                        "attributes": {},
                        "type": "Record"
                    }
                },
                "memberOf": []
            },
            "UpdateCase": {
                "appliesTo": {
                    "resourceTypes": [
                        "Case"
                    ],
                    "principalTypes": [
                        "User"
                    ],
                    "context": {
                        "type": "Record",
                        "attributes": {}
                    }
                },
                "memberOf": []
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the menu on the left select "&lt;strong&gt;Policy templates&lt;/strong&gt;", then click "&lt;strong&gt;Create policy template&lt;/strong&gt;"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enter "&lt;strong&gt;Case Viewers&lt;/strong&gt;" as &lt;strong&gt;Description&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the following policy expression to "&lt;strong&gt;Policy Statement&lt;/strong&gt;", then click on "&lt;strong&gt;Create policy template&lt;/strong&gt;". Name the policy "&lt;strong&gt;Case Viewer Template&lt;/strong&gt;". Copy the &lt;strong&gt;Policy Template ID&lt;/strong&gt; which we will need later.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;permit(
  principal == ?principal,
  action in [CaseManager::Action::"GetCase"],
  resource == ?resource
) unless {
  resource.IsSensitive == true
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the menu on the left select "&lt;strong&gt;Policies&lt;/strong&gt;"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create the following &lt;strong&gt;Static Policies&lt;/strong&gt; (skip the visual assistant and copy the policy expression directly)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Case Managers can create cases&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;permit(
  principal in CaseManager::Group::"os-case-manager",
  action in [CaseManager::Action::"AddCase"],
  resource == CaseManager::Application::"CaseManager"
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Case Managers can perform any case action&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;permit(
  principal in CaseManager::Group::"os-case-manager",
  action in [CaseManager::Action::"GetCase",CaseManager::Action::"UpdateCase",CaseManager::Action::"DeleteCase",CaseManager::Action::"AssignCase",CaseManager::Action::"ToggleSensitivity"],
  resource
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Assignee can read and update an assigned case&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;permit(
  principal,
  action in [CaseManager::Action::"GetCase",CaseManager::Action::"UpdateCase"],
  resource
) when {
  resource.IsSensitive == false &amp;amp;&amp;amp; resource.AssignedTo == principal
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create IAM Policy and User
&lt;/h3&gt;

&lt;p&gt;Next, we need an IAM user with programmatic access and an associated policy that grants specific permissions to the created Policy Store.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the AWS console switch to Identity and Access Management Service (IAM).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the menu on the left select &lt;strong&gt;Policies&lt;/strong&gt; and click on "&lt;strong&gt;Create policy&lt;/strong&gt;"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Switch to JSON edit mode and copy the following Permission Definition. Make sure to change the placeholders for "&lt;strong&gt;&amp;lt;AWSAccount&amp;gt;&lt;/strong&gt;" and "&lt;strong&gt;&amp;lt;PolicyStoreId&amp;gt;&lt;/strong&gt;" to your AWS Account ID and the ID of the Policy Store you created.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VisualEditor0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"verifiedpermissions:DeletePolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"verifiedpermissions:CreatePolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"verifiedpermissions:ListPolicies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"verifiedpermissions:IsAuthorized"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"verifiedpermissions:GetPolicy"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:verifiedpermissions::&amp;lt;AWSAccount&amp;gt;:policy-store/&amp;lt;PolicyStoreId&amp;gt;
        }
    ]
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Complete the Policy creation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the Users menu create a new user and attach the created policy directly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the details page of the created user in the "&lt;strong&gt;Security credentials&lt;/strong&gt;" tab generate a new access key pair.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make sure to copy both the "&lt;strong&gt;Access Key&lt;/strong&gt;" and "&lt;strong&gt;Secret Access Key&lt;/strong&gt;". We will need both later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Download and install Forge components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Download and install "&lt;a href="https://www.outsystems.com/forge/component-overview/16755/aws-verified-permissions"&gt;AWS Verified Permissions&lt;/a&gt;" from OutSystems Forge - This is the connector component.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attached to the connector, there is also a Demo Application. Download this too, as we will use it to examine some implementation specifics.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Add a Group to OutSystems User Provider
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Open the Users Provider Frontend in your environment (https://&amp;lt;youroutsystemsenvironment&amp;gt;/Users)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new group with the exact name "os-case-manager". The name is used as an identifier in some policies you imported earlier. Add at least one user to this group. Members of this group have full permissions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configure Demo application
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In &lt;strong&gt;Service Center&lt;/strong&gt; (&lt;a href="https://youroutsystemsenvironment&amp;gt;/servicecenter"&gt;https://youroutsystemsenvironment&amp;amp;gt;/servicecenter&lt;/a&gt;) open the &lt;strong&gt;VerifiedPermissionsAuthService_IS&lt;/strong&gt; module.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In Site Properties set the values for &lt;strong&gt;AWSAccessKey&lt;/strong&gt;, &lt;strong&gt;AWSSecretAccessKey&lt;/strong&gt;, &lt;strong&gt;AWSRegion&lt;/strong&gt; and &lt;strong&gt;AVPPolicyStoreId&lt;/strong&gt; to match your IAM User and Policy Store Identifier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, go to the &lt;strong&gt;VerifiedPermissionsDemo&lt;/strong&gt; module and set the site property &lt;strong&gt;AVPPolicyStoreId&lt;/strong&gt; to the policy store identifier you copied above. Set the &lt;strong&gt;AVPViewerTemplateId&lt;/strong&gt; to the Policy Template ID you created above.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡&lt;br&gt;
As usual the security reminder here: Secrets shouldn’t be stored in site properties but instead in a secure credentials management solution like AWS Secrets Manager or Hashicorp Vault.&lt;/p&gt;

&lt;p&gt;Now that all preparatory tasks are completed, you are ready to test the sample application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo Application Overview
&lt;/h2&gt;

&lt;p&gt;The demo application is very simple. It allows a member of the os-case-manager group to create a case with a title and a description. Cases can be assigned to any user account and an assigned user can view the details and update the details. The first assigned user is the creator of the case.&lt;/p&gt;

&lt;p&gt;💡&lt;br&gt;
The demo application only performs permission checks when executing a server action. I have not implemented permission checks on the front end, which is why everything is accessible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modules
&lt;/h3&gt;

&lt;p&gt;The Demo Application consists of two modules&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;VerifiedPermissionsDemo&lt;/strong&gt; - The actual web application&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;VerifiedPermissionsAuthService_IS&lt;/strong&gt; - This module is designed to serve as a central authorization service. In a real OutSystems Factory, it should function as a central service that provides Service Actions for all other applications.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Permissions
&lt;/h3&gt;

&lt;p&gt;There are some basic permissions represented by the static policies you created.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case Managers can create cases&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This policy allows members of the os-case-manager group to add a new case to the application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case Managers can perform any case action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This policy allows members of the os-case-manager group to perform all case-related actions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GetCase&lt;/strong&gt; - Retrieve the details of a case&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UpdateCase&lt;/strong&gt; - Update the details of a case&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DeleteCase&lt;/strong&gt; - Permanently delete a case&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AssignCase&lt;/strong&gt; - Assign a case to a user or add or remove a viewer of a case&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ToggleSensitivity&lt;/strong&gt; - Switch case to Sensitive and back&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Assignee can read and update an assigned case&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A user that is assigned to a case can perform the following actions&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GetCase&lt;/strong&gt; - Retrieve the details of a case&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;UpdateCase&lt;/strong&gt; - Update the details of a case&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, if the case is marked as sensitive, even the assignee cannot access or edit the case details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case Viewer Template&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In addition, policies are created at runtime whenever a member of the os-case-manager groups adds another viewer to a case. Those policies are created using the Policy Template "&lt;strong&gt;Case Viewer Template&lt;/strong&gt;" you created which grants the following permission&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GetCase&lt;/strong&gt; - Retrieve the details of a case&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, similar to the assignee permission, this applies only if the case is not sensitive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try out
&lt;/h3&gt;

&lt;p&gt;Before delving into the technical implementation details, it is recommended that you explore the demo application. Alter group memberships and experiment with various user accounts to observe how these changes impact specific actions and the error messages you may encounter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Details
&lt;/h2&gt;

&lt;p&gt;In this article, I will walk you through the most important implementation steps related to authorization.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open both modules of the demo application in Service Studio (VerifiedPermissionsDemo and VerifiedPermissionsAuthService_IS)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Authorization Service
&lt;/h3&gt;

&lt;p&gt;We'll begin by examining the VerifiedPermissionsAuthService_IS module. As previously mentioned, this service module is intended to function as a central authorization service, which means it can be utilized across multiple applications.&lt;/p&gt;

&lt;p&gt;The module exposes four actions (exposed as service actions)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CheckAuthorization&lt;/strong&gt; - Used to check if a user has permission to act on a resource&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CreatePolicyFromTemplate&lt;/strong&gt; - Used to create a new policy based on a policy template. In the demo, this action is used whenever a new viewer gets added to a case&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DeletePolicy&lt;/strong&gt; - Used to delete a policy. In the demo, this action is used when a viewer is removed from a case.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ListTemplateLinkedPolicies&lt;/strong&gt; - Used to discover all policies affecting a principal or a resource or both&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open the &lt;strong&gt;CheckAuthorizationAction&lt;/strong&gt; server action.&lt;/p&gt;

&lt;p&gt;💡&lt;br&gt;
In Amazon Verified Permissions, principals (such as users), actions, and resources are referred to as entities. Each entity has a type and an identifier. The type consists of the namespace, as declared in the schema, followed by the actual type, such as User or Case. The identifier is a unique ID, for example, the user identifier. In addition, entities can have parent entities and attributes.&lt;/p&gt;

&lt;p&gt;This action flow&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Builds the user entity hierarchy by retrieving all group memberships for the given user. It returns an entity for the user along with the parent group identifiers. With this entity, AVP can evaluate group memberships. GetUserEntityItem&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This entity along with all other entities given as input parameters is then used to perform the authorization check against AVP policies.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next, open the &lt;strong&gt;ListTemplateLinkedPoliciesAction&lt;/strong&gt; server action&lt;/p&gt;

&lt;p&gt;This action is used whenever we need to determine which policies affect a given principal or resource. In the demo, this action is used to determine the current allowed viewers of a case.&lt;/p&gt;

&lt;p&gt;Next, open the &lt;strong&gt;CreatePolicyFromTemplateAction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This one is pretty easy. It takes a template identifier and principal and creates a template-linked policy.&lt;/p&gt;

&lt;p&gt;Lastly, open the &lt;strong&gt;DeletePolicyAction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This action deletes a policy using the given policy identifier.&lt;/p&gt;

&lt;p&gt;💡&lt;br&gt;
To get more insights on the various Verified Permissions actions used I recommend reading the &lt;a rel="noopener noreferrer nofollow" href="https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/Welcome.html"&gt;API Reference&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Case Manager
&lt;/h3&gt;

&lt;p&gt;Switch to the VerifiedPermissionsDemo. In the logic tab review the server actions in the Business_Logic folder.&lt;/p&gt;

&lt;p&gt;Each action here relates to a task a user can perform on the UI and each of it contains an authorization check before processing the request.&lt;/p&gt;

&lt;p&gt;The application has two general types of authorization check&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;On the application level using the &lt;strong&gt;CheckApplicationAuthorization&lt;/strong&gt; server action&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On the case level using the &lt;strong&gt;CheckCaseAuthorization&lt;/strong&gt; action&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The only difference between the two is, that in the later case, the database is queried for the case details and an AVP entity is created using the &lt;strong&gt;CaseToEntityItem&lt;/strong&gt; server action and added to the input parameters of the &lt;strong&gt;CheckAuthorizationOperation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Both actions take an Action as input which is an entity identified by its namespace e.g. "&lt;strong&gt;CaseManager::Action&lt;/strong&gt;" and its identifier e.g. "&lt;strong&gt;GetCase&lt;/strong&gt;".&lt;/p&gt;

&lt;p&gt;I guess most of the business logic is easy to read, so I will not get into details. But there is one server action we should take a closer look.&lt;/p&gt;

&lt;p&gt;Open the &lt;strong&gt;CaseManager_GetViewers&lt;/strong&gt; server action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bK7trolx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pw5go4iu56ab9p0av0pm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bK7trolx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pw5go4iu56ab9p0av0pm.png" alt="GetViewers Action" width="800" height="1209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This server action uses the ListTemplateLinkedPolices service action of the VerifiedPermissionsAuthService_IS module to retrieve all applicable policies for the given case.&lt;/p&gt;

&lt;p&gt;It then cycles through the policies to get all principal identifiers and builds a list of retrieved user identifiers.&lt;/p&gt;

&lt;p&gt;Lastly, it performs an advanced SQL statement with an IN clause to retrieve all viewer user accounts.&lt;/p&gt;

&lt;p&gt;💡&lt;br&gt;
Note that the service action is only performed once and that AVP returns a max of 50 policies. In case you have more you would need to implement pagination with the NextToken.&lt;/p&gt;

&lt;p&gt;And that's it. I hope you don't mind that I didn't go into every detail of the implementation. I believe that most parts are pretty much self-explaining. Let me know if you have any difficulties.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;AVP and Cedar can be a great addition to your OutSystems factory or even just to a single application. It can drastically reduce the efforts of building complex authorization logic. But AVP does not only have advantages. Personally, I am missing&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The ability to send bulk authorization requests which would be very helpful to check a principal's permission to entries of a list of records.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The ability to retrieve a list of actions a principal can perform on a resource.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the time of writing Amazon Verified Permissions is still brand-new, so we can expect some nice additions in the future.&lt;/p&gt;

&lt;p&gt;Thank you for reading. I hope you liked it and that i have explained the important parts well. Let me know if not 😊&lt;/p&gt;

&lt;p&gt;If you have difficulties in getting up and running, please use the &lt;a href="https://www.outsystems.com/forums"&gt;&lt;strong&gt;OutSystems Forum&lt;/strong&gt;&lt;/a&gt; to get help. Suggestions on how to improve this article are very welcome. Send me a message via my &lt;a href="https://www.outsystems.com/profile/0qginuc0j5/overview"&gt;&lt;strong&gt;OutSystems Profile&lt;/strong&gt;&lt;/a&gt; or write a comment.&lt;/p&gt;

</description>
      <category>awsverifiedpermissions</category>
      <category>outsystems</category>
    </item>
  </channel>
</rss>
