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, andopensslare installed on the broker host- An Atlas OAuth2 Service Account (Project Owner or Project Database Access Admin scope) with its
client_id/client_secretstored 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:
| Variable | Notes |
|---|---|
client_id | Atlas OAuth2 Service Account client ID — reference from Britive Secrets Store |
client_secret | Atlas OAuth2 Service Account client secret — reference from Britive Secrets Store |
project_id | Atlas project ID — set as a resource parameter |
atlas_username | Injected by Britive — the requesting user’s SSO email |
db_checkout_role | Atlas database role to grant (e.g. readAnyDatabase, dbAdmin) |
db_checkout_database | Target 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}"
fiCheckin 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."
fiThe 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:
| Variable | System defined | Notes |
|---|---|---|
atlas_username | Yes | Injected automatically — the requesting user’s SSO email |
client_id | No | Atlas OAuth2 Service Account client ID |
client_secret | No | Reference from Britive Secrets Store |
project_id | No | Set per resource |
db_checkout_role | No | e.g. readAnyDatabase, dbAdmin |
db_checkout_database | No | Target 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 Access → Check 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 failedTroubleshoot
| Symptom | Cause | Fix |
|---|---|---|
Empty or null access token | Wrong client_id/client_secret, or Service Account disabled | Verify the OAuth2 Service Account credentials and that the Service Account is active in Atlas |
HTTP 403 | Service Account lacks Project Owner / Project Database Access Admin scope | Assign the required role to the Service Account for the target project |
| Role not appended, existing roles wiped | db-role-checkout.sh role-merge jq step skipped or edited incorrectly | Confirm the checkout routine reads current roles before PATCHing — see the full script |
| User not deleted at checkin despite no other roles | REMAINING_ROLES count check failed, or db_checkout_role/db_checkout_database mismatch between checkout and checkin | Confirm both routines receive identical db_checkout_role and db_checkout_database values |
mongosh: command not found | MongoDB shell not installed locally | Install from mongodb.com/try/download/shell |