# Bridge the Gap: OutSystems User Credentials to AWS Temporary Credentials

*The article discusses how to use AWS services with OutSystems applications without needing to share permanent AWS credentials. It outlines an approach that involves using OutSystems Developer Cloud's identity provider to obtain a user's access token, exchanging that token with AWS Cognito for temporary AWS credentials, and then using those temporary credentials to access AWS services.*

%[https://creators.spotify.com/pod/show/withoutsystems/episodes/Bridge-the-Gap-OutSystems-User-Credentials-to-AWS-Temporary-Credentials-e2t57pm] 

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Please note that the podcast episode above is automatically generated from this article and may not include a proper level of detail.</div>
</div>

Consuming AWS services with OutSystems is easy if you use one of the available AWS Connector libraries on [Forge](https://www.outsystems.com/forge/), such as S3, Translate, Rekognition, and others. To use them, you need AWS credentials created by your AWS administrators and given to you. The **officially OutSystems supported AWS connectors** use permanent, or long-lasting, AWS credentials, which consist of an access key and a secret access key. Some community AWS connectors also support temporary credentials. Additionally, your AWS administrators need to grant permissions that allow these credentials to use the services and their actions.

**Disadvantages**

This handover of credentials has several disadvantages. The main issue is that long-lasting credentials with associated permissions are given to another team. As we all know, credentials can spread quickly, which is why administrators might be hesitant to provide long-lasting credentials, even with minimal permissions.

If you plan to use many AWS services across different ODC applications, you will likely have multiple long-lasting credentials, one for each application, with limited permissions tailored to each application's needs. If you need to change credentials regularly (secret access key rotation), this can quickly become an error-prone administrative task.

It is desirable if **no credentials** need to be handed over at all and the AWS administrators retain absolute control over the use of services.

In this article, we take a look at how this can be achieved.

At a glance, this involves the following steps:

* AWS administration configures an **AWS Cognito Identity Pool** that trusts federated identities from your OutSystems Developer Cloud Identity Provider.
    
* Whenever an AWS service needs to be used, the developer exchanges the logged-in user's ODC credentials for **temporary AWS credentials**.
    
* The temporary AWS credentials are then used to access an AWS service.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716973826459/a76124c3-8981-4975-83f9-78d744f07587.png align="center")

The image above shows the entire process. In this article, we will walk through each part involved.

Unlike the long-lasting credentials mentioned earlier, temporary credentials have a limited lifetime and expire after a certain period.

This avoids sharing permanent AWS access keys and gives admins control over permissions. It leverages Cognito's ability to issue short-lived credentials based on federated identities.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">The following approach is unofficial, and you should not expect support from OutSystems. However, it is <strong>valid and secure</strong>.</div>
</div>

# Identity Providers in OutSystems Developer Cloud

Let's start by looking into how Identity Management works in OutSystems Developer Cloud.

After your OutSystems Developer Cloud is set up, you can configure multiple OpenID Connect compatible Identity Providers and assign them to different stages. You can also use the built-in provider, which is also OpenID Connect compatible. Later, you can use any of these configured providers in your applications for authentication.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Note </strong>that everything described in this article also works with the built-in provider. Therefore, you do not have to configure an external Identity Provider.</div>
</div>

Under the hood OutSystems registers each of your configured Identity Providers in a **KeyCloak** instance in each stage you selected. This **KeyCloak** instance brokers authentications from the providers and issues tokens to your application including OutSystems specific claims.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><a target="_blank" rel="noopener noreferrer nofollow" href="https://www.keycloak.org/" style="pointer-events: none">KeyCloak </a>is an open-source Identity and Access Management solution largely sponsored by Redhat.</div>
</div>

If you are curious. The built-in provider uses an [AWS Cognito User Pool](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html) for authentication.

What’s important here is that only your **KeyCloak** instance issues tokens (Identity and Access Tokens) to your applications, not the configured and used Identity Provider in the ODC Portal, including the built-in provider.

Tokens issued by your **KeyCloak** instance are stored in the local storage of your client application and sent with every request to a server or service action.

# Issued Access and Identity Tokens

Let's inspect how ODC credentials for applications are stored in the browser.

Open any of your ODC applications and log in. After a successful login, open the **developer tools** of your browser (F12 in Edge).

Switch to the **Application** tab, and under **Storage**, you should see your current stage domain name. Click on it to view the stored values on the right.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716549269858/862b4af4-4fad-4f16-a9db-4fa556a4a969.png align="center")

