> ## 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 authorization to an ASP.NET Core Web API application using the standard JWT middleware.

# Add Authorization to Your ASP.NET Core Web API 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: "define-permissions",
  title: "Define permissions"
}, {
  id: "install-dependencies",
  title: "Install dependencies"
}, {
  id: "configure-the-middleware",
  title: "Configure the middleware"
}, {
  id: "validate-scopes",
  title: "Validate scopes"
}, {
  id: "protect-api-endpoints",
  title: "Protect API endpoints"
}, {
  id: "call-your-api",
  title: "Call your API"
}];

<Recipe>
  <Content>
    Auth0 allows you to add authentication and access user profile information in almost any application type quickly.
    This guide demonstrates how to integrate Auth0 with any new or existing ASP.NET Web API application using the
    `Microsoft.AspNetCore.Authentication.JwtBearer` package.

    If you haven't created an API in your Auth0 dashboard yet, you can use the interactive selector to create a new
    Auth0 API or select an existing API that represents the project you want to integrate with.

    Alternatively, you can read our getting started guide,
    which will help you set up your first API through the Auth0 Dashboard.

    Note that every API in Auth0 is configured using an API Identifier; your application code will use the API
    Identifier as the Audience to validate the access token.

    <Info>
      **New to Auth0?** Learn how Auth0 works and
      read about implementing API authentication and
      authorization using the OAuth 2.0 framework.
    </Info>

    <Section id={sections[0].id} title={sections[0].title} stepNumber="1">
      Permissions let you define how resources can be accessed on behalf of the user with a given access token. For
      example, you might choose to grant read access to the `messages` resource if users have the manager
      access level, and grant write access to that resource if they have the administrator access level.

      You can define allowed permissions in the **Permissions** view of the Auth0 Dashboard's [APIs](https://manage.auth0.com/#/apis) section. The following
      example uses the `read:messages` scope.

      <Frame>
        <img src="https://mintcdn.com/docs-staging-quickstart-revamp/fNPG21NgQLCA0axA/images/cdy7uua7fh8z/1s3Yp5zqJiKiSWqbPSezNO/e61793a2822d095666002c3f65c71ac2/configure-permissions.png?fit=max&auto=format&n=fNPG21NgQLCA0axA&q=85&s=460e697ffac537de4d7729d0e20a23ea" width="1078" height="679" data-path="images/cdy7uua7fh8z/1s3Yp5zqJiKiSWqbPSezNO/e61793a2822d095666002c3f65c71ac2/configure-permissions.png" />
      </Frame>
    </Section>

    <Section id={sections[1].id} title={sections[1].title} stepNumber="2">
      To allow your application to validate access tokens, add a reference to the
      `Microsoft.AspNetCore.Authentication.JwtBearer` NuGet package:

      ```
      Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
      ```
    </Section>

    <Section id={sections[2].id} title={sections[2].title} stepNumber="3">
      Set up the authentication middleware by configuring it in your application's `Program.cs` file:

      1. Register the authentication services by making a call to the `AddAuthentication` method. Configure
         `JwtBearerDefaults.AuthenticationScheme` as the default scheme.

      2. Register the JWT Bearer authentication scheme by making a call to the `AddJwtBearer` method.
         Configure your Auth0 domain as the authority and your Auth0 API Identifier as the audience, and be sure that
         your Auth0 domain and API Identifier are set in your application's **appsettings.json** file.

               <Info>
                 In some cases, the access token will not have a `sub` claim; in this case, the
                 `User.Identity.Name` will be `null`. If you want to map a different claim to
                 `User.Identity.Name`, add it to `options.TokenValidationParameters` within the
                 `AddJwtBearer()` call.
               </Info>

      3. Add the authentication and authorization middleware to the middleware pipeline by adding calls to the
         `UseAuthentication`and `UseAuthorization`methods under the
         `var app = builder.Build();`method.
    </Section>

    <Section id={sections[3].id} title={sections[3].title} stepNumber="4">
      To ensure that an access token contains the correct scopes, use [Policy-Based Authorization](https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies) in the ASP.NET Core:

      1. Create a new authorization requirement called `HasScopeRequirement`, which will check whether the
         `scope`claim issued by your Auth0 tenant is present, and if so, will check that the claim contains
         the requested scope.
      2. Under your `Program.cs`file's
         `var builder = WebApplication.CreateBuilder(args);`method, add a call to the
         `app.AddAuthorization`method.
      3. Add policies for scopes by calling `AddPolicy`for each scope.
      4. Register a singleton for the `HasScopeHandler`class.
    </Section>

    <Section id={sections[4].id} title={sections[4].title} stepNumber="5">
      The JWT middleware integrates with the standard ASP.NET Core [Authentication](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/) and [Authorization](https://docs.microsoft.com/en-us/aspnet/core/security/authorization/) mechanisms.

      To secure an endpoint, add the `[Authorize]` attribute to your controller action (or the entire
      controller if you want to protect all of its actions).

      When securing endpoints that require specific scopes, make sure that the correct scope is present in the
      `access_token`. To do so, add the `Authorize` attribute to the `Scoped` action
      and pass `read:messages` as the `policy` parameter.
    </Section>

    <Section id={sections[5].id} title={sections[5].title} stepNumber="6">
      The way in which you call your API depends on the type of application you are developing and the framework you
      are using. To learn more, read the relevant application Quickstart:

      * [Single-Page Applications](/docs/quickstart#single-page-app)
      * [Mobile / Native Application](/docs/quickstart#native-mobile-app)

      ### Get an access token

      Regardless of the type of application you are developing or the framework you are using, to call your API, you
      need an access token.

      If you call your API from a Single-Page Application (SPA) or Native application, you will receive an access token
      after the authorization flow completes.

      If you call the API from a command-line tool or other service where a user entering credentials does not exist,
      use the [OAuth Client
      Credentials Flow](https://auth0.com/docs/api/authentication#client-credentials). To do so, register a [Machine-to-Machine Application](https://manage.auth0.com/#/applications) and pass the following values in your request:

      * **Client ID** as the `client_id` parameter.
      * **Client Secret** as the `client_secret` parameter.
      * **API Identifier** (the same value used to configure the middleware earlier in this quickstart) as the
        `audience` parameter.

      <Info>
        To learn more about getting the Client ID and Client Secret for your machine-to-machine application,
        read Application Settings.
      </Info>

      **Example request**

      <CodeGroup>
        ```sh cURL lines
        curl --request post \
        --url 'https://dev-gja8kxz4ndtex3rq.us.auth0.com/oauth/token' \
        --header 'content-type: application/x-www-form-urlencoded'
        ```

        ```cs C# lines
        var client = new RestClient("https://dev-gja8kxz4ndtex3rq.us.auth0.com/oauth/token");
        var request = new RestRequest(Method.POST);
        request.AddHeader("content-type", "application/x-www-form-urlencoded");
        IRestResponse response = client.Execute(request);
        ```

        ```go Go lines
        package main
        import (
        "fmt"
        "net/http"
        "io/ioutil"
        )
        func main() {
        url := "https://dev-gja8kxz4ndtex3rq.us.auth0.com/oauth/token"
        req, _ := http.NewRequest("post", url, nil)
        req.Header.Add("content-type", "application/x-www-form-urlencoded")
        res, _ := http.DefaultClient.Do(req)
        defer res.Body.Close()
        body, _ := ioutil.ReadAll(res.Body)
        fmt.Println(res)
        fmt.Println(string(body))
        }
        ```

        ```java Java lines
        HttpResponse<String> response = Unirest.post("https://dev-gja8kxz4ndtex3rq.us.auth0.com/oauth/token")
        .header("content-type", "application/x-www-form-urlencoded")
        .asString();
        ```

        ```js Node.JS lines
        var axios = require("axios").default;
        var options = {
        method: 'post',
        url: 'https://dev-gja8kxz4ndtex3rq.us.auth0.com/oauth/token',
        headers: {'content-type': 'application/x-www-form-urlencoded'}
        };
        axios.request(options).then(function (response) {
        console.log(response.data);
        }).catch(function (error) {
        console.error(error);
        });
        ```

        ```obj-c Obj-C lines
        #import <Foundation/Foundation.h>
        NSDictionary *headers = @{ @"content-type": @"application/x-www-form-urlencoded" };
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://dev-gja8kxz4ndtex3rq.us.auth0.com/oauth/token"]
                                                           cachePolicy:NSURLRequestUseProtocolCachePolicy

                                                       timeoutInterval:10.0];

        [request setHTTPMethod:@"post"];
        [request setAllHTTPHeaderFields:headers];
        NSURLSession *session = [NSURLSession sharedSession];
        NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                                completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

                                                    if (error) {

                                                        NSLog(@&quot;%@&quot;, error);

                                                    } else {

                                                        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;

                                                        NSLog(@&quot;%@&quot;, httpResponse);

                                                    }

                                                }];

        [dataTask resume];
        ```

        ```php PHP lines
        $curl = curl_init();
        curl_setopt_array($curl, [
        CURLOPT_URL => "https://dev-gja8kxz4ndtex3rq.us.auth0.com/oauth/token",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING => "",
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST => "post",
        CURLOPT_HTTPHEADER => [
        &quot;content-type: application/x-www-form-urlencoded&quot;

        ],
        ]);
        $response = curl_exec($curl);
        $err = curl_error($curl);
        curl_close($curl);
        if ($err) {
        echo "cURL Error #:" . $err;
        } else {
        echo $response;
        }
        ```

        ```python Python lines
        import http.client
        conn = http.client.HTTPSConnection("")
        headers = { 'content-type': "application/x-www-form-urlencoded" }
        conn.request("post", "/dev-gja8kxz4ndtex3rq.us.auth0.com/oauth/token", headers=headers)
        res = conn.getresponse()
        data = res.read()
        print(data.decode("utf-8"))
        ```

        ```rb Ruby lines
        require 'uri'
        require 'net/http'
        require 'openssl'
        url = URI("https://dev-gja8kxz4ndtex3rq.us.auth0.com/oauth/token")
        http = Net::HTTP.new(url.host, url.port)
        http.use_ssl = true
        http.verify_mode = OpenSSL::SSL::VERIFY_NONE
        request = Net::HTTP::Post.new(url)
        request["content-type"] = 'application/x-www-form-urlencoded'
        response = http.request(request)
        puts response.read_body
        ```

        ```swift Swift lines
        require 'uri'
        require 'net/http'
        require 'openssl'
        url = URI("https://dev-gja8kxz4ndtex3rq.us.auth0.com/oauth/token")
        http = Net::HTTP.new(url.host, url.port)
        http.use_ssl = true
        http.verify_mode = OpenSSL::SSL::VERIFY_NONE
        request = Net::HTTP::Post.new(url)
        request["content-type"] = 'application/x-www-form-urlencoded'
        response = http.request(request)
        puts response.read_body
        ```
      </CodeGroup>

      ### Call a secure endpoint

      Now that you have an access token, you can use it to call secure API endpoints. When calling a secure endpoint,
      you must include the access token as a Bearer token in the **Authorization** header of the request. For
      example, you can make a request to the `/api/private` endpoint:

      <CodeGroup>
        ```sh cURL lines
        curl --request get \
        --url http://localhost:3010/api/private \
        --header 'authorization: Bearer YOUR_ACCESS_TOKEN'
        ```

        ```cs C# lines
        var client = new RestClient("http://localhost:3010/api/private");
        var request = new RestRequest(Method.GET);
        request.AddHeader("authorization", "Bearer YOUR_ACCESS_TOKEN");
        IRestResponse response = client.Execute(request);
        ```

        ```go Go lines
        package main
        import (
        "fmt"
        "net/http"
        "io/ioutil"
        )
        func main() {
        url := "http://localhost:3010/api/private"
        req, _ := http.NewRequest("get", url, nil)
        req.Header.Add("authorization", "Bearer YOUR_ACCESS_TOKEN")
        res, _ := http.DefaultClient.Do(req)
        defer res.Body.Close()
        body, _ := ioutil.ReadAll(res.Body)
        fmt.Println(res)
        fmt.Println(string(body))
        }
        ```

        ```java Java lines
        HttpResponse<String> response = Unirest.get("http://localhost:3010/api/private")
        .header("authorization", "Bearer YOUR_ACCESS_TOKEN")
        .asString();
        ```

        ```js Node.JS lines
        var axios = require("axios").default;
        var options = {
        method: 'get',
        url: 'http://localhost:3010/api/private',
        headers: {authorization: 'Bearer YOUR_ACCESS_TOKEN'}
        };
        axios.request(options).then(function (response) {
        console.log(response.data);
        }).catch(function (error) {
        console.error(error);
        });
        ```

        ```obj-c Obj-C lines
        #import <Foundation/Foundation.h>
        NSDictionary *headers = @{ @"authorization": @"Bearer YOUR_ACCESS_TOKEN" };
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost:3010/api/private"]
                                                          cachePolicy:NSURLRequestUseProtocolCachePolicy

                                                      timeoutInterval:10.0];

        [request setHTTPMethod:@"get"];
        [request setAllHTTPHeaderFields:headers];
        NSURLSession *session = [NSURLSession sharedSession];
        NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                                completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

                                                    if (error) {

                                                        NSLog(@&quot;%@&quot;, error);

                                                    } else {

                                                        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;

                                                        NSLog(@&quot;%@&quot;, httpResponse);

                                                    }

                                                }];

        [dataTask resume];
        ```

        ```php PHP lines
        $curl = curl_init();
        curl_setopt_array($curl, [
        CURLOPT_PORT => "3010",
        CURLOPT_URL => "http://localhost:3010/api/private",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING => "",
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST => "get",
        CURLOPT_HTTPHEADER => [
        &quot;authorization: Bearer YOUR_ACCESS_TOKEN&quot;

        ],
        ]);
        $response = curl_exec($curl);
        $err = curl_error($curl);
        curl_close($curl);
        if ($err) {
        echo "cURL Error #:" . $err;
        } else {
        echo $response;
        }
        ```

        ```python Python lines
        import http.client
        conn = http.client.HTTPConnection("localhost:3010")
        headers = { 'authorization': "Bearer YOUR_ACCESS_TOKEN" }
        conn.request("get", "/api/private", headers=headers)
        res = conn.getresponse()
        data = res.read()
        print(data.decode("utf-8"))
        ```

        ```rb Ruby lines
        require 'uri'
        require 'net/http'
        url = URI("http://localhost:3010/api/private")
        http = Net::HTTP.new(url.host, url.port)
        request = Net::HTTP::Get.new(url)
        request["authorization"] = 'Bearer YOUR_ACCESS_TOKEN'
        response = http.request(request)
        puts response.read_body
        ```

        ```swift Swift lines
        import Foundation
        let headers = ["authorization": "Bearer YOUR_ACCESS_TOKEN"]
        let request = NSMutableURLRequest(url: NSURL(string: "http://localhost:3010/api/private")! as URL,
                                            cachePolicy: .useProtocolCachePolicy,

                                        timeoutInterval: 10.0)

        request.httpMethod = "get"
        request.allHTTPHeaderFields = headers
        let session = URLSession.shared
        let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
        if (error != nil) {
        print(error)

        } else {
        let httpResponse = response as? HTTPURLResponse

        print(httpResponse)

        }
        })
        dataTask.resume()
        ```
      </CodeGroup>

      Call the `/api/private-scoped` endpoint in a similar way, but ensure that the API permissions are
      configured correctly and that the access token includes the `read:messages` scope.

      <Note>
        ##### Checkpoint

        You should now be able to call the `/api/private` and `/api/private-scoped`
        endpoints.

        Run your application and verify that:

        * `GET /api/private`is available for authenticated requests.
        * `GET /api/private-scoped`is available for authenticated requests containing an access
          token with the `read:messages`scope.
      </Note>
    </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 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>
        ```cs Program.cs lines highlight={}
        var builder = WebApplication.CreateBuilder(args);
        builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Authority = $"https://{builder.Configuration["Auth0:Domain"]}/";
            options.Audience = builder.Configuration["Auth0:Audience"];
            options.TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = ClaimTypes.NameIdentifier
            };
        });

            builder.Services
              .AddAuthorization(options =>
              {
                  options.AddPolicy(
                    "read:messages",
                    policy => policy.Requirements.Add(
                      new HasScopeRequirement("read:messages", domain)
                    )
                  );
              });

            builder.Services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();

        var app = builder.Build();
        app.UseAuthentication();
        app.UseAuthorization();
        ```

        ```json appsettings.json lines highlight={}
        {
          "Auth0": {
            "Domain": "dev-gja8kxz4ndtex3rq.us.auth0.com",
            "Audience": "{yourApiIdentifier}"
          }
        }
        ```

        ```cs HasScopeHandler.cs lines highlight={}
        public class HasScopeHandler : AuthorizationHandler<HasScopeRequirement>
        {
          protected override Task HandleRequirementAsync(
            AuthorizationHandlerContext context,
            HasScopeRequirement requirement
          ) {
            // If user does not have the scope claim, get out of here
            if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer))
              return Task.CompletedTask;

            // Split the scopes string into an array
            var scopes = context.User
              .FindFirst(c => c.Type == "scope" && c.Issuer == requirement.Issuer).Value.Split(' ');

            // Succeed if the scope array contains the required scope
            if (scopes.Any(s => s == requirement.Scope))
              context.Succeed(requirement);

            return Task.CompletedTask;
          }
        }
        ```

        ```cs HasScopeRequirement.cs lines highlight={}
        public class HasScopeRequirement : IAuthorizationRequirement
        {
            public string Issuer { get; }
            public string Scope { get; }

            public HasScopeRequirement(string scope, string issuer)
            {
                Scope = scope ?? throw new ArgumentNullException(nameof(scope));
                Issuer = issuer ?? throw new ArgumentNullException(nameof(issuer));
            }
        }
        ```

        ```cs ApiController.cs lines highlight={}
        [Route("api")]
        public class ApiController : Controller
        {
            [HttpGet("private")]
            [Authorize]
            public IActionResult Private()
            {
                return Ok(new
                {
                    Message = "Hello from a private endpoint!"
                });
            }

            [HttpGet("private-scoped")]
            [Authorize("read:messages")]
            public IActionResult Scoped()
            {
                return Ok(new
                {
                    Message = "Hello from a private-scoped endpoint!"
                });
            }
        }
        ```
      </CodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[3].id}>
      <CodeGroup>
        ```cs HasScopeHandler.cs lines highlight={}
        public class HasScopeHandler : AuthorizationHandler<HasScopeRequirement>
        {
          protected override Task HandleRequirementAsync(
            AuthorizationHandlerContext context,
            HasScopeRequirement requirement
          ) {
            // If user does not have the scope claim, get out of here
            if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer))
              return Task.CompletedTask;

            // Split the scopes string into an array
            var scopes = context.User
              .FindFirst(c => c.Type == "scope" && c.Issuer == requirement.Issuer).Value.Split(' ');

            // Succeed if the scope array contains the required scope
            if (scopes.Any(s => s == requirement.Scope))
              context.Succeed(requirement);

            return Task.CompletedTask;
          }
        }
        ```

        ```cs Program.cs lines highlight={}
        var builder = WebApplication.CreateBuilder(args);
        builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Authority = $"https://{builder.Configuration["Auth0:Domain"]}/";
            options.Audience = builder.Configuration["Auth0:Audience"];
            options.TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = ClaimTypes.NameIdentifier
            };
        });

            builder.Services
              .AddAuthorization(options =>
              {
                  options.AddPolicy(
                    "read:messages",
                    policy => policy.Requirements.Add(
                      new HasScopeRequirement("read:messages", domain)
                    )
                  );
              });

            builder.Services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();

        var app = builder.Build();
        app.UseAuthentication();
        app.UseAuthorization();
        ```

        ```json appsettings.json lines highlight={}
        {
          "Auth0": {
            "Domain": "dev-gja8kxz4ndtex3rq.us.auth0.com",
            "Audience": "{yourApiIdentifier}"
          }
        }
        ```

        ```cs HasScopeRequirement.cs lines highlight={}
        public class HasScopeRequirement : IAuthorizationRequirement
        {
            public string Issuer { get; }
            public string Scope { get; }

            public HasScopeRequirement(string scope, string issuer)
            {
                Scope = scope ?? throw new ArgumentNullException(nameof(scope));
                Issuer = issuer ?? throw new ArgumentNullException(nameof(issuer));
            }
        }
        ```

        ```cs ApiController.cs lines highlight={}
        [Route("api")]
        public class ApiController : Controller
        {
            [HttpGet("private")]
            [Authorize]
            public IActionResult Private()
            {
                return Ok(new
                {
                    Message = "Hello from a private endpoint!"
                });
            }

            [HttpGet("private-scoped")]
            [Authorize("read:messages")]
            public IActionResult Scoped()
            {
                return Ok(new
                {
                    Message = "Hello from a private-scoped endpoint!"
                });
            }
        }
        ```
      </CodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[4].id}>
      <CodeGroup>
        ```cs ApiController.cs lines highlight={}
        [Route("api")]
        public class ApiController : Controller
        {
            [HttpGet("private")]
            [Authorize]
            public IActionResult Private()
            {
                return Ok(new
                {
                    Message = "Hello from a private endpoint!"
                });
            }

            [HttpGet("private-scoped")]
            [Authorize("read:messages")]
            public IActionResult Scoped()
            {
                return Ok(new
                {
                    Message = "Hello from a private-scoped endpoint!"
                });
            }
        }
        ```

        ```cs HasScopeHandler.cs lines highlight={}
        public class HasScopeHandler : AuthorizationHandler<HasScopeRequirement>
        {
          protected override Task HandleRequirementAsync(
            AuthorizationHandlerContext context,
            HasScopeRequirement requirement
          ) {
            // If user does not have the scope claim, get out of here
            if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer))
              return Task.CompletedTask;

            // Split the scopes string into an array
            var scopes = context.User
              .FindFirst(c => c.Type == "scope" && c.Issuer == requirement.Issuer).Value.Split(' ');

            // Succeed if the scope array contains the required scope
            if (scopes.Any(s => s == requirement.Scope))
              context.Succeed(requirement);

            return Task.CompletedTask;
          }
        }
        ```

        ```cs Program.cs lines highlight={}
        var builder = WebApplication.CreateBuilder(args);
        builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Authority = $"https://{builder.Configuration["Auth0:Domain"]}/";
            options.Audience = builder.Configuration["Auth0:Audience"];
            options.TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = ClaimTypes.NameIdentifier
            };
        });

            builder.Services
              .AddAuthorization(options =>
              {
                  options.AddPolicy(
                    "read:messages",
                    policy => policy.Requirements.Add(
                      new HasScopeRequirement("read:messages", domain)
                    )
                  );
              });

            builder.Services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();

        var app = builder.Build();
        app.UseAuthentication();
        app.UseAuthorization();
        ```

        ```json appsettings.json lines highlight={}
        {
          "Auth0": {
            "Domain": "dev-gja8kxz4ndtex3rq.us.auth0.com",
            "Audience": "{yourApiIdentifier}"
          }
        }
        ```

        ```cs HasScopeRequirement.cs lines highlight={}
        public class HasScopeRequirement : IAuthorizationRequirement
        {
            public string Issuer { get; }
            public string Scope { get; }

            public HasScopeRequirement(string scope, string issuer)
            {
                Scope = scope ?? throw new ArgumentNullException(nameof(scope));
                Issuer = issuer ?? throw new ArgumentNullException(nameof(issuer));
            }
        }
        ```
      </CodeGroup>
    </SideMenuSectionItem>

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