I’m running multiple n8n instances (dev / rec / prod) and using Microsoft Entra ID credentials to query Microsoft Graph (list chats by userId, chat members, etc.).
When I deploy a workflow from n8n-dev to n8n-rec, the workflow systematically fails on the first scheduled run with: “refreshToken is required” / ERR_ASSERTION.
The only way to recover is to manually open the credential and click “Reconnect” on the target instance. After a few hours or the next deploy, the issue comes back.
I suspect this is the combination of three known behaviors, but I’d like confirmation from the n8n team and best-practice guidance for a multi-environment setup.
What I think is happening
-
Credentials are not transferred with workflow exports. The workflow JSON only contains a credential reference (id + name), not the encrypted token blob. This is expected behavior.
-
Source Control & Environments explicitly excludes credentials. Per the official docs ( External secrets | n8n Docs ): “The feature doesn’t support using different credentials in different instances.”
-
Microsoft Entra uses refresh token rotation. Each refresh call invalidates the previous refresh_token and issues a new one. So if the same credential record exists on two instances (dev + rec), whichever instance refreshes first burns the other’s token, resulting in “refreshToken is required” on the second one. This is documented in issue #26453 ( Microsoft Outlook OAuth2 token refresh fails after ~1 hour on n8n Cloud, masked by dummy.stack.replace error · Issue #26453 · n8n-io/n8n · GitHub ): “Microsoft Entra ID replaces refresh tokens with a fresh token upon every use. If n8n doesn’t save the new refresh token, subsequent refresh attempts may fail.” It is also reproduced on the Entra ID node specifically in community thread #193787 ( Entra ID node reconnection issues ) and issue #14426 (Microsoft Entra Component auth failure. · Issue #14426 · n8n-io/n8n · GitHub).
The node is an HTTP Request node pointing to https://graph.microsoft.com/v1.0/users/{id}/chats with a Microsoft Entra ID (Azure Active Directory) API predefined credential type.
Workflow
WORKFLOW INPUT → LIST CHAT BY USERID (HTTP Request, Graph API, fails here) → SPLIT OUT LIST VALUE → LOOP OVER CHATS → FILTER CHAT BY TOPIC → if true: GET CHAT MEMBERS → USERS INFOS / if false: OFF TOPIC CHAT NAME → END OF LOOP.
Welcome @Rodolphe24 to our community! I’m Jay and I am a n8n verified creator.
Your root cause analysis is exactly right. Microsoft Entra ID uses refresh token rotation, so whichever environment calls the token endpoint first invalidates the token on the other. The fix is to treat each environment as a completely separate OAuth app - create a distinct App Registration in Azure for dev and another for rec, each with its own Client ID/Secret and its own redirect URI pointing to that environment’s n8n instance. Never share the same credential record across instances. Once you’ve set that up, each environment manages its own refresh cycle independently and the token invalidation stops.
Good morning @Rodolphe24
I would also avoid promoting workflows expecting the credential to go along with it. What I usually do in these scenarios is keep the same logical name for the credential across dev/rec/prod, but reconnect/create the credential locally on each instance using that environment’s App Registration. This way the workflow remains easy to promote via Source Control, but each environment maintains its own OAuth state and its own token refresh cycle. It’s also worth checking if the imported workflow is pointing to the correct credential in the target environment after the pull/deploy.
Thanks for the input — that’s actually the pattern I’m already running:
-
Same logical credential name across dev/rec/prod
-
Separate Azure App Registration per environment
-
Each credential reconnected locally on its own instance
After the deploy, the workflow does point to the correct credential on the target.Before publishing the workflow i’ve already launched it with success.That why i don’t understand…
@Rodolphe24
I would investigate two things: whether the credential is actually receiving a refresh token at the time of reconnection, especially with the correct offline_access/admin consent, and whether all containers/workers of the same instance use the same N8N_ENCRYPTION_KEY.
Hi , thank you for your feedback. Could this be related to an issue with an n8n worker? When I run the workflow manually, it works correctly. However, when I trigger the main workflow using a scheduler node after publishing it, I encounter a refresh token error.
Yes, this is almost certainly a worker issue. When a scheduled workflow runs via a worker, the worker needs the exact same N8N_ENCRYPTION_KEY as the main instance to decrypt stored credentials. If they differ, the token decryption fails and you get a refresh token error. Check your worker’s environment variables and confirm N8N_ENCRYPTION_KEY matches the main instance. Also make sure the worker has access to the same database where the credentials are stored - a worker connecting to a different DB won’t see the token at all.
ملاحظة حول خطأ refreshToken
أجريت عدة اختبارات متعلقة بخطأ refreshToken is required:
-
الاختبار 1:
على مثيل n8n-rec بأذونات القراءة فقط، يفشل تشغيل سير العمل برسالة الخطأ التالية:
refreshToken is required
-
الاختبار 2:
على مثيل n8n-rec بأذونات القراءة/الكتابة، يظهر سير العمل نفس الخطأ:
refreshToken is required
-
الاختبار 3:
بعد إعادة توصيل Microsoft Entra ID يدويًا على مثيل n8n-rec بأذونات القراءة/الكتابة، يتم تشغيل سير العمل بنجاح بدون أي خطأ.
الخطأ لا يحدث أبدًا في مثيل n8n-dev بأذونات القراءة/الكتابة، مع نشر أسفل العمل.
@Rodolphe24 تحليل اختبار رائع. نتيجة الاختبار 3 منطقية — عندما تعيد الاتصال بالبيانات الاعتمادية يدويًا على n8n-rec، تُصدر Microsoft رمز OAuth جديد يتضمن نطاق offline_access (مطلوب لرمز التحديث). من المحتمل أن البيانات الاعتمادية القديمة المخزنة في n8n-rec كانت تحتوي على رمز منتهي الصلاحية أو محدود النطاق من وقت إعدادها الأول.
النقطة الأساسية: إذا كان إعادة الاتصال على n8n-rec مع قراءة/كتابة يعمل، فإن البيانات الاعتمادية الأصلية كانت تفتقد نطاق offline_access. لتجنب تكرار هذا، تأكد من تفعيل هذا النطاق في Azure App Registration الخاص بك وأعد التفويض على كل مثيل بشكل منفصل.
- إنشاء تسجيل تطبيق منفصل في Azure: واحد للتطوير، وواحد للاختبار، وواحد للإنتاج.
- حقن إعدادات العميل الخاصة بك في حالات خادم n8n المختلفة باستخدام متغيرات البيئة القياسية:
MICROSOFT_CLIENT_ID
MICROSOFT_CLIENT_SECRET
MICROSOFT_TENANT_ID
- في عقدة HTTP Request، قم بتبديل نوع المصادقة إلى Generic Credential Type → OAuth2.
- في حقول إعدادات بيانات الاعتماد، استخدم تعبيرات n8n للإشارة إلى متغيرات البيئة الخاصة بك:
- معرّف العميل:
{{$env.MICROSOFT_CLIENT_ID}}
- سر العميل:
{{$env.MICROSOFT_CLIENT_SECRET}}
نظراً لأن n8n يقيّم متغيرات البيئة بشكل أصلي لكل حالة، فإن JSON سير العمل الخاص بك يبقى متطابقاً عبر التطوير والاختبار والإنتاج، لكن كل حالة تتواصل مع حاوية Azure معزولة خاصة بها.
أخبرني إذا كان هذا يناسبك، وإلا فلدي حل آخر.
حسنًا، شكرًا على ملاحظاتك، سأختبر ذلك.
مرحباً، شكراً على ملاحظاتك، لكن هذا غير ممكن لأنني اضطر إلى استخدام المصادقة المحددة بناءً على Microsoft Graph: Microsoft Entra ID (Azure Active Directory) API الذي يعتمد على oauth2 أيضاً
يسعدني أن تكون إجابتي مفيدة واختيرت كحل – هذا أدخل البهجة على يومي حقاً!
إذا واجهت أي أسئلة إضافية حول هذا الموضوع (أو إعدادات n8n أخرى)، فلا تتردد في التواصل معي، أنا سعيد بالبحث بشكل أعمق.
@Rodolphe24
بعد النشر، قبل النقر على “إعادة الاتصال”، هل بيانات اعتماد REC تحتوي على حالة OAuth صالحة وهي نفس بيانات الاعتماد المستخدمة من قبل التنفيذ المجدول؟
إذا كان ذلك ممكناً يرجى مشاركة طريقة النشر، وبنية REC (نسخة واحدة أو وضع الطابور/العمال/حاويات متعددة)، والدليل قبل إعادة الاتصال، وملف السجل الكامل لأول تنفيذ مجدول بعد النشر.
مرحبا بالجميع،
أعتذر عن التأخير في الرد، لقد كنت مشغولاً جداً في الآونة الأخيرة.
فقط لإغلاق النقاش حول هذا الموضوع: بعد ترقية n8n عبر عدة إصدارات أحدث، يبدو أن مشكلة رمز التحديث التي كنا نواجهها عند نقل سير العمل من بيئة n8n-dev إلى n8n-rec قد اختفت.
لم نتمكن من إعادة إنتاج المشكلة منذ الترقيات، لذا يبدو أنها قد تم إصلاحها في أحد الإصدارات الأحدث.
شكراً للجميع على مساعدتكم ورؤاكم طوال هذا النقاش.
مع أطيب التحيات