Skip to content
Temporary Database User

Temporary Database User

Overview

At checkout, the broker calls the MongoDB Atlas Administration API to grant a database role to the requesting user. If the derived database user does not exist, it is created with a one-time generated password and the requested role; if it already exists, the role is appended to its existing roles so any baseline access is preserved. At checkin, only the JIT role is removed — the user is deleted entirely only if that leaves them with no roles at all (meaning they were created solely for this session).

Supported roles include any Atlas built-in role (atlasAdmin, readWriteAnyDatabase, readAnyDatabase, dbAdmin) or custom roles defined in your Atlas project.

MongoDB Atlas Federation (SAML/OIDC SSO) applies only to the Atlas control plane (UI and API) — it does not work for database connections. Database-level auth uses SCRAM (username/password), which is what this script generates.

Before You Begin

  • The broker is running and connected (see Getting Started)
  • curl, jq, base64, tr, and openssl are installed on the broker host
  • An Atlas OAuth2 Service Account (Project Owner or Project Database Access Admin scope) with its client_id/client_secret stored in the Britive Secrets Store
  • The Atlas project ID is set as a resource parameter

Checkout Routine

Full script: MongoDB Atlas/permissions/DB Roles/db-role-checkout.sh

Environment variables:

VariableNotes
client_idAtlas OAuth2 Service Account client ID — reference from Britive Secrets Store
client_secretAtlas OAuth2 Service Account client secret — reference from Britive Secrets Store
project_idAtlas project ID — set as a resource parameter
atlas_usernameInjected by Britive — the requesting user’s SSO email
db_checkout_roleAtlas database role to grant (e.g. readAnyDatabase, dbAdmin)
db_checkout_databaseTarget database name (e.g. mydb, admin)

Obtain a token and derive the database username:

TOKEN=$(curl -s -X POST "https://cloud.mongodb.com/api/oauth/token" \
  -H "Authorization: Basic $(printf '%s:%s' "${client_id}" "${client_secret}" | base64 | tr -d '\n')" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" | jq -r '.access_token')

# Derive a valid Atlas username from the SSO email — strip the domain and
# remove non-alphanumeric characters (e.g. jane.doe@contoso.com -> janedoe)
DB_USERNAME="${atlas_username%%@*}"
DB_USERNAME="${DB_USERNAME//[^a-zA-Z0-9]/}"

Create the user (if new) or append the role (if it already exists):

LOOKUP_CODE=$(curl -s -o /tmp/atlas_resp.json -w "%{http_code}" \
  "https://cloud.mongodb.com/api/atlas/v2/groups/${project_id}/databaseUsers/admin/${DB_USERNAME}" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Accept: application/vnd.atlas.2025-02-19+json, */*")

if [ "$LOOKUP_CODE" -eq 404 ]; then
  # New user — generate a one-time password and create them with the role
  DB_PASSWORD=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 24)

  curl -s -X POST "https://cloud.mongodb.com/api/atlas/v2/groups/${project_id}/databaseUsers" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    -d "{\"databaseName\":\"admin\",\"username\":\"${DB_USERNAME}\",\"password\":\"${DB_PASSWORD}\",\"roles\":[{\"roleName\":\"${db_checkout_role}\",\"databaseName\":\"${db_checkout_database}\"}]}"

  echo "username=${DB_USERNAME}"
  echo "password=${DB_PASSWORD}"
else
  # Existing user — append the JIT role to their current roles
  UPDATED_ROLES=$(jq '.roles // []' /tmp/atlas_resp.json | jq \
    --arg role "${db_checkout_role}" --arg db "${db_checkout_database}" \
    '. + [{"roleName": $role, "databaseName": $db}] | unique_by(.roleName + .databaseName)')

  curl -s -X PATCH "https://cloud.mongodb.com/api/atlas/v2/groups/${project_id}/databaseUsers/admin/${DB_USERNAME}" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    -d "{\"roles\": ${UPDATED_ROLES}}"

  echo "username=${DB_USERNAME}"
fi

Checkin Routine

Full script: MongoDB Atlas/permissions/DB Roles/db-role-checkin.sh

Remove the JIT role, deleting the user only if no roles remain:

DB_USERNAME="${atlas_username%%@*}"
DB_USERNAME="${DB_USERNAME//[^a-zA-Z0-9]/}"

curl -s -o /tmp/atlas_resp.json \
  "https://cloud.mongodb.com/api/atlas/v2/groups/${project_id}/databaseUsers/admin/${DB_USERNAME}" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Accept: application/vnd.atlas.2025-02-19+json, */*"

REMAINING_ROLES=$(jq \
  --arg role "${db_checkout_role}" --arg db "${db_checkout_database}" \
  '[.roles[]? | select(.roleName != $role or .databaseName != $db)]' /tmp/atlas_resp.json)

if [ "$(echo "$REMAINING_ROLES" | jq 'length')" -eq 0 ]; then
  # No roles left — this user was created solely for this JIT session
  curl -s -X DELETE "https://cloud.mongodb.com/api/atlas/v2/groups/${project_id}/databaseUsers/admin/${DB_USERNAME}" \
    -H "Authorization: Bearer ${TOKEN}"
  echo "User ${DB_USERNAME} deleted — no roles remained."
else
  # Other roles remain — only the JIT role is removed
  curl -s -X PATCH "https://cloud.mongodb.com/api/atlas/v2/groups/${project_id}/databaseUsers/admin/${DB_USERNAME}" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    -d "{\"roles\": ${REMAINING_ROLES}}"
  echo "Role ${db_checkout_role} revoked from ${DB_USERNAME} — other roles preserved."
fi

The checkin routine derives DB_USERNAME the same way checkout does, and needs a fresh OAuth2 token the same way (omitted above for brevity — see the full script). No state needs to be stored between checkout and checkin.


Configure in Britive

Create a response template

Go to Resource Manager → Response Templates → New Template. Add fields for username and password from the checkout routine output. These are the Atlas credentials returned to the user (password is only populated when a new user is created).

Create a permission

Go to Resource Manager → Resource Type Permissions → New Permission. Set Language to Shell.

Paste the checkout and checkin routines into the respective fields.

Declare variables:

VariableSystem definedNotes
atlas_usernameYesInjected automatically — the requesting user’s SSO email
client_idNoAtlas OAuth2 Service Account client ID
client_secretNoReference from Britive Secrets Store
project_idNoSet per resource
db_checkout_roleNoe.g. readAnyDatabase, dbAdmin
db_checkout_databaseNoTarget database name, e.g. mydb

Under Response Templates, attach the template you created.

Create a profile

Go to Resource Manager → Profiles → New Profile. Set an expiration (e.g. 2h). Under Associations, select the resource label(s) covering your Atlas resources. Under Permissions, add the permission above.

Add a policy

Under Policies, assign members (users or tags) and configure approval conditions.


Verify

Check out the profile

Navigate to My Access → find the profile → Check Out. For a first-time user, the Atlas username and a generated password appear in the checkout response. If the derived username already exists in Atlas, only the role is granted — no new password is issued.

Connect to the cluster

mongosh "mongodb+srv://<cluster-name>.mongodb.net" \
  --username <returned-username> \
  --password <returned-password>

Confirm the user exists in Atlas

In the Atlas console, go to Database Access — the temporary user should appear.

Check in

Return to My AccessCheck In.

Confirm the user is deleted

For a first-time user (created solely for this session), the user is deleted entirely on checkin — go to Database Access in the Atlas console and confirm it no longer appears. For a pre-existing user, only the JIT role is removed; the user itself remains with its baseline roles.

# Connection should fail after checkin
mongosh "mongodb+srv://<cluster-name>.mongodb.net" \
  --username <returned-username> \
  --password <returned-password>
# Expected: Authentication failed

Troubleshoot

SymptomCauseFix
Empty or null access tokenWrong client_id/client_secret, or Service Account disabledVerify the OAuth2 Service Account credentials and that the Service Account is active in Atlas
HTTP 403Service Account lacks Project Owner / Project Database Access Admin scopeAssign the required role to the Service Account for the target project
Role not appended, existing roles wipeddb-role-checkout.sh role-merge jq step skipped or edited incorrectlyConfirm the checkout routine reads current roles before PATCHing — see the full script
User not deleted at checkin despite no other rolesREMAINING_ROLES count check failed, or db_checkout_role/db_checkout_database mismatch between checkout and checkinConfirm both routines receive identical db_checkout_role and db_checkout_database values
mongosh: command not foundMongoDB shell not installed locallyInstall from mongodb.com/try/download/shell
Last updated on