Check the value of **os-runtime-currentAuthType** which is set to **builtin** if using the default identity pool and to **external** if you use your own Identity Provider.

Next click on **os-runtime-token** which contains your personal access and identity token (id\_token). Copy the value of the access token (access\_token) and paste it to [jwt.io](https://jwt.io) for inspection.

* **Access Tokens** - They serve as credentials that allow an OAuth client (such as a mobile app or a web application) to make requests to an API. Access tokens are primarily used for authorization. They grant the client permission to access specific resources on behalf of the user who authorized the application.
    
* **Identity Tokens** - ID tokens are defined in OpenID Connect (OIDC), an extension of OAuth. OIDC is used for authentication and identity management. ID tokens provide information about what happened during the user authentication process. They serve as proof that the user has been authenticated.
    

Last click on **os-runtime-identity-endpoints** and scroll down to **issuer** and copy the value of the issuer field.

```plaintext
https://<domain-stage-name>.outsystems.app/auth/realms/<KeyCloak Realm Identifier>
```

This last information we are going to use to configure an AWS Cognito Identity Pool.

# AWS Cognito Identity Pool

Cognito Identity Pool is a service that exchanges federated identities, like your ODC access token, for temporary AWS credentials.

Put simply, a federated identity is a user who has already authenticated with an external identity provider you trust. You configure this trust in AWS Cognito Identity Pools.

Configuring a basic Identity pool is pretty simple, but Identity Pool provides lots of advanced features like attribute based access control. Read the [official documentation](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html) for details.

## Create IAM Identity Provider

In your AWS account switch to the **IAM** console. In the menu on the left select **Identity Providers** and click the **Add Provider** button.

Paste the value of your **KeyCloak realm instance** here and for audience enter **client\_runtime**.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716551493323/bba8846f-5aff-4a3c-9d75-d709b2255d3d.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">The audience value can be found by inspecting your access token's <strong>aud </strong>field. It is always <strong>client_runtime</strong>.</div>
</div>

Repeat this step for all your stages if necessary.

## Create a Cognito Identity Pool

Next switch to the **AWS Cognito Console**. Select **Identity Pools** from the menu and click on **Create Identity Pool**.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">You should create the Identity Pool in the same region your OutSystems Developer Cloud instance is running, though it is not mandatory.</div>
</div>

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716551854037/adc32ca0-b0b5-41cc-9ccb-6c15fe2ccd11.png align="center")

Select **Authenticated access** (we will only allow ODC authenticated users) and in sources **OpenID Connect (OIDC)**. Then click **Next**.

In the **Configure Permissions** screen select Create a new IAM role and type a role name.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716552027109/4d3cf6fd-e735-4f47-a059-ace33d913e16.png align="center")

When an access token is exchanged for AWS credentials, the permissions attached to this role are assigned to the issued credentials by default.

Click **Next**.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716553510451/6fce3c2d-1f25-4335-bcfa-7ce27979e214.png align="center")

Select the **OIDC Identity Provider** you configured in IAM before. Leave defaults for the other options and click **Next**.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Not covered in this article, but you should check the documentation on <strong>Role Settings</strong> and <strong>Attributes for access control</strong>. These are powerful features for fine-grained control of permissions.</div>
</div>

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716553797665/2472e210-1937-43dd-ac8b-b474e06da25d.png align="center")

In the **Configure Properties** screen provide a name for your Identity Pool and click **Next**. On the final screen review your settings and finish with **Create Identity Pool**.

# Retrieving a User's Access Token

Before we can exchange an ODC access token for AWS credentials, we need to retrieve it. Fortunately, this is very straightforward. With every request to a **server** or **service** action, your application also sends an **Authorization** header with the user's access token. The header looks like this:

```plaintext
Bearer <Your access token value>
```

To get the access token we read the **Authorization** header using the **Request\_GetHeaders** action from the **HTTP** source.

With **String\_Split** from the **Text** source we can split the value by space and we return the second element (**String\_Split.List\[1\].Text.Value**)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1717145261489/85b0c0a7-26e9-4bc6-aac8-b3a09628fc2f.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">If a server or service action is called from an unauthenticated user, the <strong>Authorization </strong>header is not sent. Note that Cognito is also able to issue credentials for unauthenticated (anonymous) users, though not covered in this article. Check the Cognito Identity Pools documentation on how to issue temporary AWS credentials for unauthenticated users.</div>
</div>

# Exchange for AWS Credentials

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">You must install the <strong>AWSCognitoIdentity </strong>external logic connector from ODC Forge to perform this steps.</div>
</div>

Having the access token, we can finally exchange it for temporary AWS credentials using a Cognito Authentication flow. The default [Enhanced AuthFlow](https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html) is a two-step process:

1. Call **GetId** to retrieve an **IdentityId**, using our access token as proof of authentication.
    
2. Use the **IdentityId** along with our access token to call **GetCredentialsForIdentity**, which returns the temporary AWS credentials.
    

Both actions are implemented in the **AWSCognitoIdentity** external logic connector.

For **GetId** you need to provide your **Identity Pool ID** which can be copied from the AWS Cognito Identity Pool console.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716884465465/a87e572b-6cef-4b44-a951-6ee5ec7dd59b.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716884508462/3ab5125a-7da5-4b70-99d9-2bdf84eb74bc.png align="center")

Add one item to the Logins list and set the Provider to your Identity Provider ID (created in IAM above). This is your **KeyCloak** realm name without "https://".

Set the token to the retrieved access token from the **Authorization** header.

**GetCredentialsForIdentity** takes the returned **IdentityId** from **GetId** as parameter and again the same **Logins** values (Identity Provider and Token).

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716884696233/1bd5ae3e-60a5-4eee-ac5a-b23bc19c70cb.png align="center")

**GetCredentialsForIdentity** returns temporary AWS credentials, which include an **AccessKeyId**, **SecretAccessKey**, and **SessionToken**. It also provides the **Expiration** time for these credentials.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">In a production environment, it makes sense to build a <strong>credential cache</strong> to reduce the number of trips to Cognito.</div>
</div>

# Using AWS Credentials

Unfortunately, there are only a few AWS connectors available on Forge that support AWS temporary credentials. At the time of writing, these are:

* **AWSBedrockRuntime**
    
* **AWSComprehend**
    
* **AWSSimpleStorage**
    

All of these are maintained by me, and you can expect more to be added to Forge in the future. I am also trying to convince the OutSystems Platform Maintenance team to include support for temporary credentials in the officially supported integrations like **Transcribe** and **Rekognition**.

Anyhow. To use the retrieved temporary credentials with the **AWSBedrockRuntime** connector you choose one of the model actions and set the credential parameters accordingly.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Note </strong>that you need to add permissions to the Identity Pool default role to use an AWS service. Read my article <a target="_blank" rel="noopener noreferrer nofollow" href="https://without.systems/get-started-with-outsystems-and-amazon-bedrock" style="pointer-events: none">Get Started with OutSystems and Amazon Bedrock</a> on how to get started with Amazon Bedrock in OutSystems.</div>
</div>

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716890788606/b034a437-cf3d-456a-bfd6-635b1c32e973.png align="center")

# Summary

Setting up a trust relationship between AWS Cognito Identity Pools and your OutSystems Developer Cloud environment greatly enhances security as no long-lasting credentials must be handed-over from AWS administrators to OutSystems developers. The downside is that Cognito issues temporary credentials that can only be used with a few AWS service connectors available on ODC Forge.

Thank you for reading. I hope you enjoyed it and that I've explained the important parts clearly. If not, please let me know 😊 Your feedback is greatly appreciated.

Follow me on LinkedIn to receive notifications whenever I publish something new.

# One final disclaimer

As mentioned above, this is not officially supported by OutSystems. OutSystems is constantly improving and optimizing the platform, and they may not actively communicate changes to the underlying technology stack.

The only technology element used here is the trust relationship with the KeyCloak Identity Broker. If OutSystems changes the Identity Broker to something else, you would simply need to update your registered OpenId Connect Provider on the AWS side to keep it working.

# Whats next

Cognito Identity Pools offer more capabilities than discussed in this article. One of the most powerful features is the ability to turn claims from your access token into AWS credential tags. This lets you set conditional IAM policies for detailed access control. For more information, check out the documentation on attribute mapping.

Also, look out for the **AWS Cognito Identity JS Client** ODC Forge component, which allows you to exchange an ODC access token for temporary AWS credentials directly in the client application.
