Last active
November 15, 2023 11:58
-
-
Save thameera/ae035e799381b00c988f98b50eaf5150 to your computer and use it in GitHub Desktop.
Bulk delete Auth0 users
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.