Created
December 15, 2021 13:58
-
-
Save teawithfruit/b76bf0d045958e25fbfdf9a28141c259 to your computer and use it in GitHub Desktop.
Migrate accounts with pbkdf2 passwords from MySQL to Keycloak
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
const mysql = require('mysql') | |
const { curly } = require('node-libcurl'); | |
const querystring = require('querystring'); | |
const host = 'URL_TO_KEYCLOAK' | |
const realm = 'REALM_NAME' | |
async function migrate() { | |
var connection = mysql.createConnection({ | |
host: 'HOST', // Insert your database host. | |
user: 'USER', // Insert your database user. | |
password: 'PASSWORD', // Insert your database password. | |
database: 'DATABASE_NAME' // Insert your database name. | |
}) | |
connection.connect() | |
let account = await new Promise(resolve => { | |
// Update this qurey to get the accounts from your database. | |
connection.query('SELECT id, username, email, password, salt FROM account', (error, results) => { | |
if(error) throw error; | |
resolve(results) | |
}) | |
}) | |
for(let a of account) { | |
const email = a.email | |
const username = a.username | |
const password = Buffer.from(a.password, 'hex').toString('base64') | |
const salt = Buffer.from(a.salt).toString('base64') | |
try { | |
const { data } = await curly.post(`${host}/realms/master/protocol/openid-connect/token`, { | |
POST: true, | |
SSL_VERIFYPEER: false, | |
POSTFIELDS: querystring.stringify({ | |
username: 'KEYCLOAK_ADMIN_USER', // Insert your keycloak admin user. | |
password: 'KEYCLOAK_ADMIN_PASSWORD', // Insert your keycloak admin password. | |
grant_type: 'password', | |
client_id: 'admin-cli' | |
}), | |
httpHeader: [ | |
'Content-Type: application/x-www-form-urlencoded', | |
'Accept: application/json' | |
], | |
}) | |
await curly.post(`${host}/admin/realms/${realm}/users`, { | |
POST: true, | |
SSL_VERIFYPEER: false, | |
POSTFIELDS: JSON.stringify({ | |
email: email, | |
emailVerified: true, | |
username: username, | |
enabled: true, | |
attributes: {}, | |
credentials: [ | |
{ | |
credentialData: JSON.stringify({ | |
hashIterations: 2048, // Change this if you have used a different number of interations. | |
algorithm: "pbkdf2-sha512" // Change this if you used a different pbkdf2 setting. | |
}), | |
secretData: JSON.stringify({ | |
salt: salt, | |
value: password, | |
additionalParameters: {} | |
}), | |
temporary: false, | |
type: "password" | |
} | |
] | |
}), | |
httpHeader: [ | |
'Content-Type: application/json', | |
'Accept: application/json', | |
`Authorization: Bearer ${data.access_token}` | |
], | |
}) | |
const response = await curly.get(`${host}/admin/realms/${realm}/users?email=${email}`, { | |
SSL_VERIFYPEER: false, | |
httpHeader: [ | |
'Content-Type: application/json', | |
'Accept: application/json', | |
`Authorization: Bearer ${data.access_token}` | |
] | |
}) | |
// Change or delete this query if you want to store the keycloak id in your database. | |
await new Promise(resolve => { | |
connection.query('UPDATE account SET keycloak = ? WHERE id = ?', [response.data[0].id, a.id], (error, results) => { | |
if(error) throw error; | |
resolve(results) | |
}) | |
}) | |
console.log(a.email); | |
} catch(e) { | |
console.log(e); | |
} | |
} | |
connection.end() | |
console.log('DONE'); | |
} | |
migrate() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment