The Problem Every App Faces
Every application that lets people log in has to answer three questions, constantly, for every single request:
- Who is this person? (Authentication)
- What are they allowed to do? (Authorization)
- Are they still who they say they are, right now? (Session validity)
Building this yourself sounds easy at first — a users table, some hashed passwords, done. But real apps quickly need:
- Password reset flows
- Email verification
- Multi-factor authentication (MFA)
- Social logins (Google, GitHub, Microsoft)
- Session expiry and refresh
- Account lockout after failed login attempts
- Audit logs for compliance
Building and maintaining all of this correctly is a full-time specialty. Getting it wrong is how companies get breached. This exact problem is what an Identity Provider (IdP) exists to solve.
What is IAM?
Identity and Access Management (IAM) is the general discipline of managing:
- Identity — who a user is
- Access — what that user is allowed to do
Okta is a company that provides IAM as a hosted, external service. Instead of you building login, MFA, password recovery, and user storage inside your own Next.js app, you outsource all of that to Okta.
What This Means for You as a Developer
Your job changes. You are no longer writing authentication logic yourself — you are integrating with an authentication provider using a standard protocol called OpenID Connect (OIDC), which sits on top of OAuth 2.0. We'll cover that protocol in full detail in Lecture 2.
Where Okta Actually Sits in Your App
Here's the mental model, in plain terms:
- User clicks "Log in" on your Next.js app.
- Your app redirects the user to Okta — a login page hosted on Okta's own servers, not yours.
- The user enters their password (and does MFA if required) on Okta's page. Your app never sees the password.
- Okta authenticates the user and redirects them back to your app, along with proof of who they are (a signed token).
- Your app verifies that proof and starts a session for the user.
That's the entire authentication flow at a conceptual level. Every lecture from Module 2 onward is about implementing these five steps with real TypeScript code in Next.js.
One More Thing to Know
Okta actually has two product lines:
- Workforce Identity Cloud — for logging employees into internal company tools.
- Customer Identity Cloud — for logging your app's end users (customers) in.
This course focuses on the developer-facing OIDC/OAuth layer, which works identically for both — so nothing here changes based on which one you're using.
OAuth 2.0 and OpenID Connect, Explained Properly
You've heard these terms thrown around, and Okta's docs assume you already know them. You don't need to feel that way after this lecture. We're going to build up the concepts slowly, with real reasoning behind each piece, so nothing feels like magic later.
Start With the Actual Problem
Imagine you're building an app called "TaskFlow." A user wants to log in. Somewhere, a check needs to happen: "does this password match this email?" You have two options.
Option A: Build your own login system. Store passwords (hashed), build a login form, handle "forgot password," handle account lockouts, eventually add MFA. You own all of it, forever, including every security patch.
Option B: Let a specialist (Okta) hold the credentials and do the checking. Your app never touches a password. Okta just tells your app "yes, this is [email protected], and here's proof."
Almost every serious app today picks Option B. But Option B raises a new question: how does Okta prove to your app that a user is who they say they are, in a way your app can trust, without your app and Okta needing to secretly share passwords?
That question is exactly what OAuth 2.0 and OpenID Connect answer. They are not Okta-specific — they're open standards. Okta is just one company that implements them (Google, Auth0, Microsoft Entra ID, and others also do). Once you understand these protocols, you understand any modern login system, not just Okta's.
OAuth 2.0: Solving "Access," Not "Identity"
Here's a common point of confusion, so let's kill it immediately: OAuth 2.0 was never designed to answer "who is this user?" It was designed to answer a narrower question: "can this app access this specific resource, on this user's behalf, without knowing the user's password?"
Think of the classic example: a photo-printing website wants to print your Google Photos, without you typing your Google password into the printing website. OAuth 2.0 lets you approve, from within Google's own page, that the printing site can access just your photos — nothing else, and only for as long as you allow.
The output of OAuth 2.0 is an access token — a piece of proof that says "the bearer of this token is allowed to access X." Critically, an access token does not, by design, guarantee anything about who the user actually is. It's a permission slip, not an ID card.
So Where Does "Identity" Come From? OpenID Connect
This is where OpenID Connect (OIDC) comes in. OIDC is a thin, standardized layer built directly on top of OAuth 2.0. It adds exactly one crucial thing that OAuth 2.0 alone doesn't guarantee: a reliable, verifiable answer to "who is this user?"
OIDC does this by introducing a new token type: the ID token. Unlike the access token (a permission slip), the ID token is explicitly an identity document. It's a signed piece of data containing claims like the user's email, name, and a unique user ID, and your app can cryptographically verify it hasn't been tampered with.
So, in one sentence that will save you a lot of confusion going forward:
OAuth 2.0 grants access. OpenID Connect proves identity. When people say "Okta uses OAuth," what they really mean is "Okta uses OIDC," because OIDC is what actually logs a user in. You'll use both together, always.
The Three Tokens You'll See Constantly
Once login succeeds, Okta hands your app up to three tokens. You'll work with these directly starting in Phase 2, so get familiar with their purpose now:
- ID Token — Proves who the user is. Contains identity claims (email, name, user ID). You use this to know who's logged in. Never send this to an API as proof of authorization — that's not its job.
- Access Token — Proves what the bearer is allowed to do. You attach this to requests to protected APIs (including your own Next.js API routes later). It does not reliably contain identity information you should trust for display purposes.
- Refresh Token — A long-lived token used to silently get new Access/ID tokens once the old ones expire, without forcing the user to log in again. We cover this properly in Phase 3.
The Authorization Code Flow, Step by Step
There are several ways ("flows" or "grant types") OAuth/OIDC define for getting these tokens. Some are outdated for browser apps and considered insecure today — if you find an old tutorial using the "Implicit Flow," skip it; it's deprecated and Okta actively discourages it. The flow we'll use throughout this course, and the one Okta recommends for basically everything now, is the Authorization Code Flow with PKCE. Here's exactly what happens, in order:
- User clicks "Log in" on your Next.js app.
- Your app redirects the browser to Okta's
/authorizeendpoint, including your app's Client ID, the permissions you're requesting (called scopes — e.g.openid profile email), and a redirect URI telling Okta where to send the user back afterward. - Before this redirect, your app generates a random secret called a code verifier, and sends a hashed version of it (the code challenge) along with the request. This is the "PKCE" part — Proof Key for Code Exchange. It exists to stop an attacker from intercepting the authorization code in step 5 and using it themselves.
- The user authenticates on Okta's page — types their password, does MFA if required. Your app is never involved in this step; it's entirely on Okta's domain.
- Okta redirects the browser back to your redirect URI, appending a short-lived, one-time-use authorization code as a query parameter.
- Your app's backend takes that code, along with the original code verifier from step 3, and sends both directly to Okta's
/tokenendpoint (a server-to-server request, not visible to the browser). - Okta checks that the code verifier matches the code challenge from step 3. If it matches, Okta responds with the ID token, access token, and (if requested) refresh token.
- Your app stores these tokens (we'll cover exactly where, safely, in Phase 2) and the user is now logged in.
Why does PKCE matter so much that Okta requires it by default now? Because step 5's authorization code briefly travels through the browser's URL bar, which can potentially be intercepted (via browser history, referrer headers, or a badly behaved extension). Without PKCE, anyone who steals that code could redeem it themselves. With PKCE, the code is useless to a thief because they don't have the original code verifier, which never left your app's server.
Scopes and Claims — Two Terms You'll See Everywhere
Two words you'll run into constantly, so let's define them precisely now:
- A scope is a request for a category of access — think of it as a checkbox you're asking the user to approve.
openidis a mandatory scope for OIDC logins.profileandemailrequest that the ID token includes the user's name and email. - A claim is an actual piece of data returned inside a token as a result of scopes you requested. Request the
emailscope, and you receive anemailclaim inside your ID token. Later, in Phase 5, you'll learn to create your own custom claims (like a user's role) to enforce authorization logic in your app.
Okta's Core Vocabulary
Now that you understand the protocol, here's the specific vocabulary Okta uses to implement it. Every one of these terms will reappear throughout the course, so it's worth being precise now.
Org — Your entire Okta account is called an "Org" (short for organization). It's the top-level container for everything: your users, your applications, your settings. When you sign up, you get a unique domain like dev-12345678.okta.com — this is your Org's base URL, and you'll use it constantly in configuration.
Application (or "App Integration") — A registration inside your Org representing one specific app that wants to use Okta for login — in our case, the Next.js dashboard we're building. Each Application gets its own Client ID, and (depending on type) a Client Secret. When you set one up, Okta asks what type of application it is — critically, whether it's a "Web Application" (has a secure backend, can keep a Client Secret private — this is what our Next.js app will be) versus a "Single-Page Application" (all code runs in the browser, so no secret can be kept safe, and PKCE alone protects it).
Authorization Server — The actual component that issues tokens and validates login requests, per the flow we just walked through. This part has some nuance worth knowing now: every Okta Org automatically comes with an Org Authorization Server, which handles basic SSO login but cannot be customized (no custom scopes or claims). Separately, Okta Orgs (including the free Integrator Free Plan we'll use) come with a default Custom Authorization Server, literally named default, which can be customized — this is the one we'll use starting in Phase 2, because Phase 5 requires custom claims that only a Custom Authorization Server supports. One detail worth flagging now so it doesn't surprise you later: on the free Integrator Free Plan, this default authorization server does not come with a basic access policy attached — we'll add one ourselves when we get to setup.
Users — Individual identity records inside your Org. Each has a profile (email, name, custom attributes you define) and credentials.
Groups — Collections of Users, used for organizing permissions. Instead of assigning access rules to individual users one by one, you assign a user to a Group (like "Admins" or "Editors") and write rules against the Group. This becomes central in Phase 5 when we build role-based access control.
Sign-On Policies / Authentication Policies — Rules attached to an Application or Authorization Server controlling how someone is allowed to log in — for example, "require MFA if logging in from a new device." We'll configure these hands-on in Phase 4.
What's Next
You now have the full theoretical foundation: why identity providers exist, exactly how the Authorization Code Flow with PKCE works step by step, what each token is for, and the specific Okta terms you'll be clicking through in the admin console. Nothing above required you to touch a keyboard yet — that changes in the next post.
Next we'll do the two hands-on steps that finish this phase: creating your free Okta Integrator Free Plan account and registering your first Application, followed by setting up the actual Next.js + TypeScript + Tailwind project we'll build on for the rest of the course.