> ## Documentation Index
> Fetch the complete documentation index at: https://docs-staging-quickstart-revamp.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> This tutorial demonstrates how to add user login to an Android application using native Facebook Login.

# Android - Facebook Login

export const LoggedInForm = ({sampleApp}) => {
  const LS_APPS_KEY = "auth_demo_apps";
  const LS_APP_CFG_KEY = "auth_demo_app_cfg";
  const CHANNEL = "auth_flows_sync_v1";
  const mkChannel = () => new BroadcastChannel(CHANNEL);
  function uid() {
    return Math.random().toString(36).slice(2) + Date.now().toString(36);
  }
  function loadApps() {
    const raw = localStorage.getItem(LS_APPS_KEY);
    if (raw) return JSON.parse(raw);
    const seeded = [{
      id: "mz9iNEIo2PHu7oeh8QRt19ndTyyCIgai",
      name: "Default App"
    }];
    localStorage.setItem(LS_APPS_KEY, JSON.stringify(seeded));
    return seeded;
  }
  function saveApps(apps) {
    localStorage.setItem(LS_APPS_KEY, JSON.stringify(apps));
  }
  function loadCfg() {
    const raw = localStorage.getItem(LS_APP_CFG_KEY);
    return raw ? JSON.parse(raw) : {};
  }
  function saveCfg(cfg) {
    localStorage.setItem(LS_APP_CFG_KEY, JSON.stringify(cfg));
  }
  const RightChevron = ({className = "w-5 h-5", ...props}) => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke="currentColor" fill="none" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className} {...props}>
      <polyline points="9 18 15 12 9 6" />
    </svg>;
  const LightningIcon = () => <svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
      <path fillRule="evenodd" clipRule="evenodd" className="fill-[#3F59E4] dark:fill-[#99A7F1]" d="M24.971 30.152H7.088c-1.786 0-2.745-2.103-1.574-3.453l19.07-21.988c1.33-1.532 3.835-.4 3.569 1.607L24.97 30.152z" />
      <path fillRule="evenodd" clipRule="evenodd" className="fill-[#3F59E4] dark:fill-[#99A7F1]" d="M23.201 17.885h17.885c1.787 0 2.746 2.102 1.575 3.453l-19.073 21.99c-1.33 1.532-3.835.4-3.568-1.607L23.2 17.885z" />
    </svg>;
  const LayersIcon = () => <svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
      <path className="fill-[#3F59E4] dark:fill-[#99A7F1]" d="M34.54 29.135l6.373 3.183c1.566.782 1.566 3.017 0 3.8l-14.815 7.396a4.623 4.623 0 01-4.125 0L7.174 36.12c-1.565-.782-1.565-3.017 0-3.798l6.532-3.214" />
      <path className="fill-[#AAB6F3] dark:fill-[#3449BA]" d="M34.54 18.86l6.373 3.183c1.566.782 1.566 3.016 0 3.8L26.098 33.24a4.623 4.623 0 01-4.125 0L7.174 25.843c-1.565-.781-1.565-3.016 0-3.798l6.33-3.164" />
      <path className="fill-[#CFD6F8] dark:fill-[#22307C]" d="M21.94 23.058L7.306 15.745c-1.62-.81-1.62-3.123 0-3.932l14.631-7.319a4.693 4.693 0 014.194 0l14.648 7.319c1.622.81 1.62 3.124 0 3.932L26.13 23.058c-1.321.66-2.873.66-4.191 0z" />
    </svg>;
  const GithubIcon = () => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="w-5 h-5">
      <path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
    </svg>;
  function IconTile({children}) {
    return <div className="
          shrink-0 grid place-items-center w-10 h-10 rounded-lg
          bg-indigo-50 ring-1 ring-indigo-200/60
          dark:bg-indigo-950/40 dark:ring-white/10
        ">
        {children}
      </div>;
  }
  function Card({className = "", children}) {
    return <div className={`rounded-2xl shadow-sm ring-1 ring-zinc-200 dark:ring-zinc-800 ${className}`}>{children}</div>;
  }
  function Button({variant = "primary", type = "button", onClick, children}) {
    const base = "inline-flex items-center justify-center gap-2 h-10 px-4 rounded-xl font-medium transition";
    let styles = "";
    if (variant === "primary") {
      styles = "mint-bg-indigo-600 text-white hover:mint-bg-indigo-700";
    } else if (variant === "outline") {
      styles = "border border-zinc-300 dark:border-zinc-700 mint-bg-transparent hover:mint-bg-zinc-50 dark:hover:mint-bg-zinc-800";
    } else if (variant === "ghost") {
      styles = "hover:mint-bg-zinc-100 dark:hover:mint-bg-zinc-800";
    }
    return <button type={type} onClick={onClick} className={`${base} ${styles}`}>
        {children}
      </button>;
  }
  function Input({id, label, value, onChange, placeholder, name}) {
    return <label className="block space-y-1">
        <span className="text-sm text-zinc-700 dark:text-zinc-300">{label}</span>
        <input id={id} name={name} className="w-full h-11 px-3 rounded-xl border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-indigo-500" placeholder={placeholder} value={value} onChange={e => onChange(e.target.value)} />
      </label>;
  }
  function Select({label, value, onChange, options}) {
    return <label className="block space-y-1 max-w-[300px]">
        <span className="text-sm text-zinc-700 dark:text-zinc-300">{label}</span>
        <div className="relative">
          <select className="w-full h-11 appearance-none px-3 pr-9 rounded-xl border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-indigo-500" value={value} onChange={e => onChange(e.target.value)}>
            <optgroup label="Generic Applications">
              {options.map(o => <option key={o.id} value={o.id}>
                  {o.name}
                </option>)}
            </optgroup>
          </select>
          <svg className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 w-5 h-5 text-zinc-500" viewBox="0 0 24 24">
            <path d="M7 10l5 5 5-5z" fill="currentColor" />
          </svg>
        </div>
      </label>;
  }
  function Toast({open, onClose, children}) {
    useEffect(() => {
      if (!open) return;
      const t = setTimeout(onClose, 2200);
      return () => clearTimeout(t);
    }, [open, onClose]);
    return <div className={`fixed right-4 top-4 z-50 transition ${open ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-2 pointer-events-none"}`}>
        <div className="flex items-center gap-2 rounded-xl shadow ring-1 ring-emerald-200 bg-white dark:bg-zinc-900 px-4 py-2">
          <span className="w-1.5 h-8 rounded-l bg-emerald-500" />
          <svg className="w-5 h-5 text-emerald-600" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
            <path d="M20 6L9 17l-5-5" />
          </svg>
          <span className="text-sm text-zinc-900 dark:text-zinc-100">{children}</span>
        </div>
      </div>;
  }
  function Flows() {
    const [route, setRoute] = useState("menu");
    const [apps, setApps] = useState(loadApps());
    const [cfg, setCfg] = useState(loadCfg());
    const [selected, setSelected] = useState(apps[0]?.id || "");
    const [toast, setToast] = useState(false);
    const [bc] = useState(() => mkChannel());
    useEffect(() => {
      if (!apps.find(a => a.id === selected)) {
        setSelected(apps[0]?.id || "");
      }
    }, [apps, selected]);
    useEffect(() => {
      const onMsg = e => {
        const {type, payload} = e.data || ({});
        switch (type) {
          case "NAV":
            setRoute(payload.route);
            break;
          case "SELECT":
            setSelected(payload.appId);
            break;
          case "APPS_UPDATED":
            setApps(loadApps());
            break;
          case "CFG_UPDATED":
            setCfg(loadCfg());
            setToast(true);
            break;
          default:
            break;
        }
      };
      bc.addEventListener("message", onMsg);
      return () => bc.removeEventListener("message", onMsg);
    }, [bc]);
    const nav = nextRoute => {
      setRoute(nextRoute);
      bc.postMessage({
        type: "NAV",
        payload: {
          route: nextRoute
        }
      });
    };
    const selectApp = appId => {
      setSelected(appId);
      bc.postMessage({
        type: "SELECT",
        payload: {
          appId
        }
      });
    };
    const onCreate = name => {
      const id = uid();
      const next = [...apps, {
        id,
        name: name || "Untitled"
      }];
      setApps(next);
      saveApps(next);
      bc.postMessage({
        type: "APPS_UPDATED"
      });
      selectApp(id);
      nav("integrate");
    };
    const onSaveCfg = (appId, data) => {
      const next = {
        ...cfg,
        [appId]: data
      };
      setCfg(next);
      saveCfg(next);
      setToast(true);
      bc.postMessage({
        type: "CFG_UPDATED"
      });
    };
    return <div>
        {route === "menu" && <Menu onCreate={() => nav("create")} onIntegrate={() => nav("integrate")} />}

        {route === "create" && <CreateForm onCancel={() => nav("menu")} onSave={onCreate} />}

        {route === "integrate" && <IntegrateForm apps={apps} selected={selected} onSelect={selectApp} saved={cfg[selected]} onSave={data => onSaveCfg(selected, data)} onCancel={() => nav("menu")} />}

        <Toast open={toast} onClose={() => setToast(false)}>
          Successfully saved your changes.
        </Toast>
      </div>;
  }
  function Menu({onCreate, onIntegrate}) {
    return <ul className="space-y-4 list-none login_list">
        <li className="list-none !px-0">
          <button onClick={onCreate} className="w-full text-left">
            <Card className="p-5 hover:shadow-md transition">
              <div className="flex items-center justify-between">
                <div className="flex items-center gap-4">
                  <IconTile>
                    <LightningIcon />
                  </IconTile>
                  <h2 className="text-lg">Create a new application</h2>
                </div>
                <RightChevron className="w-4 h-4 text-zinc-500" />
              </div>
            </Card>
          </button>
        </li>
        <li className="list-none !px-0">
          <button onClick={onIntegrate} className="w-full text-left">
            <Card className="p-5 hover:shadow-md transition">
              <div className="flex items-center justify-between">
                <div className="flex items-center gap-4">
                  <IconTile>
                    <LayersIcon />
                  </IconTile>
                  <h2 className="text-lg">Integrate with an existing application</h2>
                </div>
                <RightChevron className="w-4 h-4 text-zinc-500" />
              </div>
            </Card>
          </button>
        </li>
        <li className="list-none !px-0">
          <a className="no_external_icon block" href={sampleApp ? sampleApp : "/"} target="_blank" rel="noreferrer">
            <Card className="p-5 hover:shadow-md transition">
              <div className="flex items-center justify-between">
                <div className="flex items-center gap-4">
                  <IconTile>
                    <GithubIcon />
                  </IconTile>
                  <h2 className="text-lg">View a sample application</h2>
                </div>
                <RightChevron className="w-4 h-4 text-zinc-500" />
              </div>
            </Card>
          </a>
        </li>
      </ul>;
  }
  function CreateForm({onSave, onCancel}) {
    const [name, setName] = useState("");
    return <div className="space-y-6">
        <Input id="app-name" label="Application Name" placeholder="My App" value={name} onChange={setName} />
        <p className="text-sm text-zinc-500">You can change this later in the application settings.</p>
        <div className="flex gap-3">
          <Button onClick={() => onSave(name)}>Save</Button>
          <Button variant="outline" onClick={onCancel}>
            Cancel
          </Button>
        </div>
      </div>;
  }
  function IntegrateForm({apps, selected, onSelect, saved, onSave, onCancel}) {
    const [callbacks, setCallbacks] = useState(saved?.callbacks ?? "");
    const [logouts, setLogouts] = useState(saved?.logouts ?? "");
    const [origins, setOrigins] = useState(saved?.origins ?? "");
    useEffect(() => {
      setCallbacks(loadCfg()[selected]?.callbacks ?? "");
      setLogouts(loadCfg()[selected]?.logouts ?? "");
      setOrigins(loadCfg()[selected]?.origins ?? "");
    }, [selected]);
    return <div className="space-y-6">
        <div>
          <span className="block text-sm text-zinc-600 dark:text-zinc-300 mb-1">Select your Application</span>
          <Select label="" value={selected} onChange={onSelect} options={apps} />
        </div>

        <form className="space-y-4" onSubmit={e => {
      e.preventDefault();
      onSave({
        callbacks,
        logouts,
        origins
      });
    }}>
          <Input id="callbacks" name="callbacks" label="Callback URLs" placeholder="http://localhost:3000" value={callbacks} onChange={setCallbacks} />
          <Input id="logout" name="allowed_logout_urls" label="Logout URLs" placeholder="http://localhost:3000" value={logouts} onChange={setLogouts} />
          <Input id="origins" name="web_origins" label="Allowed Web Origins" placeholder="http://localhost:3000" value={origins} onChange={setOrigins} />

          <div className="flex gap-3 pt-2">
            <Button type="submit">Save</Button>
            <Button variant="outline" type="button" onClick={onCancel}>
              Cancel
            </Button>
          </div>
        </form>
      </div>;
  }
  return <div className="w-full mx-auto py-8">
      <Flows />
    </div>;
};

