Featured resource
2026 Tech Forecast
2026 Tech Forecast

1,500+ tech insiders, business leaders, and Pluralsight Authors share their predictions on what’s shifting fastest and how to stay ahead.

Download the forecast
  • Lab
    • Libraries: If you want this lab, consider one of these libraries.
    • Core Tech
Labs

When an ASP.NET Core API Leaves the Development Machine

Carved Rock Fitness rents outdoor gear to guided trip operators. Its Web API started as a single developer's localhost project but is now being handed to an operations team that will run it behind Azure App Service. Before that happens, the API needs real bearer-token security instead of a shared password, a considered answer for why it isn't using a hosted identity provider yet, two live route versions so existing trip-planning clients keep working, request scripts the ops team can run without writing code, and confirmation that the app behaves correctly once a proxy sits in front of it and secrets no longer live in a local file.

Lab platform
Lab Info
Level
Beginner
Last updated
Oct 23, 2026
Duration
48m

Contact sales

By clicking submit, you agree to our Privacy Policy and Terms of Use, and consent to receive marketing emails from Pluralsight.
Table of Contents
  1. Challenge

    Step 1: Meet Carved Rock Fitness's road to production

    Carved Rock Fitness rents outdoor gear to guided trip operators. Its Web API grew out of a single developer's localhost project, and the GearController answers requests today, but it isn't ready to hand to an operations team that will run it in Azure App Service:

    • Anyone who knows a shared password can call any endpoint.
    • Nothing distinguishes an old trip-planning client from a new one.
    • Ops has no ready-made way to send a safe, authenticated request.
    • Nothing has been checked behind a proxy, or with secrets kept outside a local file.

    Over the next four steps you will take the API from runs on my machine to ready to hand to ops. ### Step 2: Issue and evaluate bearer tokens

    A JSON Web Token (JWT) is a signed, self-contained statement of who the caller is and what they may do. It is checked cryptographically on every request, with no round trip to a database. You will:

    • Issue tokens that carry role and scope claims.
    • Require those claims before a rental request is honored.

    Carved Rock Fitness mints its own tokens rather than using an OpenID Connect provider such as Azure AD or Auth0. That is a defensible short-term choice, but only if you can say what a real OAuth 2.0/OpenID Connect provider adds (issuer, audience, expiry, and standard claim names) and where the custom tokens fall short. You will build a tool that makes that comparison concrete. ### Step 3: Version the API and its OpenAPI documents

    Trip-planning clients built against the current gear listing can't break when a richer response is needed.

    • v1 keeps its existing contract.
    • v2 adds new fields and tighter authorization.
    • One OpenAPI document per version, so a Swagger client exploring v2 isn't shown v1's routes. Each document also declares how to attach a bearer token. ### Step 4: Script the endpoints

    Ops needs to send requests without writing a test harness. You will generate HTTP_REPL commands and Visual Studio .http files that already include the right route, version, and Authorization header. ### Step 5: Run behind the App Service proxy

    Once the API runs in Azure App Service:

    • The app sees the proxy's address instead of the caller's, unless forwarded headers are handled.
    • Secrets come from a managed store instead of appsettings.Development.json.

    If either is wrong, the failures only appear in production. This step makes both visible and diagnosable before that happens.

    info> If you get stuck, you can refer to the provided solution code for each task, available in the solution folder.

  2. Challenge

    Step 2: Issue and evaluate bearer tokens

    A bearer token is only useful if it is signed and carries the claims a policy can check. src/TokenService.cs already has the signing key and JWT plumbing wired up; it just hands back an empty placeholder instead of a real token. You will teach it to embed the caller's role and scopes as claims and sign the result, so every downstream check in this lab has a real token to evaluate. A signed token is only as useful as the checks that read it. Rather than wiring claims-based authorization straight into the ASP.NET Core pipeline, src/RentalsAccessPolicy.cs isolates the decision itself: given a ClaimsPrincipal, should this caller reach the rentals endpoint? Keeping that logic in one place, separate from the pipeline, is what lets you test the authorization rule directly against the claims a token like the one you just issued would carry. Carved Rock Fitness's tokens work today, but 'works' and 'meets what an OpenID Connect provider guarantees' are different questions. src/ComplianceAdvisor.cs exists to answer the second one on demand: given any token string, does it carry the issuer, audience, and expiry claims a real OIDC provider would always include? That answer is what lets you tell ops, precisely, what changes the day Carved Rock Fitness adopts one.

  3. Challenge

    Step 3: Version the API and its OpenAPI documents

    Existing trip-planning clients call gear listing and expect exactly the fields they were built against -- name and daily rate, nothing else. src/GearControllerV1.cs is that frozen contract. It already has a route and an inventory field wired up; it just needs to actually project and return that fixed shape instead of the stub's empty response. v2 exists precisely because v1 cannot grow without breaking someone. src/GearControllerV2.cs reads from the same gear inventory as v1 but is free to expose more of it -- specifically, how many units of each item are actually available to rent. That is new information v1 clients never asked for and would not know what to do with, which is exactly why it lives behind a separate version. Two live route versions need two OpenAPI documents, or a Swagger client exploring v1 would be shown v2's routes and vice versa. src/OpenApiDocumentBuilder.cs builds that per-version description, including the fact that both versions sit behind the same bearer-token requirement -- a detail the document has to declare before any client generated from it can even attempt to authenticate.

  4. Challenge

    Step 4: Script the endpoints before anyone deploys them

    HTTP_REPL lets someone explore an API interactively from a terminal, one typed command at a time -- cd, set header, get. Ops shouldn't have to work out that sequence themselves. src/HttpReplScriptBuilder.cs generates it for them: point at the base URL, attach the bearer token, then exercise both live gear versions in order. Visual Studio's .http files take a different shape from HTTP_REPL commands: @variable = value declarations up top, then one request per block, each block a bare GET line followed by its headers, separated from the next by a blank line. src/HttpFileBuilder.cs produces exactly that text so ops can open one file and run both versioned requests without typing anything. Scripts are only half the story -- ops also needs to know, before running them, whether the token they were handed will actually pass v1's and v2's authorization checks. src/PreflightReport.cs combines what you already built: it decodes the token's claims the same way RentalsAccessPolicy does and reports a plain PASS or FAIL line for each version, so a bad token is caught before anyone runs the scripts against it.

  5. Challenge

    Step 5: Run correctly behind the App Service proxy

    Behind Azure App Service's proxy, the app's own HttpContext sees the proxy's internal scheme and host, not the address the caller actually used. App Service compensates by adding X-Forwarded-Proto and X-Forwarded-Host headers to every forwarded request. src/ForwardedHeadersResolver.cs reads those headers back out so anything that needs 'the address the caller used' -- links in a response, logs, diagnostics -- gets the right answer whether or not a proxy sits in front. A local appsettings.json secret disappears the moment Carved Rock Fitness moves to a managed host -- secrets there arrive as environment variables instead, and only fall back to configuration during local development. src/SecretLoader.cs encodes that fallback chain once, in one place, so every piece of the app that needs a secret asks this and gets the right source without knowing which environment it's running in. A startup failure that just says 'configuration invalid' sends ops hunting through every possible secret by hand. src/DiagnosticsReporter.cs checks the specific keys Carved Rock Fitness actually requires and names the ones that never resolved, turning a vague failure into a short, actionable list.

  6. Challenge

    Step 6: Run the application

    Every task is done, and each one was graded the moment you completed it. What you have not done yet is watch the whole application run at once -- which is the only place the pieces you wrote separately become a single working program.

    Start the application

    Open the Terminal tab and run:

    dotnet run --project src/Lab.csproj
    

    The program runs in the terminal and prints its output there. Every behaviour it shows is code you wrote in the previous steps, so read the output against what each task asked for -- that is the whole lab, working as one program. ### Run the checks yourself

    The lab ran each task's test for you as you went, but they are ordinary tests and you can run them whenever you like. The whole suite:

    dotnet test tests/Lab.Tests.csproj --nologo --verbosity quiet
    

    Or one task at a time:

    bash runTest.sh Task_2_1
    

    Each failure names the task it belongs to, so the output tells you which step to go back to rather than which line to stare at. Two things worth trying before you finish: break something on purpose and watch the matching check fail, then put it back. Knowing what a failure looks like is worth as much as knowing what a pass looks like, and it costs you nothing here.

    When you are done, everything you wrote is still in the editor tabs -- the lab is yours to keep reading.

About the author

Pluralsight’s AI authoring technology is designed to accelerate the creation of hands-on, technical learning experiences. Serving as a first-pass content generator, it produces structured lab drafts aligned to learning objectives defined by Pluralsight’s Curriculum team. Each lab is then enhanced by our Content team, who configure the environments, refine instructions, and conduct rigorous technical and quality reviews. The result is a collaboration between artificial intelligence and human expertise, where AI supports scale and efficiency, and Pluralsight experts ensure accuracy, relevance, and instructional quality, helping learners build practical skills with confidence.

Real skill practice before real-world application

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Learn by doing

Engage hands-on with the tools and technologies you’re learning. You pick the skill, we provide the credentials and environment.

Follow your guide

All labs have detailed instructions and objectives, guiding you through the learning process and ensuring you understand every step.

Turn time into mastery

On average, you retain 75% more of your learning if you take time to practice. Hands-on labs set you up for success to make those skills stick.

Get started with Pluralsight