-
-
Save nickdunn/d31ba8ccd56838bd4a244af4eec29eab 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