export const SignUpForm = () => {
  return <div className="flex flex-col gap-2 items-center h-full">
      <img noZoom src="/docs/img/quickstarts/action_hero_dashboard.svg" alt="Sign up for an Auth0 account" style={{
    width: "250px",
    height: "250px"
  }} />
      <span className="text-center" style={{
    width: "400px"
  }}>
        Sign up for an{" "}
        <a href="https://auth0.com/signup" target="_blank" rel="noopener noreferrer">
          Auth0 account
        </a>{" "}
        or{" "}
        <span className="font-semibold text-primary cursor-pointer" onClick={() => console.log("log in")}>
          log in
        </span>{" "}
        to your existing account to integrate directly with your own tenant.
      </span>
      <button onClick={() => console.log("sign up")} className="bg-primary dark:bg-primary-light text-white dark:text-black px-4 py-2 rounded-md mt-4 font-medium" style={{
    width: "140px"
  }}>
        Sign up
      </button>
    </div>;
};

export const SideMenuSectionItem = ({id, children}) => {
  return <div id={`side-menu-item-${id}`} className="recipe-side-menu-item flex flex-col w-full h-full">
      {children}
    </div>;
};

export const SideMenu = ({sections, children}) => {
  const [visibleSection, setVisibleSection] = useState(sections[0]?.id ?? null);
  const checkVisibility = () => {
    let currentVisible = null;
    const viewportHeight = window.innerHeight;
    const scrollY = window.scrollY;
    sections.forEach(({id}) => {
      const section = document.getElementById(id);
      if (section) {
        const rect = section.getBoundingClientRect();
        const sectionTop = rect.top + scrollY;
        const sectionBottom = sectionTop + rect.height;
        const multiplier = viewportHeight > 1600 ? 0.34 : 0.22;
        if (scrollY + viewportHeight * multiplier >= sectionTop && scrollY <= sectionBottom) {
          currentVisible = id;
        }
      }
    });
    if (currentVisible && currentVisible !== visibleSection) {
      setVisibleSection(currentVisible);
    }
  };
  useEffect(() => {
    const throttledCheck = () => {
      setTimeout(checkVisibility, 100);
    };
    checkVisibility();
    window.addEventListener("scroll", throttledCheck);
    return () => {
      window.removeEventListener("scroll", throttledCheck);
    };
  }, [sections, visibleSection]);
  useEffect(() => {
    sections.forEach(({id}) => {
      const section = document.getElementById(id);
      const sideMenuItem = document.getElementById(`side-menu-item-${id}`);
      if (section) {
        if (id === visibleSection) {
          section.classList.add("active-section");
        } else {
          section.classList.remove("active-section");
        }
      }
      if (sideMenuItem) {
        if (id === visibleSection) {
          sideMenuItem.classList.add("active-side-menu-item");
        } else {
          sideMenuItem.classList.remove("active-side-menu-item");
        }
      }
    });
  }, [visibleSection, sections]);
  return <div className="recipe-side-menu sticky px-2 py-1" style={{
    height: "calc(100vh - 7rem)",
    top: "7rem",
    scrollMarginTop: "var(--scroll-mt)"
  }}>
      {children.map(child => {
    if (child.props.id === visibleSection) {
      return child;
    }
    return null;
  })}
    </div>;
};

export const Section = ({id, title, stepNumber, children, isSingleColumn = false}) => {
  return <div id={id} className={`recipe-section flex flex-col transition-opacity duration-200`}>
      {}
      <Step title={title} stepNumber={stepNumber} titleSize="h3">
        {children}
      </Step>
    </div>;
};

export const Content = ({title, children}) => {
  return <div className="recipe-content flex flex-col">
      {title && <h1 className="text-3xl">{title}</h1>}
      {children}
    </div>;
};

export const Recipe = ({children, isSingleColumn = false}) => {
  return <div className={`pl-4 recipe-container mx-auto grid grid-cols-1 gap-10 relative ${isSingleColumn ? "md:grid-cols-1" : "md:grid-cols-2"}`}>
      {children}
    </div>;
};

export const sections = [{
  id: "system-requirements",
  title: "System requirements"
}, {
  id: "before-you-start",
  title: "Before You Start"
}, {
  id: "request-facebook-permissions",
  title: "Request Facebook permissions"
}, {
  id: "create-performlogin-method",
  title: "Create performLogin method"
}, {
  id: "call-performlogin-method",
  title: "Call performLogin method"
}, {
  id: "integrate-facebook",
  title: "Integrate Facebook"
}, {
  id: "fetch-facebook-session-access-token",
  title: "Fetch Facebook session Access Token"
}, {
  id: "fetch-facebook-user-profile",
  title: "Fetch Facebook user profile"
}, {
  id: "integrate-auth0",
  title: "Integrate Auth0"
}, {
  id: "exchange-the-received-data-for-auth0-tokens",
  title: "Exchange the received data for Auth0 tokens"
}, {
  id: "update-performlogin-method",
  title: "Update performLogin method"
}];

<Recipe>
  <Content>
    This tutorial demonstrates how to add user login to an Android application using native Facebook Login. We
    recommend that you log in to follow this quickstart with examples configured for your account.

    <Section id={sections[0].id} title={sections[0].title} stepNumber="1">
      * Android Studio 3.6.1
      * Android SDK 25
      * Emulator - Nexus 5X - Android 6.0

      This tutorial describes how to implement login with the [Facebook SDK](https://developers.facebook.com/docs/).​
    </Section>

    <Section id={sections[1].id} title={sections[1].title} stepNumber="2">
      * Install and configure the [Facebook Login SDK](https://developers.facebook.com/docs/facebook-login/). You’ll also go through the process of creating a Facebook
        app in [https://developers.facebook.com](https://developers.facebook.com/). **When you finish this step, you should have
        a mobile app running with Facebook Login integrated.**

      Configure your Auth0 application in the dashboard to use Facebook Native Sign In. See [Add Facebook Login to Native
      Apps](https://auth0.com/docs/connections/nativesocial/facebook). **When you finish this step, your application will be able to implement Facebook Native Login.**
    </Section>

    <Section id={sections[2].id} title={sections[2].title} stepNumber="3">
      Your application is already able to sign in with Facebook. However, to ensure you have a rich user profile, you
      need to update the permissions with which the Facebook Login Button was set up.

      Set the requested permissions to `public_profile` and `email`. This way, the user email
      will also be included as part of the response, provided the access request is accepted by the user.

      ```kt lines
      loginButton.setPermissions(Arrays.asList("public_profile", "email"));
      ```
    </Section>

    <Section id={sections[3].id} title={sections[3].title} stepNumber="4">
      Now, to kick off the authentication process with Auth0, create a new method in which you will prepare the payload
      to be sent.

      You will make use of a small interface to handle our internal callbacks.

      In the sample, the method was named `performLogin` and the interface `SimpleCallback`. Go
      ahead and add both.
    </Section>

    <Section id={sections[4].id} title={sections[4].title} stepNumber="5">
      Now, call the method from the Facebook login callback's `onSuccess` method.
    </Section>

    <Section id={sections[5].id} title={sections[5].title} stepNumber="6">
      When you sign in with Facebook at Auth0, the backend will perform some checks in the background to ensure the
      user is who they say they are. To achieve this, it needs to be provided with a Session Access Token.

      Furthermore, if a user needs to be created on Auth0 to represent this Facebook user, the backend will require
      some of their information, such as their name, last name, and email. The email, if provided, will be flagged as
      non-verified on the Auth0 user profile.

      To obtain the Session Access Token and the user profile, two additional requests need to be made against the
      Facebook API.
    </Section>

    <Section id={sections[6].id} title={sections[6].title} stepNumber="7">
      Make a new GET request against the Facebook API's `/oauth/access_token` endpoint. Use the following
      query parameters:

      * `grant_type`: `fb_attenuate_token`.
      * `fb_exchange_token`: the access token received upon login.
      * `client_id`: your App ID. This value comes from the Facebook Developer's dashboard and should
        already be in use in your application if you have integrated Facebook Login successfully.

      Put the logic from this step in its own method. You will be calling it later from the previously-added method.

      The sample uses the Facebook SDK's `GraphRequest` class to perform this request.
    </Section>

    <Section id={sections[7].id} title={sections[7].title} stepNumber="8">
      Now make another GET request, just like in the step above. The endpoint path will be the User ID value from the
      Facebook login result (for example, `/904636746222815`). Use the following parameters:

      * `access_token`: the access token received upon login.
      * `fields`: the fields from the user profile that you'd like to get back in the response. These are
        directly tied to the Facebook Login Button permissions that were configured at the beginning. When a
        permission is optional, the user must first consent to give access to it. For the purpose of signing up a user
        at Auth0, their full name and email will suffice.
    </Section>

    <Section id={sections[8].id} title={sections[8].title} stepNumber="9">
      Now that the required artifacts have been obtained, you are ready to trade them for Auth0 user credentials, such
      as the ID and Access Tokens. But first, you must set up the Auth0 SDK to make that last request.

      ### Get your application keys

      1. Go to the **Applications** section of the [Auth0 Dashboard](https://manage.auth0.com/) and select the existing application in which you enabled
         **Sign in with Facebook**. If you need help with this step, please check the requirements section at the
         top of this article.
      2. Copy the **Domain** and **Client ID** values from the application settings page. These are required by
         the SDK.
      3. Create two new resources in your Android application's strings.xml file to store them. The name of the keys
         must match the ones used below:

      ```xml lines
      <resources>

            <string name="com_auth0_domain">dev-gja8kxz4ndtex3rq.us.auth0.com</string>

            <string name="com_auth0_client_id">mz9iNEIo2PHu7oeh8QRt19ndTyyCIgai</string>

      </resources>
      ```

      ### Install the Auth0 SDK

      In your Android application, add this line to the app/build.gradle file:

      ```text lines
      dependencies {
            implementation 'com.auth0.android:auth0:1.+'
      }
      ```

      Now is time to run the Gradle Sync task to refresh the project and its dependencies.

      ### Update manifest for web authentication

      If your application does not plan to make use of the Web Authentication module provided by the SDK, you will need
      to remove the unused activity from the AndroidManifest.xml file to prevent Manifest Placeholder issues. This can
      be achieved by adding an activity declaration and annotating it with tools:node="remove".

      ```xml lines
      <application>
      <!-- Add the activity declaration line below -->
      <activity
      android:name="com.auth0.android.provider.AuthenticationActivity"
      tools:node="remove" />
      </application>
      ```

      However, if you do plan to support Web Authentication, head over [here](https://auth0.com/docs/libraries/auth0-android#authentication-via-universal-login) to learn how to declare the Manifest Placeholders.
    </Section>

    <Section id={sections[9].id} title={sections[9].title} stepNumber="10">
      The SDK must be instantiated before use. Define a field at the class level and initialize it on the
      `onCreate` method. Note how the credentials defined in the step above are passed to the
      `Auth0` constructor and then a new instance of the `AuthenticationAPIClient` is created with
      it.

      ```kt lines
      private AuthenticationAPIClient auth0Client;
      @Override
      public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);



      setContentView(R.layout.activity_login);



      Auth0 account = new Auth0(getString(R.string.com_auth0_client_id), getString(R.string.com_auth0_domain));

      auth0Client = new AuthenticationAPIClient(account);



      //...

      }
      ```

      Create the method that will hold the logic to exchange the two obtained artifacts for Auth0 user credentials. In
      the sample, this method is named `exchangeTokens`.

      The API client declares the method `loginWithNativeSocialToken` that receives a token and a subject
      type. The former corresponds to the session token, and the latter indicates what type of connection the backend
      will attempt to authenticate with.

      For native Facebook Login, you will use the following value:
      `"http://auth0.com/oauth/token-type/facebook-info-session-access-token"`

      Other values that need to be configured are the user profile (using the `user_profile` key) and the
      scope you request the Auth0 tokens contain.

      <Info>
        It's a good practice to keep all the values that you know won't change as constants at the top of the
        class. The sample makes use of constants for the subject token type, the Facebook permissions, and the
        Auth0 scopes. You can read more about Auth0 scopes in the dedicated article.
      </Info>
    </Section>

    <Section id={sections[10].id} title={sections[10].title} stepNumber="11">
      Now that every step is defined in its own method, it's time to put everything together inside the
      `performLogin` method.

      If everything went well, you should now be able to authenticate natively with the Facebook Login SDK. This means
      that if the Facebook app is installed on the device, the authentication will be handled via the application and
      not a browser app.
    </Section>
  </Content>

  <SideMenu sections={sections}>
    <SideMenuSectionItem id={sections[0].id}>
      <SignUpForm />
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[1].id}>
      <SignUpForm />
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[2].id}>
      <SignUpForm />
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[3].id}>
      <CodeGroup>
        ```kt performLogin+SimpleCallback lines 
        private interface SimpleCallback<T> {
          fun onResult(result: T)

          fun onError(cause: Throwable)
        }
        ```

        ```kt onCreate lines 
        override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)

                FacebookSdk.setClientToken(getString(R.string.facebook_client_token))
                FacebookSdk.sdkInitialize(this)

                setContentView(R.layout.activity_login)

                val auth0 =
                    Auth0(getString(R.string.com_auth0_client_id), getString(R.string.com_auth0_domain))
                apiClient = AuthenticationAPIClient(auth0)

                fbCallbackManager = CallbackManager.Factory.create()

                val loginButton = findViewById<LoginButton>(R.id.login_button).apply {
                    setPermissions(*FACEBOOK_PERMISSIONS)
                }

                loginButton.registerCallback(fbCallbackManager, object : FacebookCallback<LoginResult> {
                    override fun onSuccess(result: LoginResult) {

                        val accessToken = result.accessToken
                        performLogin(accessToken)
                    }

                    override fun onCancel() {
                        Log.i(TAG, "Facebook sign-in cancelled")
                    }

                    override fun onError(error: FacebookException) {
                        Log.e(TAG, "Error {error.message}")
                    }
                })
            }
        ```

        ```kt fetchSessionToken lines 
        private fun fetchSessionToken(token: String, callback: SimpleCallback<String>) {
                val params = Bundle().apply {
                    putString("grant_type", "fb_attenuate_token")
                    putString("fb_exchange_token", token)
                    putString("client_id", getString(R.string.facebook_app_id))
                }

                val request = GraphRequest().apply {
                    parameters = params
                    graphPath = "oauth/access_token"
                }

                request.callback = GraphRequest.Callback { response ->
                    if (response.error != null) {
                        callback.onError(response.error?.exception!!)
                        return@Callback
                    }

                    try {
                        val fbSessionToken = response.jsonObject!!.getString("access_token")
                        callback.onResult(fbSessionToken)
                    } catch (jsonException: JSONException) {
                        //Failed to parse session token
                        callback.onError(jsonException)
                    }
                }
                request.executeAsync()
            }
        ```

        ```kt fetchUserProfile lines 
        private fun fetchUserProfile(token: String, userId: String, callback: SimpleCallback<String>) {

                val params = Bundle().apply {
                    putString("access_token", token)
                    putString("fields", "first_name,last_name,email")
                }

                val request = GraphRequest().apply {
                    parameters = params
                    graphPath = userId
                }

                request.callback = GraphRequest.Callback { response ->
                    val error = response.error
                    if (error != null) {
                        //Failed to fetch user profile
                        callback.onError(error.exception!!)
                        return@Callback
                    }
                    //Handle back the profile as received
                    callback.onResult(response.rawResponse!!)
                }

                request.executeAsync()
            }
        ```

        ```kt exchangeTokens lines 
        private fun exchangeTokens(
                sessionToken: String,
                userProfile: String,
                callback: SimpleCallback<Credentials>
            ) {
                val params = mapOf("user_profile" to userProfile)
                apiClient.loginWithNativeSocialToken(sessionToken, FACEBOOK_SUBJECT_TOKEN_TYPE)
                    .setScope(AUTH0_SCOPE)
                    .addParameters(params)
                    .start(object : Callback<Credentials, AuthenticationException> {
                        override fun onFailure(error: AuthenticationException) {
                            callback.onError(error)
                        }

                        override fun onSuccess(result: Credentials) {
                            callback.onResult(result)
                        }
                    })
            }
        ```

        ```kt performLogin lines 
        private fun performLogin(accessToken: AccessToken) {
                val token = accessToken.token
                fetchSessionToken(token, object : SimpleCallback<String> {
                    override fun onResult(sessionToken: String) {
                        //2. Obtained the Facebook session token
                        fetchUserProfile(token, accessToken.userId, object : SimpleCallback<String> {
                            override fun onResult(userProfile: String) {
                                //3. Obtained the user profile
                                exchangeTokens(
                                    sessionToken,
                                    userProfile,
                                    object : SimpleCallback<Credentials> {
                                        override fun onResult(credentials: Credentials) {
                                            //4. Exchanged the tokens
                                            Log.i(TAG, "Logged in to Auth0")
                                        }

                                        override fun onError(cause: Throwable) {
                                            Log.e(TAG, "Error exchanging tokens", cause)
                                        }
                                    })
                            }

                            override fun onError(cause: Throwable) {
                                Log.e(TAG, "Error fetching the profile", cause)
                            }
                        })
                    }

                    override fun onError(cause: Throwable) {
                        Log.e(TAG, "Error fetching the session token", cause)
                    }
                })
            }
        ```
      </CodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[4].id}>
      <CodeGroup>
        ```kt onCreate lines 
        override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)

                FacebookSdk.setClientToken(getString(R.string.facebook_client_token))
                FacebookSdk.sdkInitialize(this)

                setContentView(R.layout.activity_login)

                val auth0 =
                    Auth0(getString(R.string.com_auth0_client_id), getString(R.string.com_auth0_domain))
                apiClient = AuthenticationAPIClient(auth0)

                fbCallbackManager = CallbackManager.Factory.create()

                val loginButton = findViewById<LoginButton>(R.id.login_button).apply {
                    setPermissions(*FACEBOOK_PERMISSIONS)
                }

                loginButton.registerCallback(fbCallbackManager, object : FacebookCallback<LoginResult> {
                    override fun onSuccess(result: LoginResult) {

                        val accessToken = result.accessToken
                        performLogin(accessToken)
                    }

                    override fun onCancel() {
                        Log.i(TAG, "Facebook sign-in cancelled")
                    }

                    override fun onError(error: FacebookException) {
                        Log.e(TAG, "Error {error.message}")
                    }
                })
            }
        ```

        ```kt performLogin+SimpleCallback lines 
        private interface SimpleCallback<T> {
          fun onResult(result: T)

          fun onError(cause: Throwable)
        }
        ```

        ```kt fetchSessionToken lines 
        private fun fetchSessionToken(token: String, callback: SimpleCallback<String>) {
                val params = Bundle().apply {
                    putString("grant_type", "fb_attenuate_token")
                    putString("fb_exchange_token", token)
                    putString("client_id", getString(R.string.facebook_app_id))
                }

                val request = GraphRequest().apply {
                    parameters = params
                    graphPath = "oauth/access_token"
                }

                request.callback = GraphRequest.Callback { response ->
                    if (response.error != null) {
                        callback.onError(response.error?.exception!!)
                        return@Callback
                    }

                    try {
                        val fbSessionToken = response.jsonObject!!.getString("access_token")
                        callback.onResult(fbSessionToken)
                    } catch (jsonException: JSONException) {
                        //Failed to parse session token
                        callback.onError(jsonException)
                    }
                }
                request.executeAsync()
            }
        ```

        ```kt fetchUserProfile lines 
        private fun fetchUserProfile(token: String, userId: String, callback: SimpleCallback<String>) {

                val params = Bundle().apply {
                    putString("access_token", token)
                    putString("fields", "first_name,last_name,email")
                }

                val request = GraphRequest().apply {
                    parameters = params
                    graphPath = userId
                }

                request.callback = GraphRequest.Callback { response ->
                    val error = response.error
                    if (error != null) {
                        //Failed to fetch user profile
                        callback.onError(error.exception!!)
                        return@Callback
                    }
                    //Handle back the profile as received
                    callback.onResult(response.rawResponse!!)
                }

                request.executeAsync()
            }
        ```

        ```kt exchangeTokens lines 
        private fun exchangeTokens(
                sessionToken: String,
                userProfile: String,
                callback: SimpleCallback<Credentials>
            ) {
                val params = mapOf("user_profile" to userProfile)
                apiClient.loginWithNativeSocialToken(sessionToken, FACEBOOK_SUBJECT_TOKEN_TYPE)
                    .setScope(AUTH0_SCOPE)
                    .addParameters(params)
                    .start(object : Callback<Credentials, AuthenticationException> {
                        override fun onFailure(error: AuthenticationException) {
                            callback.onError(error)
                        }

                        override fun onSuccess(result: Credentials) {
                            callback.onResult(result)
                        }
                    })
            }
        ```

        ```kt performLogin lines 
        private fun performLogin(accessToken: AccessToken) {
                val token = accessToken.token
                fetchSessionToken(token, object : SimpleCallback<String> {
                    override fun onResult(sessionToken: String) {
                        //2. Obtained the Facebook session token
                        fetchUserProfile(token, accessToken.userId, object : SimpleCallback<String> {
                            override fun onResult(userProfile: String) {
                                //3. Obtained the user profile
                                exchangeTokens(
                                    sessionToken,
                                    userProfile,
                                    object : SimpleCallback<Credentials> {
                                        override fun onResult(credentials: Credentials) {
                                            //4. Exchanged the tokens
                                            Log.i(TAG, "Logged in to Auth0")
                                        }

                                        override fun onError(cause: Throwable) {
                                            Log.e(TAG, "Error exchanging tokens", cause)
                                        }
                                    })
                            }

                            override fun onError(cause: Throwable) {
                                Log.e(TAG, "Error fetching the profile", cause)
                            }
                        })
                    }

                    override fun onError(cause: Throwable) {
                        Log.e(TAG, "Error fetching the session token", cause)
                    }
                })
            }
        ```
      </CodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[5].id}>
      <SignUpForm />
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[6].id}>
      <CodeGroup>
        ```kt onCreate lines 
        override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)

                FacebookSdk.setClientToken(getString(R.string.facebook_client_token))
                FacebookSdk.sdkInitialize(this)

                setContentView(R.layout.activity_login)

                val auth0 =
                    Auth0(getString(R.string.com_auth0_client_id), getString(R.string.com_auth0_domain))
                apiClient = AuthenticationAPIClient(auth0)

                fbCallbackManager = CallbackManager.Factory.create()

                val loginButton = findViewById<LoginButton>(R.id.login_button).apply {
                    setPermissions(*FACEBOOK_PERMISSIONS)
                }

                loginButton.registerCallback(fbCallbackManager, object : FacebookCallback<LoginResult> {
                    override fun onSuccess(result: LoginResult) {

                        val accessToken = result.accessToken
                        performLogin(accessToken)
                    }

                    override fun onCancel() {
                        Log.i(TAG, "Facebook sign-in cancelled")
                    }

                    override fun onError(error: FacebookException) {
                        Log.e(TAG, "Error {error.message}")
                    }
                })
            }
        ```

        ```kt performLogin+SimpleCallback lines 
        private interface SimpleCallback<T> {
          fun onResult(result: T)

          fun onError(cause: Throwable)
        }
        ```

        ```kt fetchSessionToken lines 
        private fun fetchSessionToken(token: String, callback: SimpleCallback<String>) {
                val params = Bundle().apply {
                    putString("grant_type", "fb_attenuate_token")
                    putString("fb_exchange_token", token)
                    putString("client_id", getString(R.string.facebook_app_id))
                }

                val request = GraphRequest().apply {
                    parameters = params
                    graphPath = "oauth/access_token"
                }

                request.callback = GraphRequest.Callback { response ->
                    if (response.error != null) {
                        callback.onError(response.error?.exception!!)
                        return@Callback
                    }

                    try {
                        val fbSessionToken = response.jsonObject!!.getString("access_token")
                        callback.onResult(fbSessionToken)
                    } catch (jsonException: JSONException) {
                        //Failed to parse session token
                        callback.onError(jsonException)
                    }
                }
                request.executeAsync()
            }
        ```

        ```kt fetchUserProfile lines 
        private fun fetchUserProfile(token: String, userId: String, callback: SimpleCallback<String>) {

                val params = Bundle().apply {
                    putString("access_token", token)
                    putString("fields", "first_name,last_name,email")
                }

                val request = GraphRequest().apply {
                    parameters = params
                    graphPath = userId
                }

                request.callback = GraphRequest.Callback { response ->
                    val error = response.error
                    if (error != null) {
                        //Failed to fetch user profile
                        callback.onError(error.exception!!)
                        return@Callback
                    }
                    //Handle back the profile as received
                    callback.onResult(response.rawResponse!!)
                }

                request.executeAsync()
            }
        ```

        ```kt exchangeTokens lines 
        private fun exchangeTokens(
                sessionToken: String,
                userProfile: String,
                callback: SimpleCallback<Credentials>
            ) {
                val params = mapOf("user_profile" to userProfile)
                apiClient.loginWithNativeSocialToken(sessionToken, FACEBOOK_SUBJECT_TOKEN_TYPE)
                    .setScope(AUTH0_SCOPE)
                    .addParameters(params)
                    .start(object : Callback<Credentials, AuthenticationException> {
                        override fun onFailure(error: AuthenticationException) {
                            callback.onError(error)
                        }

                        override fun onSuccess(result: Credentials) {
                            callback.onResult(result)
                        }
                    })
            }
        ```

        ```kt performLogin lines 
        private fun performLogin(accessToken: AccessToken) {
                val token = accessToken.token
                fetchSessionToken(token, object : SimpleCallback<String> {
                    override fun onResult(sessionToken: String) {
                        //2. Obtained the Facebook session token
                        fetchUserProfile(token, accessToken.userId, object : SimpleCallback<String> {
                            override fun onResult(userProfile: String) {
                                //3. Obtained the user profile
                                exchangeTokens(
                                    sessionToken,
                                    userProfile,
                                    object : SimpleCallback<Credentials> {
                                        override fun onResult(credentials: Credentials) {
                                            //4. Exchanged the tokens
                                            Log.i(TAG, "Logged in to Auth0")
                                        }

                                        override fun onError(cause: Throwable) {
                                            Log.e(TAG, "Error exchanging tokens", cause)
                                        }
                                    })
                            }

                            override fun onError(cause: Throwable) {
                                Log.e(TAG, "Error fetching the profile", cause)
                            }
                        })
                    }

                    override fun onError(cause: Throwable) {
                        Log.e(TAG, "Error fetching the session token", cause)
                    }
                })
            }
        ```
      </CodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[7].id}>
      <CodeGroup>
        ```kt fetchUserProfile lines 
        private fun fetchUserProfile(token: String, userId: String, callback: SimpleCallback<String>) {

                val params = Bundle().apply {
                    putString("access_token", token)
                    putString("fields", "first_name,last_name,email")
                }

                val request = GraphRequest().apply {
                    parameters = params
                    graphPath = userId
                }

                request.callback = GraphRequest.Callback { response ->
                    val error = response.error
                    if (error != null) {
                        //Failed to fetch user profile
                        callback.onError(error.exception!!)
                        return@Callback
                    }
                    //Handle back the profile as received
                    callback.onResult(response.rawResponse!!)
                }

                request.executeAsync()
            }
        ```

        ```kt performLogin+SimpleCallback lines 
        private interface SimpleCallback<T> {
          fun onResult(result: T)

          fun onError(cause: Throwable)
        }
        ```

        ```kt onCreate lines 
        override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)

                FacebookSdk.setClientToken(getString(R.string.facebook_client_token))
                FacebookSdk.sdkInitialize(this)

                setContentView(R.layout.activity_login)

                val auth0 =
                    Auth0(getString(R.string.com_auth0_client_id), getString(R.string.com_auth0_domain))
                apiClient = AuthenticationAPIClient(auth0)

                fbCallbackManager = CallbackManager.Factory.create()

                val loginButton = findViewById<LoginButton>(R.id.login_button).apply {
                    setPermissions(*FACEBOOK_PERMISSIONS)
                }

                loginButton.registerCallback(fbCallbackManager, object : FacebookCallback<LoginResult> {
                    override fun onSuccess(result: LoginResult) {

                        val accessToken = result.accessToken
                        performLogin(accessToken)
                    }

                    override fun onCancel() {
                        Log.i(TAG, "Facebook sign-in cancelled")
                    }

                    override fun onError(error: FacebookException) {
                        Log.e(TAG, "Error {error.message}")
                    }
                })
            }
        ```

        ```kt fetchSessionToken lines 
        private fun fetchSessionToken(token: String, callback: SimpleCallback<String>) {
                val params = Bundle().apply {
                    putString("grant_type", "fb_attenuate_token")
                    putString("fb_exchange_token", token)
                    putString("client_id", getString(R.string.facebook_app_id))
                }

                val request = GraphRequest().apply {
                    parameters = params
                    graphPath = "oauth/access_token"
                }

                request.callback = GraphRequest.Callback { response ->
                    if (response.error != null) {
                        callback.onError(response.error?.exception!!)
                        return@Callback
                    }

                    try {
                        val fbSessionToken = response.jsonObject!!.getString("access_token")
                        callback.onResult(fbSessionToken)
                    } catch (jsonException: JSONException) {
                        //Failed to parse session token
                        callback.onError(jsonException)
                    }
                }
                request.executeAsync()
            }
        ```

        ```kt exchangeTokens lines 
        private fun exchangeTokens(
                sessionToken: String,
                userProfile: String,
                callback: SimpleCallback<Credentials>
            ) {
                val params = mapOf("user_profile" to userProfile)
                apiClient.loginWithNativeSocialToken(sessionToken, FACEBOOK_SUBJECT_TOKEN_TYPE)
                    .setScope(AUTH0_SCOPE)
                    .addParameters(params)
                    .start(object : Callback<Credentials, AuthenticationException> {
                        override fun onFailure(error: AuthenticationException) {
                            callback.onError(error)
                        }

                        override fun onSuccess(result: Credentials) {
                            callback.onResult(result)
                        }
                    })
            }
        ```

        ```kt performLogin lines 
        private fun performLogin(accessToken: AccessToken) {
                val token = accessToken.token
                fetchSessionToken(token, object : SimpleCallback<String> {
                    override fun onResult(sessionToken: String) {
                        //2. Obtained the Facebook session token
                        fetchUserProfile(token, accessToken.userId, object : SimpleCallback<String> {
                            override fun onResult(userProfile: String) {
                                //3. Obtained the user profile
                                exchangeTokens(
                                    sessionToken,
                                    userProfile,
                                    object : SimpleCallback<Credentials> {
                                        override fun onResult(credentials: Credentials) {
                                            //4. Exchanged the tokens
                                            Log.i(TAG, "Logged in to Auth0")
                                        }

                                        override fun onError(cause: Throwable) {
                                            Log.e(TAG, "Error exchanging tokens", cause)
                                        }
                                    })
                            }

                            override fun onError(cause: Throwable) {
                                Log.e(TAG, "Error fetching the profile", cause)
                            }
                        })
                    }

                    override fun onError(cause: Throwable) {
                        Log.e(TAG, "Error fetching the session token", cause)
                    }
                })
            }
        ```
      </CodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[8].id}>
      <SignUpForm />
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[9].id}>
      <SignUpForm />
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[10].id}>
      <CodeGroup>
        ```kt performLogin lines 
        private fun performLogin(accessToken: AccessToken) {
                val token = accessToken.token
                fetchSessionToken(token, object : SimpleCallback<String> {
                    override fun onResult(sessionToken: String) {
                        //2. Obtained the Facebook session token
                        fetchUserProfile(token, accessToken.userId, object : SimpleCallback<String> {
                            override fun onResult(userProfile: String) {
                                //3. Obtained the user profile
                                exchangeTokens(
                                    sessionToken,
                                    userProfile,
                                    object : SimpleCallback<Credentials> {
                                        override fun onResult(credentials: Credentials) {
                                            //4. Exchanged the tokens
                                            Log.i(TAG, "Logged in to Auth0")
                                        }

                                        override fun onError(cause: Throwable) {
                                            Log.e(TAG, "Error exchanging tokens", cause)
                                        }
                                    })
                            }

                            override fun onError(cause: Throwable) {
                                Log.e(TAG, "Error fetching the profile", cause)
                            }
                        })
                    }

                    override fun onError(cause: Throwable) {
                        Log.e(TAG, "Error fetching the session token", cause)
                    }
                })
            }
        ```

        ```kt performLogin+SimpleCallback lines 
        private interface SimpleCallback<T> {
          fun onResult(result: T)

          fun onError(cause: Throwable)
        }
        ```

        ```kt onCreate lines 
        override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)

                FacebookSdk.setClientToken(getString(R.string.facebook_client_token))
                FacebookSdk.sdkInitialize(this)

                setContentView(R.layout.activity_login)

                val auth0 =
                    Auth0(getString(R.string.com_auth0_client_id), getString(R.string.com_auth0_domain))
                apiClient = AuthenticationAPIClient(auth0)

                fbCallbackManager = CallbackManager.Factory.create()

                val loginButton = findViewById<LoginButton>(R.id.login_button).apply {
                    setPermissions(*FACEBOOK_PERMISSIONS)
                }

                loginButton.registerCallback(fbCallbackManager, object : FacebookCallback<LoginResult> {
                    override fun onSuccess(result: LoginResult) {

                        val accessToken = result.accessToken
                        performLogin(accessToken)
                    }

                    override fun onCancel() {
                        Log.i(TAG, "Facebook sign-in cancelled")
                    }

                    override fun onError(error: FacebookException) {
                        Log.e(TAG, "Error {error.message}")
                    }
                })
            }
        ```

        ```kt fetchSessionToken lines 
        private fun fetchSessionToken(token: String, callback: SimpleCallback<String>) {
                val params = Bundle().apply {
                    putString("grant_type", "fb_attenuate_token")
                    putString("fb_exchange_token", token)
                    putString("client_id", getString(R.string.facebook_app_id))
                }

                val request = GraphRequest().apply {
                    parameters = params
                    graphPath = "oauth/access_token"
                }

                request.callback = GraphRequest.Callback { response ->
                    if (response.error != null) {
                        callback.onError(response.error?.exception!!)
                        return@Callback
                    }

                    try {
                        val fbSessionToken = response.jsonObject!!.getString("access_token")
                        callback.onResult(fbSessionToken)
                    } catch (jsonException: JSONException) {
                        //Failed to parse session token
                        callback.onError(jsonException)
                    }
                }
                request.executeAsync()
            }
        ```

        ```kt fetchUserProfile lines 
        private fun fetchUserProfile(token: String, userId: String, callback: SimpleCallback<String>) {

                val params = Bundle().apply {
                    putString("access_token", token)
                    putString("fields", "first_name,last_name,email")
                }

                val request = GraphRequest().apply {
                    parameters = params
                    graphPath = userId
                }

                request.callback = GraphRequest.Callback { response ->
                    val error = response.error
                    if (error != null) {
                        //Failed to fetch user profile
                        callback.onError(error.exception!!)
                        return@Callback
                    }
                    //Handle back the profile as received
                    callback.onResult(response.rawResponse!!)
                }

                request.executeAsync()
            }
        ```

        ```kt exchangeTokens lines 
        private fun exchangeTokens(
                sessionToken: String,
                userProfile: String,
                callback: SimpleCallback<Credentials>
            ) {
                val params = mapOf("user_profile" to userProfile)
                apiClient.loginWithNativeSocialToken(sessionToken, FACEBOOK_SUBJECT_TOKEN_TYPE)
                    .setScope(AUTH0_SCOPE)
                    .addParameters(params)
                    .start(object : Callback<Credentials, AuthenticationException> {
                        override fun onFailure(error: AuthenticationException) {
                            callback.onError(error)
                        }

                        override fun onSuccess(result: Credentials) {
                            callback.onResult(result)
                        }
                    })
            }
        ```
      </CodeGroup>
    </SideMenuSectionItem>
  </SideMenu>
</Recipe>
