> ## 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 guide demonstrates how to integrate Auth0 with any new or existing Java Servlet application.

# Add Login to Your Java Servlet Application

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: "configure-auth0",
  title: "Configure Auth0"
}, {
  id: "integrate-auth0-in-your-application",
  title: "Integrate Auth0 in your application"
}, {
  id: "configure-your-java-application",
  title: "Configure your Java application"
}, {
  id: "create-the-authenticationcontroller",
  title: "Create the AuthenticationController"
}, {
  id: "login-redirection",
  title: "Login Redirection"
}, {
  id: "handling-the-tokens",
  title: "Handling the tokens"
}, {
  id: "display-the-home-page",
  title: "Display the home page"
}, {
  id: "handle-logout",
  title: "Handle logout"
}, {
  id: "run-the-sample",
  title: "Run the sample"
}];

<Recipe>
  <Content>
    Auth0 allows you to quickly add authentication and gain access to user profile information in your application.
    This guide demonstrates how to integrate Auth0 with any new or existing Java Servlet application.

    <Section id={sections[0].id} title={sections[0].title} stepNumber="1">
      To use Auth0 services, you’ll need to have an application set up in the Auth0 Dashboard. The Auth0 application is
      where you will configure how you want authentication to work for the project you are developing.

      ### Configure an application

      Use the interactive selector to create a new Auth0 application or select an existing application that represents
      the project you want to integrate with. Every application in Auth0 is assigned an alphanumeric, unique client ID
      that your application code will use to call Auth0 APIs through the SDK.

      Any settings you configure using this quickstart will automatically update for your Application in the [Dashboard](https://manage.auth0.com/#/), which is where you
      can manage your Applications in the future.

      If you would rather explore a complete configuration, you can view a sample application instead.

      ### Configure Callback URLs

      A callback URL is a URL in your application that you would like Auth0 to redirect users to after they have
      authenticated. If not set, users will not be returned to your application after they log in.

      <Info>
        If you are following along with our sample project, set this to
        `http://localhost:3000/callback`.
      </Info>

      ### Configure Logout URLs

      A logout URL is a URL in your application that you would like Auth0 to redirect users to after they have logged
      out. If not set, users will not be able to log out from your application and will receive an error.

      <Info>
        If you are following along with our sample project, set this to `http://localhost:3000/`.
      </Info>
    </Section>

    <Section id={sections[1].id} title={sections[1].title} stepNumber="2">
      ### Setup dependencies

      To integrate your Java application with Auth0, add the following dependencies:

      * **javax.servlet-api**
        : is the library that allows you to create Java Servlets. You then need to add a Server dependency like
        Tomcat or Gretty, which one is up to you. Check our sample code for more information.
      * **auth0-java-mvc-commons**: is the [Java library](https://github.com/auth0/auth0-java-mvc-common) that allows you to use Auth0 with Java for
        server-side MVC web apps. It generates the Authorize URL that you need to call in order to authenticate and
        validates the result received on the way back to finally obtain the [Auth0 Tokens](https://auth0.com/docs/tokens) that identify the user.

      If you are using Gradle, add them to your `build.gradle`:

      ```text lines
      // build.gradle
      compile 'javax.servlet:javax.servlet-api:3.1.0'
      compile 'com.auth0:mvc-auth-commons:1.+'W
      ```

      If you are using Maven, add them to your `pom.xml`:

      ```text lines
      <!-- pom.xml -->
      <dependency>
      <groupId>com.auth0</groupId>
      <artifactId>mvc-auth-commons</artifactId>
      <version>[1.0, 2.0)</version>
      </dependency>
      <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      </dependency>
      ```
    </Section>

    <Section id={sections[2].id} title={sections[2].title} stepNumber="3">
      Your Java App needs some information in order to authenticate against your Auth0 account. The samples read this
      information from the deployment descriptor file `src/main/webapp/WEB-INF/web.xml`, but you could store
      them anywhere else.

      This information will be used to configure the **auth0-java-mvc-commons** library to enable users to login to
      your application. To learn more about the library, including its various configuration options, see the [library's documentation](https://github.com/auth0/auth0-java-mvc-common/blob/master/README.md).

      ### Check populated attributes

      If you downloaded this sample using the **Download Sample** button, the `domain`,
      `clientId` and `clientSecret` attributes will be populated for you. You should verify that
      the values are correct, especially if you have multiple Auth0 applications in your account.

      ### Project structure

      The example project, which can be downloaded using the **Download Sample** button, has the following
      structure:

      ```text lines
      - src
      -- main
      ---- java
      ------ com
      -------- auth0
      ---------- example
      ------------ Auth0Filter.java
      ------------ AuthenticationControllerProvider.java
      ------------ HomeServlet.java
      ------------ CallbackServlet.java
      ------------ LoginServlet.java
      ------------ LogoutServlet.java
      ---- webapp
      ------ WEB-INF
      -------- jsp
      ---------- home.jsp
      -------- web.xml

      build.gradle
      ```

      The project contains a single JSP: the `home.jsp` which will display the tokens associated with the
      user after a successful login and provide the option to logout.

      The project contains a WebFilter: the `Auth0Filter.java` which will check for existing tokens before
      giving the user access to our protected `/portal/*` path. If the tokens don't exist, the request will
      be redirected to the `LoginServlet`.

      The project contains also four servlets:

      * `LoginServlet.java`: Invoked when the user attempts to log in. The servlet uses the
        `client_id` and `domain` parameters to create a valid Authorize URL and redirects the
        user there.
      * `CallbackServlet.java`: The servlet captures requests to our Callback URL and processes the data
        to obtain the credentials. After a successful login, the credentials are then saved to the request's
        HttpSession.
      * `HomeServlet.java`: The servlet reads the previously saved tokens and shows them on the
        `home.jsp` resource.
      * `LogoutServlet.java`: Invoked when the user clicks the logout link. The servlet invalidates the
        user session and redirects the user to the login page, handled by the `LoginServlet`.
      * `AuthenticationControllerProvider.java`: Responsible to create and manage a single instance of the
        `AuthenticationController`
    </Section>

    <Section id={sections[3].id} title={sections[3].title} stepNumber="4">
      To enable users to authenticate, create an instance of the `AuthenticationController` provided by the
      `auth0-java-mvc-commons` SDK using the `domain`, `clientId`, and
      `clientSecret`. The sample shows how to configure the component for use with tokens signed using the
      RS256 asymmetric signing algorithm, by specifying a `JwkProvider` to fetch the public key used to
      verify the token's signature. See the [jwks-rsa-java repository](https://github.com/auth0/jwks-rsa-java) to learn about additional configuration options. If you
      are using HS256, there is no need to configure the `JwkProvider`.

      <Info>
        The `AuthenticationController` does not store any context, and is inteded to be reused.
        Unneccessary creation may result in additonal resources being created which could impact performance.
      </Info>
    </Section>

    <Section id={sections[4].id} title={sections[4].title} stepNumber="5">
      To enable users to log in, your application will redirect them to the Universal Login page. Using the
      `AuthenticationController` instance, you can generate the redirect URL by calling the
      `buildAuthorizeUrl(HttpServletRequest request`, `HttpServletResponse response`,
      `String redirectUrl)` method. The redirect URL must be the URL that was added to the **Allowed
      Callback URLs** of your Auth0 application.
    </Section>

    <Section id={sections[5].id} title={sections[5].title} stepNumber="6">
      After the user logs in, the result will be received in our `CallbackServlet` via either a GET or POST
      HTTP request. Because we are using the Authorization Code Flow (the default), a GET request will be sent. If you
      have configured the library for the Implicit Flow, a POST request will be sent instead.

      The request holds the call context that the library previously set by generating the Authorize URL with the
      `AuthenticationController`. When passed to the controller, you get back either a valid
      `Tokens` instance or an Exception indicating what went wrong. In the case of a successful call, you
      need to save the credentials somewhere to access them later. You can use the `HttpSession` of the
      request by using the `SessionsUtils` class included in the library.

      <Info>
        It is recommended to store the time in which we requested the tokens and the received
        `expiresIn` value, so that the next time when we are going to use the token we can check if
        it has already expired or if it's still valid. For the sake of this sample, we will skip that
        validation.
      </Info>
    </Section>

    <Section id={sections[6].id} title={sections[6].title} stepNumber="7">
      Now that the user is authenticated (the tokens exists), the `Auth0Filter` will allow them to access
      our protected resources. In the `HomeServlet` we obtain the tokens from the request's session and set
      them as the `userId` attribute so they can be used from the JSP code.
    </Section>

    <Section id={sections[7].id} title={sections[7].title} stepNumber="8">
      To properly handle logout, we need to clear the session and log the user out of Auth0. This is handled in the
      `LogoutServlet` of our sample application.

      First, we clear the session by calling `request.getSession().invalidate()`. We then construct the
      logout URL, being sure to include the `returnTo` query parameter, which is where the user will be
      redirected to after logging out. Finally, we redirect the response to our logout URL.
    </Section>

    <Section id={sections[8].id} title={sections[8].title} stepNumber="9">
      To run the sample from a terminal, change the directory to the root folder of the project and execute the
      following line:

      ```text lines
      ./gradlew clean app
      ```

      After a few seconds, the application will be accessible on `http://localhost:3000/`. Try to access the
      protected resource [http://localhost:3000/portal/home](http://localhost:3000/portal/home) and note how you're redirected by the
      `Auth0Filter` to the Auth0 Login Page. The widget displays all the social and database connections that
      you have defined for this application in the [dashboard](https://manage.auth0.com/#/).

      <Frame>
        <img src="https://mintcdn.com/docs-staging-quickstart-revamp/KCEsvkqT5-VRQ297/images/cdy7uua7fh8z/7L6lZ6xCi1L7sJBFZUPb9g/b7697bfa1bc83a1072c2de2f15cec93c/Login_Screen_-_English.png?fit=max&auto=format&n=KCEsvkqT5-VRQ297&q=85&s=d84eed0b7fbec9e4aeb5cf082e3e4988" width="434" height="739" data-path="images/cdy7uua7fh8z/7L6lZ6xCi1L7sJBFZUPb9g/b7697bfa1bc83a1072c2de2f15cec93c/Login_Screen_-_English.png" />
      </Frame>

      After a successful authentication, you'll be able to see the home page contents.

      <Frame>
        <img src="https://mintcdn.com/docs-staging-quickstart-revamp/cn1eMmAiJHX3hF4T/images/cdy7uua7fh8z/FzK3jxfSGoeIDYQamxnJl/6b608e39ff39e044644193cfd2ee0f69/java-step-9-2.png?fit=max&auto=format&n=cn1eMmAiJHX3hF4T&q=85&s=6c13e66f1bf443370c3c30ab2aeab686" width="1058" height="633" data-path="images/cdy7uua7fh8z/FzK3jxfSGoeIDYQamxnJl/6b608e39ff39e044644193cfd2ee0f69/java-step-9-2.png" />
      </Frame>

      Log out by clicking the **logout** button at the top right of the home page.
    </Section>

    ## Next Steps

    Excellent work! If you made it this far, you should now have login, logout, and user profile information running in your application.

    This concludes our quickstart tutorial, but there is so much more to explore. To learn more about what you can do with Auth0, check out:

    * [Auth0 Dashboard](https://manage.auth0.com/dashboard/us/dev-gja8kxz4ndtex3rq) - Learn how to configure and manage your Auth0 tenant and applications
    * [auth0-java-mvc-common SDK](https://github.com/auth0/auth0-java-mvc-common) - Explore the SDK used in this tutorial more fully
    * [Auth0 Marketplace](https://marketplace.auth0.com/) - Discover integrations you can enable to extend Auth0’s functionality
  </Content>

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

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

    <SideMenuSectionItem id={sections[2].id}>
      <CodeGroup>
        ```xml web.xml lines
        <context-param>
            <param-name>com.auth0.domain</param-name>
            <param-value>dev-gja8kxz4ndtex3rq.us.auth0.com</param-value>
        </context-param>

        <context-param>
            <param-name>com.auth0.clientId</param-name>
            <param-value>mz9iNEIo2PHu7oeh8QRt19ndTyyCIgai</param-value>
        </context-param>

        <context-param>
            <param-name>com.auth0.clientSecret</param-name>
            <param-value>yLTW7npKO4g1HHsCENiZbOaHHXLmhVefJxdNnXcyhOBOomZ2tgjJjSC2pMK7Swvr</param-value>
        </context-param>
        ```

        ```java AuthenticationControllerProvider.java highlight={5-26} lines 
        class AuthenticationControllerProvider {

            private AuthenticationControllerProvider() {}

            private static AuthenticationController INSTANCE;

            // if multiple threads may call this, synchronize this method and consider double locking
            static AuthenticationController getInstance(ServletConfig config) throws UnsupportedEncodingException {
                if (INSTANCE == null) {
                    String domain = config.getServletContext().getInitParameter("com.auth0.domain");
                    String clientId = config.getServletContext().getInitParameter("com.auth0.clientId");
                    String clientSecret = config.getServletContext().getInitParameter("com.auth0.clientSecret");

                    if (domain == null || clientId == null || clientSecret == null) {
                        throw new IllegalArgumentException("Missing domain, clientId, or clientSecret. Did you update src/main/webapp/WEB-INF/web.xml?");
                    }

                    // JwkProvider required for RS256 tokens. If using HS256, do not use.
                    JwkProvider jwkProvider = new JwkProviderBuilder(domain).build();
                    INSTANCE = AuthenticationController.newBuilder(domain, clientId, clientSecret)
                            .withJwkProvider(jwkProvider)
                            .build();
                }

                return INSTANCE;
            }
        }
        ```

        ```java LoginServlet.java highlight={21-23} lines
        @WebServlet(urlPatterns = {"/login"})
        public class LoginServlet extends HttpServlet {
            private AuthenticationController authenticationController;
            private String domain;

            @Override
            public void init(ServletConfig config) throws ServletException {
                super.init(config);
                domain = config.getServletContext().getInitParameter("com.auth0.domain");
                authenticationController = AuthenticationControllerProvider.getInstance(config);
            }

            @Override
            protected void doGet(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException {
                String redirectUri = req.getScheme() + "://" + req.getServerName();
                if ((req.getScheme().equals("http") && req.getServerPort() != 80) || (req.getScheme().equals("https") && req.getServerPort() != 443)) {
                    redirectUri += ":" + req.getServerPort();
                }
                redirectUri += "/callback";

                String authorizeUrl = authenticationController.buildAuthorizeUrl(req, res, redirectUri)
                        .build();
                res.sendRedirect(authorizeUrl);
            }
        }
        ```

        ```java CallbackServlet.java highlight={16-37} lines 
        @WebServlet(urlPatterns = {"/callback"})
        public class CallbackServlet extends HttpServlet {

            private String redirectOnSuccess;
            private String redirectOnFail;
            private AuthenticationController authenticationController;

            @Override
            public void init(ServletConfig config) throws ServletException {
                super.init(config);
                redirectOnSuccess = "/portal/home";
                redirectOnFail = "/login";
                authenticationController = AuthenticationControllerProvider.getInstance(config);
            }

            @Override
            public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
                handle(req, res);
            }

            @Override
            public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
                handle(req, res);
            }

            private void handle(HttpServletRequest req, HttpServletResponse res) throws IOException {
                try {
                    // Parse the request
                    Tokens tokens = authenticationController.handle(req, res);
                    SessionUtils.set(req, "accessToken", tokens.getAccessToken());
                    SessionUtils.set(req, "idToken", tokens.getIdToken());
                    res.sendRedirect(redirectOnSuccess);
                } catch (IdentityVerificationException e) {
                    e.printStackTrace();
                    res.sendRedirect(redirectOnFail);
                }
            }
        }
        ```

        ```java HomeServlet.java highlight={4-14} lines
        @WebServlet(urlPatterns = {"/portal/home"})
        public class HomeServlet extends HttpServlet {

            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
                final String accessToken = (String) SessionUtils.get(req, "accessToken");
                final String idToken = (String) SessionUtils.get(req, "idToken");
                if (accessToken != null) {
                    req.setAttribute("userId", accessToken);
                } else if (idToken != null) {
                    req.setAttribute("userId", idToken);
                }
                req.getRequestDispatcher("/WEB-INF/jsp/home.jsp").forward(req, res);
            }
        }
        ```

        ```java LogoutServlet.java highlight={13-30} lines 
        @WebServlet(urlPatterns = {"/logout"})
        public class LogoutServlet extends HttpServlet {

            private String domain;
            private String clientId;

            @Override
            public void init(ServletConfig config) {
                domain = config.getServletContext().getInitParameter("com.auth0.domain");
                clientId = config.getServletContext().getInitParameter("com.auth0.clientId");
            }

            @Override
            protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
                if (request.getSession() != null) {
                    request.getSession().invalidate();
                }
                String returnUrl = String.format("%s://%s", request.getScheme(), request.getServerName());
                if ((request.getScheme().equals("http") && request.getServerPort() != 80) || (request.getScheme().equals("https") && request.getServerPort() != 443)) {
                    returnUrl += ":" + request.getServerPort();
                }
                returnUrl += "/login";
                String logoutUrl = String.format(
                        "https://%s/v2/logout?client_id=%s&returnTo=%s",
                        domain,
                        clientId,
                        returnUrl
                );
                response.sendRedirect(logoutUrl);
            }

        }
        ```
      </CodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[3].id}>
      <CodeGroup>
        ```java AuthenticationControllerProvider.java highlight={5-26} lines 
        class AuthenticationControllerProvider {

            private AuthenticationControllerProvider() {}

            private static AuthenticationController INSTANCE;

            // if multiple threads may call this, synchronize this method and consider double locking
            static AuthenticationController getInstance(ServletConfig config) throws UnsupportedEncodingException {
                if (INSTANCE == null) {
                    String domain = config.getServletContext().getInitParameter("com.auth0.domain");
                    String clientId = config.getServletContext().getInitParameter("com.auth0.clientId");
                    String clientSecret = config.getServletContext().getInitParameter("com.auth0.clientSecret");

                    if (domain == null || clientId == null || clientSecret == null) {
                        throw new IllegalArgumentException("Missing domain, clientId, or clientSecret. Did you update src/main/webapp/WEB-INF/web.xml?");
                    }

                    // JwkProvider required for RS256 tokens. If using HS256, do not use.
                    JwkProvider jwkProvider = new JwkProviderBuilder(domain).build();
                    INSTANCE = AuthenticationController.newBuilder(domain, clientId, clientSecret)
                            .withJwkProvider(jwkProvider)
                            .build();
                }

                return INSTANCE;
            }
        }
        ```

        ```xml web.xml lines
        <context-param>
            <param-name>com.auth0.domain</param-name>
            <param-value>dev-gja8kxz4ndtex3rq.us.auth0.com</param-value>
        </context-param>

        <context-param>
            <param-name>com.auth0.clientId</param-name>
            <param-value>mz9iNEIo2PHu7oeh8QRt19ndTyyCIgai</param-value>
        </context-param>

        <context-param>
            <param-name>com.auth0.clientSecret</param-name>
            <param-value>yLTW7npKO4g1HHsCENiZbOaHHXLmhVefJxdNnXcyhOBOomZ2tgjJjSC2pMK7Swvr</param-value>
        </context-param>
        ```

        ```java LoginServlet.java highlight={21-23} lines
        @WebServlet(urlPatterns = {"/login"})
        public class LoginServlet extends HttpServlet {
            private AuthenticationController authenticationController;
            private String domain;

            @Override
            public void init(ServletConfig config) throws ServletException {
                super.init(config);
                domain = config.getServletContext().getInitParameter("com.auth0.domain");
                authenticationController = AuthenticationControllerProvider.getInstance(config);
            }

            @Override
            protected void doGet(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException {
                String redirectUri = req.getScheme() + "://" + req.getServerName();
                if ((req.getScheme().equals("http") && req.getServerPort() != 80) || (req.getScheme().equals("https") && req.getServerPort() != 443)) {
                    redirectUri += ":" + req.getServerPort();
                }
                redirectUri += "/callback";

                String authorizeUrl = authenticationController.buildAuthorizeUrl(req, res, redirectUri)
                        .build();
                res.sendRedirect(authorizeUrl);
            }
        }
        ```

        ```java CallbackServlet.java highlight={16-37} lines 
        @WebServlet(urlPatterns = {"/callback"})
        public class CallbackServlet extends HttpServlet {

            private String redirectOnSuccess;
            private String redirectOnFail;
            private AuthenticationController authenticationController;

            @Override
            public void init(ServletConfig config) throws ServletException {
                super.init(config);
                redirectOnSuccess = "/portal/home";
                redirectOnFail = "/login";
                authenticationController = AuthenticationControllerProvider.getInstance(config);
            }

            @Override
            public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
                handle(req, res);
            }

            @Override
            public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
                handle(req, res);
            }

            private void handle(HttpServletRequest req, HttpServletResponse res) throws IOException {
                try {
                    // Parse the request
                    Tokens tokens = authenticationController.handle(req, res);
                    SessionUtils.set(req, "accessToken", tokens.getAccessToken());
                    SessionUtils.set(req, "idToken", tokens.getIdToken());
                    res.sendRedirect(redirectOnSuccess);
                } catch (IdentityVerificationException e) {
                    e.printStackTrace();
                    res.sendRedirect(redirectOnFail);
                }
            }
        }
        ```

        ```java HomeServlet.java highlight={4-14} lines
        @WebServlet(urlPatterns = {"/portal/home"})
        public class HomeServlet extends HttpServlet {

            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
                final String accessToken = (String) SessionUtils.get(req, "accessToken");
                final String idToken = (String) SessionUtils.get(req, "idToken");
                if (accessToken != null) {
                    req.setAttribute("userId", accessToken);
                } else if (idToken != null) {
                    req.setAttribute("userId", idToken);
                }
                req.getRequestDispatcher("/WEB-INF/jsp/home.jsp").forward(req, res);
            }
        }
        ```

        ```java LogoutServlet.java highlight={13-30} lines 
        @WebServlet(urlPatterns = {"/logout"})
        public class LogoutServlet extends HttpServlet {

            private String domain;
            private String clientId;

            @Override
            public void init(ServletConfig config) {
                domain = config.getServletContext().getInitParameter("com.auth0.domain");
                clientId = config.getServletContext().getInitParameter("com.auth0.clientId");
            }

            @Override
            protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
                if (request.getSession() != null) {
                    request.getSession().invalidate();
                }
                String returnUrl = String.format("%s://%s", request.getScheme(), request.getServerName());
                if ((request.getScheme().equals("http") && request.getServerPort() != 80) || (request.getScheme().equals("https") && request.getServerPort() != 443)) {
                    returnUrl += ":" + request.getServerPort();
                }
                returnUrl += "/login";
                String logoutUrl = String.format(
                        "https://%s/v2/logout?client_id=%s&returnTo=%s",
                        domain,
                        clientId,
                        returnUrl
                );
                response.sendRedirect(logoutUrl);
            }

        }
        ```
      </CodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[4].id}>
      <CodeGroup>
        ```java LoginServlet.java highlight={21-23} lines
        @WebServlet(urlPatterns = {"/login"})
        public class LoginServlet extends HttpServlet {
            private AuthenticationController authenticationController;
            private String domain;

            @Override
            public void init(ServletConfig config) throws ServletException {
                super.init(config);
                domain = config.getServletContext().getInitParameter("com.auth0.domain");
                authenticationController = AuthenticationControllerProvider.getInstance(config);
            }

            @Override
            protected void doGet(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException {
                String redirectUri = req.getScheme() + "://" + req.getServerName();
                if ((req.getScheme().equals("http") && req.getServerPort() != 80) || (req.getScheme().equals("https") && req.getServerPort() != 443)) {
                    redirectUri += ":" + req.getServerPort();
                }
                redirectUri += "/callback";

                String authorizeUrl = authenticationController.buildAuthorizeUrl(req, res, redirectUri)
                        .build();
                res.sendRedirect(authorizeUrl);
            }
        }
        ```

        ```xml web.xml lines
        <context-param>
            <param-name>com.auth0.domain</param-name>
            <param-value>dev-gja8kxz4ndtex3rq.us.auth0.com</param-value>
        </context-param>

        <context-param>
            <param-name>com.auth0.clientId</param-name>
            <param-value>mz9iNEIo2PHu7oeh8QRt19ndTyyCIgai</param-value>
        </context-param>

        <context-param>
            <param-name>com.auth0.clientSecret</param-name>
            <param-value>yLTW7npKO4g1HHsCENiZbOaHHXLmhVefJxdNnXcyhOBOomZ2tgjJjSC2pMK7Swvr</param-value>
        </context-param>
        ```

        ```java AuthenticationControllerProvider.java highlight={5-26} lines 
        class AuthenticationControllerProvider {

            private AuthenticationControllerProvider() {}

            private static AuthenticationController INSTANCE;

            // if multiple threads may call this, synchronize this method and consider double locking
            static AuthenticationController getInstance(ServletConfig config) throws UnsupportedEncodingException {
                if (INSTANCE == null) {
                    String domain = config.getServletContext().getInitParameter("com.auth0.domain");
                    String clientId = config.getServletContext().getInitParameter("com.auth0.clientId");
                    String clientSecret = config.getServletContext().getInitParameter("com.auth0.clientSecret");

                    if (domain == null || clientId == null || clientSecret == null) {
                        throw new IllegalArgumentException("Missing domain, clientId, or clientSecret. Did you update src/main/webapp/WEB-INF/web.xml?");
                    }

                    // JwkProvider required for RS256 tokens. If using HS256, do not use.
                    JwkProvider jwkProvider = new JwkProviderBuilder(domain).build();
                    INSTANCE = AuthenticationController.newBuilder(domain, clientId, clientSecret)
                            .withJwkProvider(jwkProvider)
                            .build();
                }

                return INSTANCE;
            }
        }
        ```

        ```java CallbackServlet.java highlight={16-37} lines 
        @WebServlet(urlPatterns = {"/callback"})
        public class CallbackServlet extends HttpServlet {

            private String redirectOnSuccess;
            private String redirectOnFail;
            private AuthenticationController authenticationController;

            @Override
            public void init(ServletConfig config) throws ServletException {
                super.init(config);
                redirectOnSuccess = "/portal/home";
                redirectOnFail = "/login";
                authenticationController = AuthenticationControllerProvider.getInstance(config);
            }

            @Override
            public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
                handle(req, res);
            }

            @Override
            public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
                handle(req, res);
            }

            private void handle(HttpServletRequest req, HttpServletResponse res) throws IOException {
                try {
                    // Parse the request
                    Tokens tokens = authenticationController.handle(req, res);
                    SessionUtils.set(req, "accessToken", tokens.getAccessToken());
                    SessionUtils.set(req, "idToken", tokens.getIdToken());
                    res.sendRedirect(redirectOnSuccess);
                } catch (IdentityVerificationException e) {
                    e.printStackTrace();
                    res.sendRedirect(redirectOnFail);
                }
            }
        }
        ```

        ```java HomeServlet.java highlight={4-14} lines
        @WebServlet(urlPatterns = {"/portal/home"})
        public class HomeServlet extends HttpServlet {

            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
                final String accessToken = (String) SessionUtils.get(req, "accessToken");
                final String idToken = (String) SessionUtils.get(req, "idToken");
                if (accessToken != null) {
                    req.setAttribute("userId", accessToken);
                } else if (idToken != null) {
                    req.setAttribute("userId", idToken);
                }
                req.getRequestDispatcher("/WEB-INF/jsp/home.jsp").forward(req, res);
            }
        }
        ```

        ```java LogoutServlet.java highlight={13-30} lines 
        @WebServlet(urlPatterns = {"/logout"})
        public class LogoutServlet extends HttpServlet {

            private String domain;
            private String clientId;

            @Override
            public void init(ServletConfig config) {
                domain = config.getServletContext().getInitParameter("com.auth0.domain");
                clientId = config.getServletContext().getInitParameter("com.auth0.clientId");
            }

            @Override
            protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
                if (request.getSession() != null) {
                    request.getSession().invalidate();
                }
                String returnUrl = String.format("%s://%s", request.getScheme(), request.getServerName());
                if ((request.getScheme().equals("http") && request.getServerPort() != 80) || (request.getScheme().equals("https") && request.getServerPort() != 443)) {
                    returnUrl += ":" + request.getServerPort();
                }
                returnUrl += "/login";
                String logoutUrl = String.format(
                        "https://%s/v2/logout?client_id=%s&returnTo=%s",
                        domain,
                        clientId,
                        returnUrl
                );
                response.sendRedirect(logoutUrl);
            }

        }
        ```
      </CodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[5].id}>
      <CodeGroup>
        ```java CallbackServlet.java highlight={16-37} lines 
        @WebServlet(urlPatterns = {"/callback"})
        public class CallbackServlet extends HttpServlet {

            private String redirectOnSuccess;
            private String redirectOnFail;
            private AuthenticationController authenticationController;

            @Override
            public void init(ServletConfig config) throws ServletException {
                super.init(config);
                redirectOnSuccess = "/portal/home";
                redirectOnFail = "/login";
                authenticationController = AuthenticationControllerProvider.getInstance(config);
            }

            @Override
            public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
                handle(req, res);
            }

            @Override
            public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
                handle(req, res);
            }

            private void handle(HttpServletRequest req, HttpServletResponse res) throws IOException {
                try {
                    // Parse the request
                    Tokens tokens = authenticationController.handle(req, res);
                    SessionUtils.set(req, "accessToken", tokens.getAccessToken());
                    SessionUtils.set(req, "idToken", tokens.getIdToken());
                    res.sendRedirect(redirectOnSuccess);
                } catch (IdentityVerificationException e) {
                    e.printStackTrace();
                    res.sendRedirect(redirectOnFail);
                }
            }
        }
        ```

        ```xml web.xml lines
        <context-param>
            <param-name>com.auth0.domain</param-name>
            <param-value>dev-gja8kxz4ndtex3rq.us.auth0.com</param-value>
        </context-param>

        <context-param>
            <param-name>com.auth0.clientId</param-name>
            <param-value>mz9iNEIo2PHu7oeh8QRt19ndTyyCIgai</param-value>
        </context-param>

        <context-param>
            <param-name>com.auth0.clientSecret</param-name>
            <param-value>yLTW7npKO4g1HHsCENiZbOaHHXLmhVefJxdNnXcyhOBOomZ2tgjJjSC2pMK7Swvr</param-value>
        </context-param>
        ```

        ```java AuthenticationControllerProvider.java highlight={5-26} lines 
        class AuthenticationControllerProvider {

            private AuthenticationControllerProvider() {}

            private static AuthenticationController INSTANCE;

            // if multiple threads may call this, synchronize this method and consider double locking
            static AuthenticationController getInstance(ServletConfig config) throws UnsupportedEncodingException {
                if (INSTANCE == null) {
                    String domain = config.getServletContext().getInitParameter("com.auth0.domain");
                    String clientId = config.getServletContext().getInitParameter("com.auth0.clientId");
                    String clientSecret = config.getServletContext().getInitParameter("com.auth0.clientSecret");

                    if (domain == null || clientId == null || clientSecret == null) {
                        throw new IllegalArgumentException("Missing domain, clientId, or clientSecret. Did you update src/main/webapp/WEB-INF/web.xml?");
                    }

                    // JwkProvider required for RS256 tokens. If using HS256, do not use.
                    JwkProvider jwkProvider = new JwkProviderBuilder(domain).build();
                    INSTANCE = AuthenticationController.newBuilder(domain, clientId, clientSecret)
                            .withJwkProvider(jwkProvider)
                            .build();
                }

                return INSTANCE;
            }
        }
        ```

        ```java LoginServlet.java highlight={21-23} lines
        @WebServlet(urlPatterns = {"/login"})
        public class LoginServlet extends HttpServlet {
            private AuthenticationController authenticationController;
            private String domain;

            @Override
            public void init(ServletConfig config) throws ServletException {
                super.init(config);
                domain = config.getServletContext().getInitParameter("com.auth0.domain");
                authenticationController = AuthenticationControllerProvider.getInstance(config);
            }

            @Override
            protected void doGet(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException {
                String redirectUri = req.getScheme() + "://" + req.getServerName();
                if ((req.getScheme().equals("http") && req.getServerPort() != 80) || (req.getScheme().equals("https") && req.getServerPort() != 443)) {
                    redirectUri += ":" + req.getServerPort();
                }
                redirectUri += "/callback";

                String authorizeUrl = authenticationController.buildAuthorizeUrl(req, res, redirectUri)
                        .build();
                res.sendRedirect(authorizeUrl);
            }
        }
        ```

        ```java HomeServlet.java highlight={4-14} lines
        @WebServlet(urlPatterns = {"/portal/home"})
        public class HomeServlet extends HttpServlet {

            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
                final String accessToken = (String) SessionUtils.get(req, "accessToken");
                final String idToken = (String) SessionUtils.get(req, "idToken");
                if (accessToken != null) {
                    req.setAttribute("userId", accessToken);
                } else if (idToken != null) {
                    req.setAttribute("userId", idToken);
                }
                req.getRequestDispatcher("/WEB-INF/jsp/home.jsp").forward(req, res);
            }
        }
        ```

        ```java LogoutServlet.java highlight={13-30} lines 
        @WebServlet(urlPatterns = {"/logout"})
        public class LogoutServlet extends HttpServlet {

            private String domain;
            private String clientId;

            @Override
            public void init(ServletConfig config) {
                domain = config.getServletContext().getInitParameter("com.auth0.domain");
                clientId = config.getServletContext().getInitParameter("com.auth0.clientId");
            }

            @Override
            protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
                if (request.getSession() != null) {
                    request.getSession().invalidate();
                }
                String returnUrl = String.format("%s://%s", request.getScheme(), request.getServerName());
                if ((request.getScheme().equals("http") && request.getServerPort() != 80) || (request.getScheme().equals("https") && request.getServerPort() != 443)) {
                    returnUrl += ":" + request.getServerPort();
                }
                returnUrl += "/login";
                String logoutUrl = String.format(
                        "https://%s/v2/logout?client_id=%s&returnTo=%s",
                        domain,
                        clientId,
                        returnUrl
                );
                response.sendRedirect(logoutUrl);
            }

        }
        ```
      </CodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[6].id}>
      <CodeGroup>
        ```java HomeServlet.java highlight={4-14} lines
        @WebServlet(urlPatterns = {"/portal/home"})
        public class HomeServlet extends HttpServlet {

            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
                final String accessToken = (String) SessionUtils.get(req, "accessToken");
                final String idToken = (String) SessionUtils.get(req, "idToken");
                if (accessToken != null) {
                    req.setAttribute("userId", accessToken);
                } else if (idToken != null) {
                    req.setAttribute("userId", idToken);
                }
                req.getRequestDispatcher("/WEB-INF/jsp/home.jsp").forward(req, res);
            }
        }
        ```

        ```xml web.xml lines
        <context-param>
            <param-name>com.auth0.domain</param-name>
            <param-value>dev-gja8kxz4ndtex3rq.us.auth0.com</param-value>
        </context-param>

        <context-param>
            <param-name>com.auth0.clientId</param-name>
            <param-value>mz9iNEIo2PHu7oeh8QRt19ndTyyCIgai</param-value>
        </context-param>

        <context-param>
            <param-name>com.auth0.clientSecret</param-name>
            <param-value>yLTW7npKO4g1HHsCENiZbOaHHXLmhVefJxdNnXcyhOBOomZ2tgjJjSC2pMK7Swvr</param-value>
        </context-param>
        ```

        ```java AuthenticationControllerProvider.java highlight={5-26} lines 
        class AuthenticationControllerProvider {

            private AuthenticationControllerProvider() {}

            private static AuthenticationController INSTANCE;

            // if multiple threads may call this, synchronize this method and consider double locking
            static AuthenticationController getInstance(ServletConfig config) throws UnsupportedEncodingException {
                if (INSTANCE == null) {
                    String domain = config.getServletContext().getInitParameter("com.auth0.domain");
                    String clientId = config.getServletContext().getInitParameter("com.auth0.clientId");
                    String clientSecret = config.getServletContext().getInitParameter("com.auth0.clientSecret");

                    if (domain == null || clientId == null || clientSecret == null) {
                        throw new IllegalArgumentException("Missing domain, clientId, or clientSecret. Did you update src/main/webapp/WEB-INF/web.xml?");
                    }

                    // JwkProvider required for RS256 tokens. If using HS256, do not use.
                    JwkProvider jwkProvider = new JwkProviderBuilder(domain).build();
                    INSTANCE = AuthenticationController.newBuilder(domain, clientId, clientSecret)
                            .withJwkProvider(jwkProvider)
                            .build();
                }

                return INSTANCE;
            }
        }
        ```

        ```java LoginServlet.java highlight={21-23} lines
        @WebServlet(urlPatterns = {"/login"})
        public class LoginServlet extends HttpServlet {
            private AuthenticationController authenticationController;
            private String domain;

            @Override
            public void init(ServletConfig config) throws ServletException {
                super.init(config);
                domain = config.getServletContext().getInitParameter("com.auth0.domain");
                authenticationController = AuthenticationControllerProvider.getInstance(config);
            }

            @Override
            protected void doGet(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException {
                String redirectUri = req.getScheme() + "://" + req.getServerName();
                if ((req.getScheme().equals("http") && req.getServerPort() != 80) || (req.getScheme().equals("https") && req.getServerPort() != 443)) {
                    redirectUri += ":" + req.getServerPort();
                }
                redirectUri += "/callback";

                String authorizeUrl = authenticationController.buildAuthorizeUrl(req, res, redirectUri)
                        .build();
                res.sendRedirect(authorizeUrl);
            }
        }
        ```

        ```java CallbackServlet.java highlight={16-37} lines 
        @WebServlet(urlPatterns = {"/callback"})
        public class CallbackServlet extends HttpServlet {

            private String redirectOnSuccess;
            private String redirectOnFail;
            private AuthenticationController authenticationController;

            @Override
            public void init(ServletConfig config) throws ServletException {
                super.init(config);
                redirectOnSuccess = "/portal/home";
                redirectOnFail = "/login";
                authenticationController = AuthenticationControllerProvider.getInstance(config);
            }

            @Override
            public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
                handle(req, res);
            }

            @Override
            public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
                handle(req, res);
            }

            private void handle(HttpServletRequest req, HttpServletResponse res) throws IOException {
                try {
                    // Parse the request
                    Tokens tokens = authenticationController.handle(req, res);
                    SessionUtils.set(req, "accessToken", tokens.getAccessToken());
                    SessionUtils.set(req, "idToken", tokens.getIdToken());
                    res.sendRedirect(redirectOnSuccess);
                } catch (IdentityVerificationException e) {
                    e.printStackTrace();
                    res.sendRedirect(redirectOnFail);
                }
            }
        }
        ```

        ```java LogoutServlet.java highlight={13-30} lines 
        @WebServlet(urlPatterns = {"/logout"})
        public class LogoutServlet extends HttpServlet {

            private String domain;
            private String clientId;

            @Override
            public void init(ServletConfig config) {
                domain = config.getServletContext().getInitParameter("com.auth0.domain");
                clientId = config.getServletContext().getInitParameter("com.auth0.clientId");
            }

            @Override
            protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
                if (request.getSession() != null) {
                    request.getSession().invalidate();
                }
                String returnUrl = String.format("%s://%s", request.getScheme(), request.getServerName());
                if ((request.getScheme().equals("http") && request.getServerPort() != 80) || (request.getScheme().equals("https") && request.getServerPort() != 443)) {
                    returnUrl += ":" + request.getServerPort();
                }
                returnUrl += "/login";
                String logoutUrl = String.format(
                        "https://%s/v2/logout?client_id=%s&returnTo=%s",
                        domain,
                        clientId,
                        returnUrl
                );
                response.sendRedirect(logoutUrl);
            }

        }
        ```
      </CodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[7].id}>
      <CodeGroup>
        ```java LogoutServlet.java highlight={13-30} lines 
        @WebServlet(urlPatterns = {"/logout"})
        public class LogoutServlet extends HttpServlet {

            private String domain;
            private String clientId;

            @Override
            public void init(ServletConfig config) {
                domain = config.getServletContext().getInitParameter("com.auth0.domain");
                clientId = config.getServletContext().getInitParameter("com.auth0.clientId");
            }

            @Override
            protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
                if (request.getSession() != null) {
                    request.getSession().invalidate();
                }
                String returnUrl = String.format("%s://%s", request.getScheme(), request.getServerName());
                if ((request.getScheme().equals("http") && request.getServerPort() != 80) || (request.getScheme().equals("https") && request.getServerPort() != 443)) {
                    returnUrl += ":" + request.getServerPort();
                }
                returnUrl += "/login";
                String logoutUrl = String.format(
                        "https://%s/v2/logout?client_id=%s&returnTo=%s",
                        domain,
                        clientId,
                        returnUrl
                );
                response.sendRedirect(logoutUrl);
            }

        }
        ```

        ```xml web.xml lines
        <context-param>
            <param-name>com.auth0.domain</param-name>
            <param-value>dev-gja8kxz4ndtex3rq.us.auth0.com</param-value>
        </context-param>

        <context-param>
            <param-name>com.auth0.clientId</param-name>
            <param-value>mz9iNEIo2PHu7oeh8QRt19ndTyyCIgai</param-value>
        </context-param>

        <context-param>
            <param-name>com.auth0.clientSecret</param-name>
            <param-value>yLTW7npKO4g1HHsCENiZbOaHHXLmhVefJxdNnXcyhOBOomZ2tgjJjSC2pMK7Swvr</param-value>
        </context-param>
        ```

        ```java AuthenticationControllerProvider.java highlight={5-26} lines 
        class AuthenticationControllerProvider {

            private AuthenticationControllerProvider() {}

            private static AuthenticationController INSTANCE;

            // if multiple threads may call this, synchronize this method and consider double locking
            static AuthenticationController getInstance(ServletConfig config) throws UnsupportedEncodingException {
                if (INSTANCE == null) {
                    String domain = config.getServletContext().getInitParameter("com.auth0.domain");
                    String clientId = config.getServletContext().getInitParameter("com.auth0.clientId");
                    String clientSecret = config.getServletContext().getInitParameter("com.auth0.clientSecret");

                    if (domain == null || clientId == null || clientSecret == null) {
                        throw new IllegalArgumentException("Missing domain, clientId, or clientSecret. Did you update src/main/webapp/WEB-INF/web.xml?");
                    }

                    // JwkProvider required for RS256 tokens. If using HS256, do not use.
                    JwkProvider jwkProvider = new JwkProviderBuilder(domain).build();
                    INSTANCE = AuthenticationController.newBuilder(domain, clientId, clientSecret)
                            .withJwkProvider(jwkProvider)
                            .build();
                }

                return INSTANCE;
            }
        }
        ```

        ```java LoginServlet.java highlight={21-23} lines
        @WebServlet(urlPatterns = {"/login"})
        public class LoginServlet extends HttpServlet {
            private AuthenticationController authenticationController;
            private String domain;

            @Override
            public void init(ServletConfig config) throws ServletException {
                super.init(config);
                domain = config.getServletContext().getInitParameter("com.auth0.domain");
                authenticationController = AuthenticationControllerProvider.getInstance(config);
            }

            @Override
            protected void doGet(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException {
                String redirectUri = req.getScheme() + "://" + req.getServerName();
                if ((req.getScheme().equals("http") && req.getServerPort() != 80) || (req.getScheme().equals("https") && req.getServerPort() != 443)) {
                    redirectUri += ":" + req.getServerPort();
                }
                redirectUri += "/callback";

                String authorizeUrl = authenticationController.buildAuthorizeUrl(req, res, redirectUri)
                        .build();
                res.sendRedirect(authorizeUrl);
            }
        }
        ```

        ```java CallbackServlet.java highlight={16-37} lines 
        @WebServlet(urlPatterns = {"/callback"})
        public class CallbackServlet extends HttpServlet {

            private String redirectOnSuccess;
            private String redirectOnFail;
            private AuthenticationController authenticationController;

            @Override
            public void init(ServletConfig config) throws ServletException {
                super.init(config);
                redirectOnSuccess = "/portal/home";
                redirectOnFail = "/login";
                authenticationController = AuthenticationControllerProvider.getInstance(config);
            }

            @Override
            public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
                handle(req, res);
            }

            @Override
            public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
                handle(req, res);
            }

            private void handle(HttpServletRequest req, HttpServletResponse res) throws IOException {
                try {
                    // Parse the request
                    Tokens tokens = authenticationController.handle(req, res);
                    SessionUtils.set(req, "accessToken", tokens.getAccessToken());
                    SessionUtils.set(req, "idToken", tokens.getIdToken());
                    res.sendRedirect(redirectOnSuccess);
                } catch (IdentityVerificationException e) {
                    e.printStackTrace();
                    res.sendRedirect(redirectOnFail);
                }
            }
        }
        ```

        ```java HomeServlet.java highlight={4-14} lines
        @WebServlet(urlPatterns = {"/portal/home"})
        public class HomeServlet extends HttpServlet {

            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
                final String accessToken = (String) SessionUtils.get(req, "accessToken");
                final String idToken = (String) SessionUtils.get(req, "idToken");
                if (accessToken != null) {
                    req.setAttribute("userId", accessToken);
                } else if (idToken != null) {
                    req.setAttribute("userId", idToken);
                }
                req.getRequestDispatcher("/WEB-INF/jsp/home.jsp").forward(req, res);
            }
        }
        ```
      </CodeGroup>
    </SideMenuSectionItem>

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