Micro-Frontends Part 3: Implementing Okta Authentication Across Next.js Micro-Frontends
In Part 2, I walked through a hands-on setup for micro-frontends using Next.js + Webpack Module Federation, with a shell application…
Micro-Frontends Part 3: Implementing Okta Authentication Across Next.js Micro-Frontends

OKTA LOGIN IN MICROFRONTENDS
In Part 2, I walked through a hands-on setup for micro-frontends using Next.js + Webpack Module Federation, with a shell application composing remote applications at runtime.
A common follow-up question was:
How do you implement authentication across multiple micro-frontends without every app building its own login flow?
The short answer:
Authenticate once in the shell, share user context to remotes, and enforce authorization at both shell and domain level.
In this article, I’ll walk through an end-to-end approach using Okta + Next.js + Module Federation.
Architecture Goal
We want this flow:
User authenticates with Okta
↓
Shell establishes shared user session
↓
Customer, Order, Cart and Admin apps consume shared auth context
↓
Access is controlled by roles and claims
↓
Domain APIs enforce fine-grained permissions
Single sign-on. No duplicate login. No multiple sessions.
Why Authentication Should Live in the Shell
A common anti-pattern is letting each micro-frontend manage login.
That creates:
- Multiple auth implementations
- Session inconsistencies
- Token duplication
- Access-control drift
Instead:
Shell owns:
- Customer sign-in
- Shared session for Order, Cart and Admin apps
- Role-based access to each domain
- Protection of private routes
- Authentication context shared to all remotes
Remotes trust the shell.
Step 1: Configure Okta Application
Create an OIDC app in Okta.
Example settings:
Application Type: Single Page App
Grant Type: Authorization Code + PKCE
Redirect URI:
http://localhost:3000/login/callback
Logout URI:
http://localhost:3000
Capture:
Client ID
Issuer URL
Example:
NEXT_PUBLIC_OKTA_ISSUER=https://dev-xxxx.okta.com/oauth2/default
NEXT_PUBLIC_OKTA_CLIENT_ID=xxxx
Step 2: Install Dependencies
npm install @okta/okta-auth-js @okta/okta-react
Step 3: Create Shared Auth Package
Instead of putting auth logic inside one app, create a shared package.
packages/auth-sdk
AuthContext
import React,
{
createContext,
useContext
} from 'react';
const AuthContext =
createContext(null);
export function AuthProvider({
user,
token,
children
}) {
return (
<AuthContext.Provider
value={{ user, token }}
>
{children}
</AuthContext.Provider>
);
}
export function useAuth(){
const ctx = useContext(AuthContext);
if(!ctx){
throw new Error(
'useAuth must be inside AuthProvider'
);
}
return ctx;
}
This will be shared across shell and remotes.
Step 4: Initialize Okta in Shell
import { OktaAuth }
from '@okta/okta-auth-js';
export const oktaAuth =
new OktaAuth({
issuer:
process.env.NEXT_PUBLIC_OKTA_ISSUER,
clientId:
process.env.NEXT_PUBLIC_OKTA_CLIENT_ID,
redirectUri:
window.location.origin +
'/login/callback'
});
Step 5: Wrap Shell with Security Provider
import {
Security
} from '@okta/okta-react';
import {
AuthProvider
} from '@org/auth-sdk';
<Security oktaAuth={oktaAuth}>
<AuthProvider
user={user}
token={accessToken}
>
<RemoteApps />
</AuthProvider>
</Security>
Now every remote can consume the same authenticated user.
Step 6: Share Auth Package as Singleton
Critical for Module Federation.
shared: {
'@org/auth-sdk': {
singleton:true
},
react:{ singleton:true },
'react-dom':{
singleton:true
}
}
If not shared as singleton, remotes may get a different context instance.
That breaks authentication.
Step 7: Consume User Context in Remote MFE
import {
useAuth
} from '@org/auth-sdk';
function ComplianceApp(){
const {
user,
token
} = useAuth();
return (
<div>
Welcome {user.name}
</div>
);
}
Remote did not implement login.
It consumed shared session.
Step 8: Protect Routes in Shell
Example Next.js middleware:
import { NextResponse }
from 'next/server';
export function middleware(req){
const token =
req.cookies.get('token');
if(!token){
return NextResponse.redirect(
new URL('/login', req.url)
);
}
return NextResponse.next();
}
Private routes stay protected.
Step 9: Add Role-Based Access
Example claims:
{
"roles":["customer"],
"apps":["customer","cart","orders"]
}
Hide unauthorized domains.
if(
!apps.includes('order')
){
return <AccessDenied />
}
You can also filter sidebar entries.
Step 10: Use Token in Domain APIs
Remotes use shared token.
fetch('/api/order',{
headers:{
Authorization:
`Bearer ${token}`
}
})
Backend still validates scopes.
Never trust frontend-only checks.
End-to-End Flow
User clicks Login
↓
Redirect to Okta
↓
Okta authenticates
↓
Shell receives access token
↓
Shell creates AuthProvider
↓
Remote consumes useAuth()
↓
Remote calls APIs with token
Single login. Shared access.
What About Different Permissions Per Domain?
Use layered authorization.
Level 1: Shell decides if user can access the micro-frontend.
Level 2: Domain backend enforces fine-grained permissions.
Example:
Customer can access Cart
Admin can access Admin Console
Handled in domain service.
Common Pitfalls
1. Each MFE implementing its own login
Avoid it.
Centralize authentication.
2. Not sharing AuthContext as singleton
Can break context.
3. Frontend-only authorization
Backend must validate claims.
4. Storing tokens separately in every MFE
Keep trust centralized.
Architecture Summary
Okta
|
Shell
(login, claims, route protection)
|
--------------------------------------
| | |
Product MFE Cart MFE Order MFE
All consume shared AuthContext
Final Takeaway
For authentication in micro-frontends, I would keep three rules:
- Authenticate once in the shell.
- Share user context to remotes through a shared auth package.
- Enforce authorization in both shell and domain backends.
That keeps authentication centralized, scalable, and secure.
In the next part, I’ll cover how to handle shared state and cross-micro-frontend communication without introducing tight coupling.
MicroFrontends #NextJS #Okta #Authentication #ModuleFederation #SingleSignOn #SSO #ReactJS #SoftwareArchitecture #FrontendArchitecture #WebSecurity #OAuth2 #OIDC #RoleBasedAccessControl #RBAC #DistributedSystems #EnterpriseArchitecture
메타데이터
- post_id
- be4e72639a2f
- slug
- micro-frontends-part-3-implementing-okta-authentication-across-next-js-micro-frontends-be4e72639a2f
- url
- https://medium.com/@GoutamSingha/micro-frontends-part-3-implementing-okta-authentication-across-next-js-micro-frontends-be4e72639a2f
- canonical_url
- https://medium.com/@GoutamSingha/micro-frontends-part-3-implementing-okta-authentication-across-next-js-micro-frontends-be4e72639a2f
- author_url
- https://medium.com/@GoutamSingha
- status
- ok
- fetched_at
- 2026-06-20 20:29:01