Skip to content

Instantly share code, notes, and snippets.

@thameera
Last active November 15, 2023 11:58
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save thameera/ae035e799381b00c988f98b50eaf5150 to your computer and use it in GitHub Desktop.
Save thameera/ae035e799381b00c988f98b50eaf5150 to your computer and use it in GitHub Desktop.
Bulk delete Auth0 users
#!/usr/bin/env node
/*
* Install dependencies with:
* npm install request request-promise-native bottleneck
*
* Replace YOUR_TENANT_NAME, MGMT_TOKEN, and FILENAME
* The input file (FILENAME) should contain a list of user ids to delete, separated by newlines
*/
const fs = require('fs')
const rp = require('request-promise-native')
const Bottleneck = require('bottleneck')
const AUTH0_DOMAIN = 'https://{{YOUR_TENANT_NAME}}.auth0.com'
const MGMT_TOKEN = '{{MGMT_TOKEN}}'
const FILENAME = '{{FILENAME}}'
const rateLimit = (fn, num, time) => {
// as recommended by Bottleneck author
// https://github.com/SGrondin/bottleneck/issues/9
const limiter = new Bottleneck(0, 0)
limiter.changeReservoir(num)
setInterval(function() {
limiter.changeReservoir(num)
}, time)
return function rateLimitedFunction() {
const args = Array.from(arguments);
return limiter.schedule(fn, ...args)
}
}
let x = 1
let total = 0
const deleteUser = async id => {
console.log(`${x++}/${total}`)
const opts = {
url: `${AUTH0_DOMAIN}/api/v2/users/${id}`,
method: 'DELETE',
headers: {
Authorization: `Bearer ${MGMT_TOKEN}`
}
}
try {
const res = await rp(opts)
} catch (e) {
console.log(`Failed to delete user ${id}`)
console.log(e.message)
}
}
// Tested with 3500 users without an issue (takes about 2 mins 30 seconds)
// 20 is calls per second. Noticed that increasing the amount to 40, 50 etc throws 429s after a while,
// even though 50 per second is supported.
const deleteRateLimited = rateLimit(deleteUser, 20, 1000)
const deleteAll = async () => {
const ids = fs.readFileSync(FILENAME, 'utf8').split('\n').filter(u => !!u)
total = ids.length
ids.forEach(id => deleteRateLimited(id))
}
deleteAll()
@scout208
Copy link

Hey, I know you added this a long time ago and maybe you're not interested in maintaining it, but I noticed there's some breaking changes introduced in bottleneck v2. I fixed those in my fork. Also, for free plans the rate limit is 2 requests per second so I adjusted for that as well as default.

@useit015
Copy link

Saved me lots of time, thanks 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment