Hi,
Thanks Rueben, but I’m still having trouble with this. I’ve removed the api.redirect.sendUserTo() and so the linking is the end of the flow, but I’m still getting the same “Oops! something went wrong” 500 server_error: internal error.
I am using the unmodified JS Sample"My App" as a SPA; I’ve got the http://localhost:3000 in the Allowed Callback URLs, Allowed Logout URLs and Allowed Web Origins. Apart from “My App”, I have the “API Explorer Application” as a M2M with access & all permissions to the “Auth0 Management API”.
The first user (using Google Mail) logs in fine. The second user (using email/password with the same email as the Google Mail) signs in okay; the account links correctly; the User Management->Users->->Raw JSON looks good; the Webtasks looks correct; and the user is presented with the dialog to “Authorize App with Accept/Decline buttons”. However, once I press “Accept”, I get the “Oops! something went wrong” with a 500 internal server error.
The code is below.
var axios = require("axios").default;
exports.onExecutePostLogin = async (event, api) => {
console.log("auto-account-link: onExecutePostLogin: Started");
console.log("getting Session Token");
var options = {
method: 'POST',
url: `https://${event.secrets.domain}/oauth/token`,
headers: {'content-type': 'application/x-www-form-urlencoded'},
data: new URLSearchParams({
grant_type: 'client_credentials',
client_id: event.secrets.m2mClientId, // The clientId for the API Explorer Application
client_secret: event.secrets.m2mClientSecret, // For the API Explorer Application
audience: `https://${event.secrets.domain}/api/v2/`
})
};
axios.request(options).then(function (response) {
const sessionToken = response.data['access_token'];
console.log("About to search for candidateUsers with email="+event.user.email+" sessionToken "+sessionToken);
var options = {
method: 'GET',
url: `https://${event.secrets.domain}/api/v2/users-by-email`,
params: {email: event.user.email},
headers: {authorization: `Bearer ${sessionToken}`}
};
axios.request(options).then(function (response) {
processCandidates(event,sessionToken,response.data);
}).catch((error) => {
console.error(error);
});
}).catch(function (error) {
console.error(error);
});
}
async function processCandidates(event,sessionToken,candidateUsers) {
console.log("Found candidateUsers ..."); console.dir(candidateUsers);
// Only one user is returned then no linking necessary
if (!Array.isArray(candidateUsers)) {
console.log("Only 1 candidateUser found => no linking necessary");
return;
}
// Get the identities of the user
const candidateIdentities = candidateUsers.flatMap((user) => user.identities);
if(candidateIdentities.length <= 1) {
console.log("only 1 candidateIndentites found - nothing to do ...");
console.dir(candidateIdentities);
return;
}
// Returns the candidate that already exists
const oldExistingIdentity = candidateIdentities.find(
(identity) => identity.provider !== event.connection.strategy
);
await linkUserAccounts(event, sessionToken, oldExistingIdentity.provider + "|" + oldExistingIdentity.user_id);
console.log(`linked.`);
}
/**
* Calls the management api and links the old existing user into the new current user.
*/
async function linkUserAccounts(event, sessionToken, fullTargetId) {
const url = `https://${event.secrets.domain}/api/v2/users/${fullTargetId}/identities`;
var options = {
method: 'POST',
url: url,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': `Bearer ${sessionToken}`
},
data: {
"provider": event.connection.strategy,
"connection_id": event.connection.id,
"user_id": event.user.user_id
}
};
await axios.request(options).then(function (response) {
return;
}).catch(function (error) {
console.log("error...");
console.error(error);
});
}
The raw JSON is (using xxxxxxxxxxx to blank things)
{
"created_at": "2025-03-13T01:14:37.321Z",
"email": "xxxxxxxxxxx@gmail.com",
"email_verified": true,
"family_name": "xxxxxxxxxxx",
"given_name": "xxxxxxxxxxx",
"identities": [
{
"provider": "google-oauth2",
"user_id": "109774375892536849889",
"connection": "google-oauth2",
"isSocial": true
},
{
"profileData": {
"email": "xxxxxxxxxxx@gmail.com",
"email_verified": false
},
"connection": "Username-Password-Authentication",
"provider": "auth0",
"user_id": "67d23215684e8a99a822b064",
"isSocial": false
}
],
"name": "xxxxxxxxxxx xxxxxxxxxxx",
"nickname": "xxxxxxxxxxx",
"picture": "https://lh3.googleusercontent.com/a/ACg8xxxxxxxxxxxs96-c",
"updated_at": "2025-03-13T01:17:10.844Z",
"user_id": "google-oauth2|109774375892536849889",
"last_ip": "14.200.69.118",
"last_login": "2025-03-13T01:14:37.317Z",
"logins_count": 1,
"blocked_for": [],
"guardian_authenticators": [],
"passkeys": []
}
The Webtasks logfile is below with xxxxxxxxxxx blanking things …
12:14:38 PM:
getting Session Token
12:14:38 PM:
About to search for candidateUsers with email=xxxxxxxxxxx@gmail.com sessionToken eyJhxxxxxxxxxxxDEzSsQ
12:14:38 PM:
Found candidateUsers ...
12:14:38 PM:
[
{
created_at: '2025-03-13T01:14:37.321Z',
email: 'xxxxxxxxxxx@gmail.com',
email_verified: true,
family_name: 'xxxxxxxxxxx',
given_name: 'xxxxxxxxxxx',
identities: [ [Object] ],
name: 'xxxxxxxxxxx xxxxxxxxxxx',
nickname: 'xxxxxxxxxxx',
picture: 'https://lh3.googleusercontent.com/a/ACgxxxxxxxxxxx6-c',
updated_at: '2025-03-13T01:14:37.321Z',
user_id: 'google-oauth2|109774375892536849889',
last_ip: '14.200.69.118',
last_login: '2025-03-13T01:14:37.317Z',
logins_count: 1
}
]
12:14:38 PM:
only 1 candidateIndentites found - nothing to do ...
12:14:38 PM:
[
{
provider: 'google-oauth2',
access_token: 'yaxxxxxxxxxxx0177',
expires_in: 3598,
user_id: '109774375892536849889',
connection: 'google-oauth2',
isSocial: true
}
]
second login attempt using email/password with same email as above
12:17:10 PM:
getting Session Token
12:17:10 PM:
About to search for candidateUsers with email=xxxxxxxxxxx@gmail.com sessionToken eyJhbxxxxxxxxxxx0omFVg8g
12:17:10 PM:
Found candidateUsers ...
12:17:10 PM:
[
{
created_at: '2025-03-13T01:17:09.998Z',
email: 'xxxxxxxxxxx@gmail.com',
email_verified: false,
identities: [ [Object] ],
name: 'xxxxxxxxxxx@gmail.com',
nickname: 'xxxxxxxxxxx',
picture: 'https://s.gravatar.com/avatar/bfecxxxxxxxxxxx%2Fpo.png',
updated_at: '2025-03-13T01:17:09.998Z',
user_id: 'auth0|67d23215684e8a99a822b064',
last_ip: '14.200.69.118',
last_login: '2025-03-13T01:17:09.995Z',
logins_count: 1
},
{
created_at: '2025-03-13T01:14:37.321Z',
email: 'xxxxxxxxxxx@gmail.com',
email_verified: true,
family_name: 'xxxxxxxxxxx',
given_name: 'xxxxxxxxxxx',
identities: [ [Object] ],
name: 'xxxxxxxxxxx xxxxxxxxxxx',
nickname: 'xxxxxxxxxxx',
picture: 'https://lh3.googleusercontent.com/a/ACg8xxxxxxxxxxx96-c',
updated_at: '2025-03-13T01:14:37.321Z',
user_id: 'google-oauth2|109774375892536849889',
last_ip: '14.200.69.118',
last_login: '2025-03-13T01:14:37.317Z',
logins_count: 1
}
]
12:17:10 PM:
linked.