Information Security 13 min read

Okta & AWS Integration Configuration Guide: Using SAML and STS for Secure Access

This guide explains how to replace static AWS IAM credentials with secure, time‑limited access by integrating Okta SSO via SAML, configuring the necessary Okta application, AWS identity provider, IAM roles, and using bash scripts to obtain temporary STS credentials for authenticated AWS operations.

Bitu Technology
Bitu Technology
Bitu Technology
Okta & AWS Integration Configuration Guide: Using SAML and STS for Secure Access

The Tubi infrastructure team promotes best practices by providing tools and processes that help developers make secure decisions, especially when accessing AWS resources.

Static IAM user credentials are risky because they are hard to rotate and have no expiration; the guide recommends using Okta SSO to generate temporary, role‑based credentials via AWS STS.

Okta configuration : create an Amazon Web Services application in Okta, set Sign‑on method to SAML 2.0, download the Identity Provider metadata XML, and note the provider ARN.

AWS configuration : create an IAM Identity Provider using the downloaded XML, create a dedicated IAM user with access/secret keys, and record its ARN.

{
  "Statement": [
    {
      "Action": [
        "iam:ListRoles",
        "iam:ListAccountAliases"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ],
  "Version": "2012-10-17"
}

Define a trust relationship for a new IAM role that allows Okta to assume it via SAML.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "Federated": "arn:aws:iam::
:saml-provider/okta" },
      "Action": "sts:AssumeRoleWithSAML",
      "Condition": { "StringEquals": { "SAML:aud": "https://signin.aws.amazon.com/saml" } }
    }
  ]
}

Return to the Okta app configuration, fill in the Identity Provider ARN, set a suitable session duration (e.g., one day), enable API integration, and assign the role to users.

Obtain an Okta session token and perform MFA if required:

OKTA_ORG=tubi
OKTA_USERNAME=james
OKTA_PASSWORD=correcthorsebatterystaple
RESPONSE=$(
  curl -X POST \
    "https://${OKTA_ORG}.okta.com/api/v1/authn" \
    -H "Content-Type: application/json" \
    -d "{\"username\": \"${OKTA_USERNAME}\", \"password\": \"${OKTA_PASSWORD}\"}"
)

echo ${RESPONSE} | jq -r .status # MFA_REQUIRED
STATE_TOKEN=$(echo ${RESPONSE} | jq -r .stateToken)
FACTOR_ID=$(echo ${RESPONSE} | jq -r '._embedded.factors[] | select(.provider == "GOOGLE") | .id')
MFA_CODE=206847
RESPONSE=$(
  curl -X POST \
    "https://${OKTA_ORG}.okta.com/api/v1/authn/factors/${FACTOR_ID}/verify" \
    -H "Content-Type: application/json" \
    -d "{\"stateToken\": \"${STATE_TOKEN}\", \"passCode\": \"${MFA_CODE}\"}"
)

echo ${RESPONSE} | jq -r .status # SUCCESS

Create a session ID and retrieve the SAML assertion:

SESSION_TOKEN=$(echo ${RESPONSE} | jq -r .sessionToken)
RESPONSE=$(
  curl -X POST \
    "https://${OKTA_ORG}.okta.com/api/v1/sessions" \
    -H "Content-Type: application/json" \
    -d "{\"sessionToken\": \"${SESSION_TOKEN}\"}"
)
SESSION_ID=$(echo ${RESPONSE} | jq -r .id)
OKTA_APP_ID=T0tUQV9PUkc9dHViaQpP
RESPONSE=$(
  curl -L \
    "https://${OKTA_ORG}.okta.com/app/amazon_aws/${OKTA_APP_ID}/login" \
    -H "Cookie: sid=${SESSION_ID}"
)
SAML_B64=$(echo ${RESPONSE} | sed 's/^.*name="SAMLResponse" type="hidden" value="\([^\"]*\)".*$/\1/' | recode html)

Decode the SAML XML, extract available roles, and assume the first role with AWS STS:

ROLES=$(echo ${SAML_B64} | base64 --decode | xq -r '."saml2p:Response"."saml2:Assertion"."saml2:AttributeStatement"."saml2:Attribute"[] | select(."@Name" == "https://aws.amazon.com/SAML/Attributes/Role") | ."saml2:AttributeValue"[] | ."#text"')
ROLE=$(echo ${ROLES} | awk '{print $1}')
PRINCIPAL_ARN=$(echo ${ROLE} | jq -r -R 'split(",")[0]')
ROLE_ARN=$(echo ${ROLE} | jq -r -R 'split(",")[1]')
CREDENTIALS=$(aws sts assume-role-with-saml \
    --role-arn=${ROLE_ARN} --principal-arn=${PRINCIPAL_ARN} \
    --saml-assertion=${SAML_B64} --duration=3600)

Export the temporary credentials for use with the AWS CLI or SDKs:

export AWS_ACCESS_KEY_ID=$(echo ${CREDENTIALS} | jq -r .Credentials.AccessKeyId)
export AWS_SECRET_ACCESS_KEY=$(echo ${CREDENTIALS} | jq -r .Credentials.SecretAccessKey)
export AWS_SESSION_TOKEN=$(echo ${CREDENTIALS} | jq -r .Credentials.SessionToken)
aws sts get-caller-identity | jq -r .UserId

These credentials can now be used for further AWS operations, integrated with HashiCorp Vault for dynamic database access, and support fine‑grained access control across multiple accounts.

securityAWSIAMOktaSAMLSTS
Bitu Technology
Written by

Bitu Technology

Bitu Technology is the registered company of Tubi's China team. We are engineers passionate about leveraging advanced technology to improve lives, and we hope to use this channel to connect and advance together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.