Unable to link accounts

We have an SPA that connects to one of our restful API backends using a custom API audience. We now also want to have this SPA be able to link user accounts, which means it needs to access the management API as well. I have a few questions about that:

a) I guess we need 2 different access tokens with each having a different audience (one for our backend access and one for the management API access), is that correct?

b) If we need 2 different access tokens, is there a way to issue the second one (for the management API) without additional user interaction (I guess there should be the Auth0 SSO cookie set, could we use that)?

c) Is there a way to instead use the id token which we get after the social login from another application? The idea here would be to not access the management API in the frontend, but just get the id token for linking, send that to our backend which then does the linking using the management API. That way we won’t need an access token for the management API in the frontend. However, it seems like the id tokens are having the client id set as audience and this cannot be changed (so the backend application won’t be able to do the linking from an id token issued in the frontend application).

d) Is there a way to alternatively do the account linking on the backend (using a restful API)?

Thank you! :pray:

Hi @mellowjay,

Welcome to the Auth0 Community!

I understand that you have questions about Account Linking.

First, have you taken a look at Auth0’s Account Linking Extension? Perhaps that is an option you might find to fit your needs: https://auth0.com/docs/extensions/account-link-extension

Next, that is correct. Since your restful API backend uses a custom API audience, you’ll need to use the audience that references the Management API (audience= https://YOUR_DOMAIN/api/v2/ ).

And to configure your application for account linking with a server side implementation, please read our documentation below on how to do so: https://auth0.com/docs/users/user-account-linking/suggested-account-linking-server-side-implementation

Regarding the usage of ID tokens, that will not be possible. Previously, in some cases, you could use ID Tokens to link and unlink user accounts. However, this functionality is being deprecated and requires using Access Tokens in all cases.

Lastly, you might find the User Account Linking Scenarios documentation useful:
https://auth0.com/docs/users/user-account-linking#scenarios

Hoped this helps! Please let me know if need further assistance, I would be happy to help.

Thank you.

Let me jump in here to clear this up. We want to build some kind of “uniqueness” score for individual users, where they can increase their score by linking more social accounts. This is supposed to increase the difficulty to just create a bunch of different accounts and thus increases the likelihood that there is a unique user behind this account. If you have an Auth0 account that is linked to your Facebook, Twitter and Google account we assign you a higher score as when you just signed up using email/password.

The way we want to do this is to use the Account Linking functionality Auth0 provides and then read the list of identities of a user to assign a score. On the technical site we have a SPA which is our frontend and then a REST API on the backend.

Looking into the account linking docs, we figured:

  • The Account Linking Extension won’t work for us as it only offers linking accounts that use the same email. Users might not use the same email for Facebook & Google for example, but should still be able to link those two
  • Server side linking might be a possibility where the frontend redirects to the API, which then initiates the OAuth2 flow, does the linking and then redirects back to the frontend. However, I don’t think having the user interact directly with the REST API is good practice as it doesn’t provide any user feedback.
  • Client side linking is the preferred way. However, when the user logs in to our SPA it uses our backend as audience to access our APIs. That means we won’t be able to use this access token issued to do the account linking, but need a second one with the management API as audience. It is not clear to us whether it is possible to get such an access token issued without additional user input (we don’t want to have the user to log in twice for the same application).

Ah that’s a misunderstanding. We don’t want to use the ID token for linking accounts, but use the targetIdToken from the backend. See this example (from here)

const linkAccount = async () => {
  const accessToken = await auth0.getTokenSilently();
  const { sub } = await auth0.getUser();
  // authenticateUser should authenticate the user with the account to be linked
  // See the Github sample for more details
  const {
    __raw: targetUserIdToken,
    email_verified,
    email,
  } = await authenticateUser();
  if (!email_verified) {
    throw new Error(
      `Account linking is only allowed to a verified account. Please verify your email ${email}.`
    );
  }
  await fetch(`https://${config.domain}/api/v2/users/${sub}/identities`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${accessToken}`,
    },
    body: JSON.stringify({
      link_with: targetUserIdToken,
    }),
  });
};

The idea was to not do the last linking step on the frontend but let it be handled by the backend, so basically something like this:

const linkAccount = async () => {
  const accessToken = await auth0.getTokenSilently();
  const { sub } = await auth0.getUser();
  // authenticateUser should authenticate the user with the account to be linked
  // See the Github sample for more details
  const {
    __raw: targetUserIdToken,
    email_verified,
    email,
  } = await authenticateUser();
  if (!email_verified) {
    throw new Error(
      `Account linking is only allowed to a verified account. Please verify your email ${email}.`
    );
  }
  await fetch(`https://our-backend.foo/v1/auth/link_identity`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${accessToken}`,
    },
    body: JSON.stringify({
      link_with: targetUserIdToken,
    }),
  });
};

Where the https://our-backend.foo/v1/auth/link_identity endpoint is basically just a wrapper for the actual call to the management API. However the targetUserIdToken has the audience set to the client_id of the frontend and it seems like this cannot be changed (so the management API won’t accept this token when send from the backend with a different client_id). So I guess this way of linking account is not possible?

Hi @eosn-fred,

I’m sorry for the delayed response.

This is a great way to handle Account Linking.

I understand that you would prefer implementing client-side User-Initiated Account Linking, but need more information on how to obtain an access token to use the Management API without user interaction.

In User-Initiated Account Linking, the first step is the user logging in to request an Access Token for the Management API. Using the getTokenSilently method, you can get the user’s Access Token. Then you can use the Access token in your request to authenticate against the Management API to link the user account. This is described in our Client-Side Implementation docs here.

Alternatively, you could use the client_credentials grant to obtain an access token for the Management API. Allowing you to authenticate your user, as usual, using your backend audience to access your API.

You may find our Docs on Getting the Management API Access Tokens for Production ​helpful.

Please let me know if you have any questions. I’d be happy to help.

Thank you

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.