Last active
March 24, 2023 03:50
-
-
Save jeff-auth0/1ac8bdc061589c6b1e962650cb9fb80f to your computer and use it in GitHub Desktop.
Trickle user migration to Auth0 from Azure B2C AD
This file contains hidden or 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
/** | |
* | |
* NOTE: THIS SCRIPT IS A GUIDE ONLY AND IT IS NOT TESTED IN A PRODUCTION ENVIRONMENT | |
* | |
* HOW: | |
* 1. Azure ROPC (Resource Owner Password Credentials) flow will be used to migrate users from Azure B2C AD to Auth0. | |
* 2. Lazy migration needs to be enable on your Auth0 Database. https://auth0.com/docs/manage-users/user-migration/configure-automatic-migration-from-your-database | |
* | |
* | |
* References: | |
* https://docs.microsoft.com/en-us/azure/active-directory-b2c/add-ropc-policy?tabs=app-reg-ga&pivots=b2c-user-flow#ropc-flow-notes | |
* https://auth0.com/docs/authenticate/database-connections/custom-db/overview-custom-db-connections | |
* https://auth0.com/docs/authenticate/database-connections/custom-db/templates/login | |
* | |
* Prerequisites: | |
* 1. Register an App in Azure B2C AD for this migration - Follow the guide in ROPC doc above. | |
* 2. Register an API ( an existing API can be used ) - this is required to get id token. | |
* 3. Add API Permissions for the application. Copy the URL of the scope | |
* | |
* TODO: | |
* 1. Verify JWT token. | |
* | |
* | |
*/ | |
function login(email, password, callback) { | |
let profile = {}; | |
let jwt_decode = require("jwt-decode"); | |
let request = require("request"); | |
const options = { | |
url: "<Azure ROPC Token Endpoint>", | |
formData: { | |
username: email, | |
password: password, | |
grant_type: "password", | |
scope: "openid <scope_url from step 3>", | |
client_id: "<Client Id of an registered App in Azure B2C>", | |
response_type: "token id_token", | |
}, | |
headers: [{ | |
name: "content-type", | |
value: "application/x-www-form-urlencoded", | |
}, ], | |
}; | |
request.post(options, (err, httpResponse, body) => { | |
if (err) { | |
return callback( | |
new WrongUsernameOrPasswordError(email, "Something went wrong"), | |
); | |
} | |
const parsed = JSON.parse(body); | |
if (parsed && parsed.id_token) { | |
var decoded = jwt_decode(parsed.id_token); | |
// Find more profile attributes: | |
// https://auth0.com/docs/authenticate/database-connections/custom-db/templates/login#callback-profile-parameter-example-) | |
profile = { | |
user_id: decoded.sub, | |
email, | |
family_name: decoded.family_name, | |
given_name: decoded.given_name, | |
}; | |
// Invoke Graph API /me endpoint to get extended attributes | |
request.get({ | |
url: "https://graph.microsoft.com/v1.0/me", | |
headers: [{ | |
name: "content-type", | |
value: "application/x-www-form-urlencoded", | |
Authorization: `Bearer ${parsed.id_token}`, | |
}, ], | |
}, | |
(err, httpResponse, body) => { | |
if (err) { | |
return callback( | |
new WrongUsernameOrPasswordError( | |
email, | |
"Cannot fetch extended profile attribute", | |
), | |
); | |
} | |
const extended_profile = JSON.parse(body); | |
if (!extended_profile) { | |
profile.app_metadata = { | |
key: extended_profile.name_of_attribute, | |
}; | |
} | |
}, | |
); | |
return callback(null, profile); | |
} else { | |
return callback(new Error("Unable to get token from Idp")); | |
} | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment