AADSTS54005 Error in NextAuth with Azure AD – How I Faced and Fixed It in Production
If you are working with Next.js and NextAuth using Azure Active Directory authentication, there is a high chance you might run into this error at some point:
AADSTS54005: OAuth2 Authorization code was already used
I faced this issue myself while deploying a production application that used secure OAuth authentication with Azure AD. At first, everything looked fine — environment variables were correct, Azure configuration was properly set, and the login flow worked in development.
But once deployed, the authentication started failing. After debugging the issue deeply, I realized this is a common problem in real-world authentication systems, especially when working with cloud identity providers and secure login flows.
AADSTS54005 error during Azure AD authentication in NextAuth
This is the exact error I encountered while deploying my application in production
What This Error Actually Means
In simple terms, this error is related to how OAuth authentication works.
When a user logs in using Azure Active Directory, an authorization code is generated. Your backend exchanges this code for an access token to complete the login process.
This is a core part of modern authentication systems used in SaaS applications, enterprise login systems, and cloud-based identity management.
The important rule is that this authorization code can only be used once. If your application tries to reuse it, Azure returns an invalid_grant error.
What Happened in My Case
I was working on a production system using Next.js, NextAuth, and Azure AD authentication. The application was deployed behind Nginx, which handled incoming requests.
Initially, everything worked in development. But after deployment, users started facing login issues. While checking logs, I noticed that the callback endpoint:
/api/auth/callback/azure-ad
was being triggered twice.
This was the key problem. The first request successfully used the authorization code, but the second request tried to reuse it, causing the failure.
Main Reasons I Found
1. Duplicate Callback Requests
This is the most common cause of this issue in authentication systems.
Duplicate requests can occur due to frontend rendering, browser retries, or reverse proxy configurations. In cloud deployments, this is very common when using load balancers or proxy servers.
- React rendering multiple times
- Browser retry behavior
- Reverse proxy retry settings
2. Mixing Development and Production Credentials
In modern DevOps workflows, we usually maintain separate environments. However, mixing Azure AD credentials between environments can break the OAuth flow.
This is especially common in SaaS applications and enterprise authentication setups.
3. Redirect URI Mismatch
Azure Active Directory requires an exact match for redirect URIs. Even a small difference can cause authentication failures.
How I Fixed the Issue Step by Step
Step 1: Verified Environment Variables
I first ensured that my production environment variables were correctly configured:
NEXTAUTH_URL=https://yourdomain.com
AZURE_AD_CLIENT_ID=your-client-id
AZURE_AD_CLIENT_SECRET=your-client-secret
This step is critical in any cloud-based authentication system.
Also, I made sure to clearly separate development and production environments like this:
Dev:
NEXTAUTH_URL=http://localhost:3000
AZURE_AD_CLIENT_ID=dev-client-id
Prod:
NEXTAUTH_URL=https://yourdomain.com
AZURE_AD_CLIENT_ID=prod-client-id
This avoids mixing credentials between environments, which can break the authentication flow.
Step 2: Checked Azure Redirect URI
I verified the redirect URI in Azure App Registration:
https://yourdomain.com/api/auth/callback/azure-ad
Ensuring correct configuration here is essential for secure login flows.
Step 3: Fixed Nginx Configuration
This was the actual root cause in my case.
My Nginx reverse proxy was retrying failed requests automatically. This caused duplicate authentication requests, which is a known issue in production environments.
I updated the configuration:
location /api/auth/ {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_buffering off;
proxy_request_buffering off;
proxy_next_upstream off;
}
After this change, the duplicate requests stopped completely.
Step 4: Fixed Frontend Login Call
I ensured the login function was triggered only once:
signIn("azure-ad", { callbackUrl: "/" });
This is important in any modern authentication flow.
Step 5: Debugged with Logs
I added logs to confirm the behavior:
callbacks: {
async signIn() {
console.log("Sign-in triggered");
return true;
}
}
After fixing the proxy issue, the log appeared only once, confirming the fix.
What You Should Check First
If you are facing this issue in your application, check the following:
- Are authentication requests duplicated?
- Are environment variables correct?
- Is the redirect URI configured properly?
- Is your reverse proxy retrying requests?
These checks apply to most modern web applications using OAuth authentication and cloud identity providers.
Best Practices I Learned
After fixing this issue, I started following better practices for authentication and deployment:
- Keep development and production environments separate
- Use proper environment management in cloud deployments
- Monitor authentication logs carefully
- Configure reverse proxy settings properly
These practices are essential for building scalable and secure applications.
Conclusion
The AADSTS54005 error is not random. It always points to duplicate requests or incorrect configuration in your authentication system.
In my case, the issue was caused by reverse proxy retry behavior. Once I fixed that, the authentication flow worked perfectly.
If you are working on production-grade applications, especially in SaaS or enterprise environments, understanding this issue will save you a lot of debugging time.
Fix the root cause once, and your authentication system will become stable and reliable.