ITMS-90034 แก้ Missing or invalid signature บน iOS
โดย Mehdi Azizi
เผยแพร่เมื่อ , 8 นาที
ITMS-90034 แปลว่า build ของคุณไม่ได้เซ็นด้วยใบรับรอง distribution ที่ใช้ได้ ตรวจลายเซ็นด้วย codesign แล้วสร้าง build แบบ store ใหม่ด้วย EAS
ITMS-90034 จะขึ้นตอนที่คุณส่ง build ไปยัง App Store Connect ข้อความนี้บอกว่าแอปของคุณ หรือส่วนประกอบใดส่วนหนึ่งของแอป ไม่ได้เซ็นด้วยใบรับรองสำหรับส่งแอปของ Apple (Apple submission certificate) ซึ่งก็คือใบรับรอง distribution ที่ยังใช้ได้ วิธีแก้คือ หาให้เจอว่า bundle ไหนเซ็นผิดและผิดเพราะอะไร แล้วสร้าง build ใหม่ที่เซ็นสำหรับ App Store
คู่มือนี้จะพูดถึงแค่ error ตัวนี้ ถ้าคุณยังไม่ค่อยเข้าใจคำว่าใบรับรองกับโปรไฟล์ แนะนำให้อ่าน ใบรับรองนักพัฒนา iOS และ provisioning profile ก่อน ในบทความนี้คุณจะได้รู้ว่าต้องอ่านข้อความตรงไหน มีแผนผังการตัดสินใจ มีคำสั่งสำหรับตรวจไฟล์ IPA และวิธีแก้ด้วยข้อมูลรับรองที่ EAS จัดการให้ ในส่วนของ EAS ผมไปอ่านโค้ดของ EAS CLI 24.10.0 ตรงส่วนที่เลือกใบรับรองมาแล้ว
error ITMS-90034 หมายความว่าอะไร?
หน้าตาปกติของมันเป็นแบบนี้ (ใช้ชื่อตัวอย่าง):
ITMS-90034: Missing or invalid signature. The bundle 'com.example.myapp' at bundle path 'Payload/MyApp.app' is not signed using an Apple submission certificate.
ในปี 2026 บนฟอรัมของ Apple ยังเจอในรูป "Validation failed (409) Missing or invalid signature" ตามด้วยข้อความเดียวกันและ "(ID: 90034)" ด้วย
"ใบรับรองสำหรับส่งแอป" ก็คือใบรับรอง distribution นั่นเอง หน้าช่วยเหลือของ Apple เรื่องใบรับรอง เขียนไว้ว่า ใบรับรอง development ใช้รันแอปบนอุปกรณ์ของคุณ ส่วนใบรับรอง distribution ใช้แจกจ่ายแอปหรือส่งไปยัง App Store Connect
อ่าน path ที่อยู่ในข้อความให้ดี เพราะมันชี้ไปที่ bundle ที่มีปัญหา Payload/MyApp.app หมายถึงตัวแอปเอง path ที่ลงท้ายด้วย .appex หมายถึง extension เช่น widget ส่วน path ที่ลงท้ายด้วย .framework หมายถึงไลบรารีที่ฝังอยู่ในแอป
นี่ไม่ใช่การปฏิเสธจาก reviewer การตรวจนี้ล้มตั้งแต่ตอนส่งหรือระหว่างประมวลผล build ก่อนถึง TestFlight build นี้จึงไม่มีวันไปถึงมือผู้ทดสอบของคุณ
แผนผังการตัดสินใจ: จากข้อความสู่วิธีแก้
แต่ละแถวคือเบาะแสที่คุณจะเห็นในข้อความ error ในคำสั่งของหัวข้อถัดไป หรือใน log ของ EAS ไล่ดูตามลำดับ แถวแรกที่ตรงคือทางที่คุณต้องไป
| สิ่งที่คุณเห็น | สาเหตุที่น่าจะเป็น | วิธีแก้ |
|---|---|---|
path ลงท้าย .appex | extension เซ็นผิด | ประกาศ extension |
Signature=adhoc | build ไม่ได้เซ็น | build ด้วยโปรไฟล์ store |
Apple Development | build แบบ development | build ด้วยโปรไฟล์ store |
อ่านเจอ ProvisionedDevices | build ภายใน (ad hoc) | build ด้วยโปรไฟล์ store |
sealed resource | IPA ถูกแก้หลังเซ็น | build ใหม่ |
| EAS: "no longer valid" | ใบรับรองถูกเพิกถอน | สร้างใบรับรองใหม่ |
| ทุกอย่างถูกต้อง | ปัญหาฝั่ง Apple | ส่งใหม่ แล้วแจ้ง Apple |
ตรวจ IPA ของคุณด้วย 4 คำสั่ง
ดาวน์โหลดไฟล์ IPA จากหน้า build บน expo.dev แล้วเปิด terminal บน Mac ของคุณ
1. ใครเป็นคนเซ็นแอป?
unzip -q MyApp.ipa -d ipa
codesign -dv --verbose=4 ipa/Payload/*.app 2>&1 | grep -E "^(Identifier|Authority|Signature|TeamIdentifier)="
codesign เขียนผลออกทาง standard error จึงต้องใส่ 2>&1 ตาม technote TN3161 ของ Apple แต่ละบรรทัด Authority คือห่วงหนึ่งในสายความเชื่อถือ (chain of trust) บรรทัดแรกต้องขึ้นต้นด้วย Apple Distribution: หรือ iPhone Distribution: ตามด้วยชื่อทีมของคุณ แบบที่สองเป็นชื่อของใบรับรองประเภท iOS Distribution รุ่นเก่า จากโค้ดของ EAS CLI 24.10.0 มันยังสร้างใบรับรองประเภทนี้อยู่ ถ้าคุณเห็น Apple Development: แปลว่าเป็น build แบบ development ถ้าเห็น Signature=adhoc โดยไม่มีบรรทัด Authority เลย แปลว่าไบนารีนี้ไม่ได้เซ็นด้วยใบรับรองใดเลย
2. แอปถูกแก้ไขหลังจากเซ็นหรือเปล่า?
codesign --verify --deep --strict -vv ipa/Payload/*.app
สิ่งที่คุณอยากเห็นคือ valid on disk ตามด้วย satisfies its Designated Requirement TN3161 อธิบายว่าการตรวจนี้รับประกันอะไร: ไฟล์ที่ควรมีอยู่ครบ ไม่มีไฟล์ไหนถูกเพิ่ม และไม่มีไฟล์ไหนถูกแก้ ผมลองกับ bundle ทดสอบที่เซ็นแล้วไปแก้ทีหลัง คำสั่งตอบกลับมาว่า a sealed resource is missing or invalid แล้วตามด้วย file modified: และชื่อไฟล์ที่ถูกแก้ ตัวเลือก --deep ในที่นี้ใช้สำหรับตรวจเท่านั้น ห้ามใช้ตอนเซ็น บนฟอรัมของ Apple วิศวกรของทีมซัพพอร์ตก็แนะนำว่าไม่ควรใช้มันเซ็น
3. โปรไฟล์ที่ฝังอยู่คืออะไร?
security cms -D -i ipa/Payload/*.app/embedded.mobileprovision -o profil.plist
plutil -extract ProvisionedDevices xml1 -o - profil.plist
plutil -extract ExpirationDate raw profil.plist
นี่คือคำสั่งจาก technote TN3125 เรื่องโปรไฟล์ โปรไฟล์ App Store จะไม่มีรายชื่ออุปกรณ์ บรรทัดที่สองจึงต้องตอบว่า Could not extract value ถ้ามันแสดง ID ของอุปกรณ์ออกมา แปลว่าเป็นโปรไฟล์ ad hoc ของ build ภายใน ส่วนบรรทัดที่สามจะบอกวันหมดอายุของโปรไฟล์
4. extension และ framework เซ็นเหมือนกันหรือเปล่า?
find ipa/Payload/*.app \( -name "*.appex" -o -name "*.framework" \) \
-exec sh -c 'echo "$1"; codesign -dvv "$1" 2>&1 | grep -m1 "^Authority="' _ {} \;
ทุกส่วนประกอบต้องแสดงบรรทัด Authority เหมือนกับตัวแอป ถ้ามีตัวไหนไม่ตรง ตัวนั้นแหละคือตัวที่ข้อความ error พูดถึง
ถ้าอยากตรวจก่อนส่ง TN3161 แนะนำ altool ซึ่งตรวจแบบเดียวกับปุ่ม Validate App ใน Xcode ต้องใช้ API key ของ App Store Connect โดยเก็บไฟล์ AuthKey_<ID_CLE>.p8 ไว้ใน ~/.appstoreconnect/private_keys:
xcrun altool --validate-app -f MyApp.ipa -t ios --api-key <ID_CLE> --api-issuer <ID_EMETTEUR>
แก้ด้วย EAS ทีละสาเหตุ
ส่ง build ภายในหรือ build แบบ development ไปให้ Apple
ตามเอกสารของ Expo เรื่อง eas.json build ที่ตั้ง "distribution": "internal" ไม่ได้เซ็นสำหรับ store แต่ใช้โปรไฟล์ ad hoc มีแค่โปรไฟล์ที่ตั้ง distribution เป็น store (ค่าเริ่มต้น) เท่านั้นที่ได้ build ซึ่งส่งได้ วิธีที่ปลอดภัยที่สุดคือส่ง build ที่คุณเพิ่ง build เสร็จ โดยไม่ต้องเลือกเอง:
eas build --platform ios --profile production --auto-submit
ถ้าคุณใช้ eas submit --path ให้เช็กว่าไฟล์นั้นคือ build แบบ store ล่าสุดจริงๆ บนฟอรัมของ Apple มีทีมหนึ่งเพิ่งมารู้ว่าเครื่องมือส่งของพวกเขาส่ง IPA เก่าที่เก็บไว้ใน git ทุกครั้ง
ลืม extension
extension แต่ละตัวเป็น bundle แยก มี identifier และโปรไฟล์ของตัวเอง ในโปรเจกต์ Expo ที่ใช้การสร้างโค้ด native อัตโนมัติ หน้าของ Expo เรื่อง extension บน iOS ให้ประกาศไว้ใน extra.eas.build.experimental.ios.appExtensions แล้ว EAS CLI จะรู้จักมันตั้งแต่ก่อน build และสร้างหรือตรวจข้อมูลรับรองให้ ไลบรารีส่วนใหญ่ที่เพิ่ม extension จะเขียนการประกาศนี้ให้คุณผ่าน plugin ของมัน
Solys แอปนาฬิกาปลุกมินิเกมของผม มี extension อยู่ 4 ตัว: widget หนึ่งตัว และ extension ของ Screen Time อีกสามตัว ทั้งสี่ตัวประกาศไว้ใน config และ EAS มีโปรไฟล์ให้ทุกตัว extension ที่เพิ่มเองใน Xcode โดยไม่ได้ประกาศไว้ คือผู้ต้องสงสัยอันดับหนึ่ง เมื่อข้อความ error มี path ลงท้าย .appex
ใบรับรองถูกเพิกถอนหรือหมดอายุ
หน้าของ Apple เรื่องใบรับรอง เขียนชัดเจนว่า คุณส่ง build ที่เซ็นด้วยใบรับรองที่หมดอายุหรือถูกเพิกถอนไม่ได้ build ที่ส่งไปแล้วแต่ยังไม่ได้ส่งรีวิว ยังอาจกลายเป็นสถานะ Invalid Binary ได้ด้วยถ้าใบรับรองของมันถูกเพิกถอน
โค้ดของ EAS CLI 24.10.0 แสดงให้เห็นว่ากรณีไหนที่ปัญหานี้หลุดรอดไปได้:
- build แบบ interactive ที่ล็อกอิน Apple ไว้: EAS จะเทียบใบรับรองของมันกับใบรับรองที่ยังใช้ได้ฝั่ง Apple ถ้าไม่เจอ จะขึ้นว่า "Current distribution certificate is no longer valid in Apple Dev Portal" แล้วให้คุณเลือกหรือสร้างใบใหม่
- build แบบ interactive ที่ไม่ได้ล็อกอิน: EAS ตรวจแค่วันที่ และเตือนว่าข้ามการตรวจฝั่ง Apple ไป
- build แบบ non-interactive ใน CI: EAS จะขึ้นว่า "Distribution Certificate is not validated for non-interactive builds" แล้วก็เซ็นต่อไปอยู่ดี
ใน CI นั้น EAS ไม่ได้ตรวจตัวใบรับรองซ้ำ การเพิกถอนจึงอาจไปโผล่ตอนส่งเท่านั้น วิธีแก้: รัน build แบบ interactive ที่ล็อกอินบัญชี Apple ไว้ หรือใช้ eas credentials --platform ios เข้าเมนู Build Credentials แล้วเลือก "Distribution Certificate: Add a new one to your account" โปรไฟล์ที่มีใบรับรองเก่าจะใช้ไม่ได้ EAS จะตรวจและสร้างใหม่ให้ใน build ถัดไป ข้อจำกัดของ Apple เรื่องจำนวนใบรับรองอธิบายไว้ในคู่มือเรื่องใบรับรองนักพัฒนา iOS
ไบนารีถูกแก้หลังจากเซ็น
ลายเซ็นจะผนึกโค้ด ทรัพยากร และ metadata ไว้ด้วยค่า hash ตามที่ technote TN3126 ของ Apple อธิบาย การแตกไฟล์ IPA เพื่อแก้ไฟล์แล้วบีบอัดกลับจะทำให้ผนึกนี้เสีย ให้แก้ใน config ของคุณ แล้ว build ใหม่ อย่าไปแก้ IPA ที่ EAS สร้างให้เด็ดขาด
ตรรกะเดียวกันใช้กับโค้ดที่วางไว้ผิดที่ เช่นอยู่ในไฟล์ .zip: App Store เซ็นมันใหม่ไม่ได้ Apple อธิบายตำแหน่งที่อนุญาตไว้ในหน้าการวางเนื้อหาใน bundle
ข้อมูลรับรองแบบ local
ถ้าโปรไฟล์ EAS ของคุณใช้ "credentialsSource": "local" ไฟล์ credentials.json จะชี้ไปที่ใบรับรอง .p12 และโปรไฟล์ .mobileprovision ให้ตรวจโปรไฟล์ด้วยคำสั่งในขั้นที่ 3: มันต้องเป็นประเภท App Store และมีใบรับรอง distribution ตัวปัจจุบันของคุณอยู่ และอย่าเก็บไฟล์พวกนี้ไว้ใน repo เช่นเดียวกับ API key ของแอป Expo
เมื่อทุกอย่างถูกต้องหมด
ยังมีอีกกรณีที่น่าหงุดหงิด บนฟอรัมของ Apple มีนักพัฒนาที่ error หายไปเองเมื่อส่ง build เดิมซ้ำโดยไม่ได้แก้อะไรเลย ในเดือนสิงหาคมและกันยายน 2026 มีสองกระทู้ที่เจอกลับกัน: ใบรับรองและโปรไฟล์ใหม่ ลายเซ็นตรวจแล้ว แต่ยังล้มเหมือนเดิม ในกระทู้หนึ่ง วิศวกรของ Apple แนะนำให้ส่งรายงานบั๊กพร้อม IPA ผลวิเคราะห์ลายเซ็น และ log ของ Transporter แล้วติดต่อ App Store Connect
ดังนั้นให้ส่งใหม่หนึ่งครั้งพร้อมเลข build ใหม่ ถ้า error ยังกลับมาทั้งที่ 4 คำสั่งของคุณผ่านหมด ให้แจ้ง Apple พร้อมข้อมูลเหล่านี้ อย่าเพิกถอนใบรับรองเพราะความเคยชิน มันไม่ได้แก้อะไรเพิ่ม แถมทำให้โปรไฟล์ของคุณใช้ไม่ได้
ส่ง build โดยไม่เจอเรื่องไม่คาดฝัน
ลายเซ็นตรวจได้ในสองนาทีก่อนส่ง การตรวจอัตโนมัติอื่นๆ ก็ต้องรอบคอบแบบเดียวกัน เช่น ITMS-90725 เรื่องเวอร์ชัน Xcode หรือ ITMS-90683 เรื่องข้อความขอสิทธิ์ ขั้นตอนครบตั้งแต่ build จนถึงส่งโดยไม่ต้องมี Mac อยู่ในเผยแพร่แอป iOS โดยไม่มี Mac
การถูก reviewer ปฏิเสธต้องใช้มุมมองที่กว้างกว่านี้ วิธีรับมืออยู่ในหน้าแอปถูก Apple ปฏิเสธ และเหตุผลที่เจอบ่อยที่สุดอยู่ในทำไม Apple ปฏิเสธแอป
ถ้าอยากตรวจความพร้อมก่อนส่ง Review Kit รวม checklist ของผมกับ skill ของ Claude Code ที่ช่วยอ่านทวนโปรเจกต์ของคุณ ถ้าการส่งติดขัดและอยากให้คนช่วยดู จองเวลาหนึ่งชั่วโมงกับผม เราจะดูโปรเจกต์ของคุณผ่านวิดีโอคอลบนหน้าจอของคุณเลย และถ้าคุณกำลังเตรียมปล่อยแอปแรก ทำแบบประเมินฟรี มันจะเรียงขั้นตอนให้เป็นลำดับ และส่ง checklist กันโดน Apple ปฏิเสธของผมให้คุณ
คำถามที่พบบ่อย
ITMS-90034 คือการถูก App Review ปฏิเสธหรือเปล่า?
ไม่ใช่ครับ มันคือการตรวจอัตโนมัติตอนส่ง build ก่อน TestFlight และก่อนการรีวิวใดๆ ไม่มีใครเปิดแอปของคุณ Apple แค่พบว่าลายเซ็นของมันไม่ได้มาจากใบรับรอง distribution ที่ใช้ได้
ต้องเพิกถอนใบรับรอง distribution เพื่อแก้ ITMS-90034 ไหม?
เฉพาะเมื่อใบรับรองรั่วไหลหรือใช้ไม่ได้อยู่แล้วเท่านั้น การเพิกถอนใบรับรองที่ยังใช้ได้จะทำให้โปรไฟล์ใช้ไม่ได้โดยไม่ได้แก้ต้นเหตุ เริ่มจากอ่านลายเซ็นของ IPA ด้วย codesign แล้วแก้ตามที่แผนผังการตัดสินใจชี้
แก้ ITMS-90034 ด้วยการอัปเดตแบบ OTA ได้ไหม?
ไม่ได้ครับ ลายเซ็นเป็นส่วนหนึ่งของไบนารี และ build ที่ถูกปฏิเสธจะใช้ไม่ได้ตลอดไป คุณต้องสร้างไบนารีใหม่ที่เซ็นถูกต้องแล้วส่งใหม่
ทำไม error ถึงพูดถึง widget ไม่ใช่ตัวแอป?
เพราะ widget เป็น bundle แยก เซ็นด้วยโปรไฟล์ของตัวเอง ถ้ามันไม่ได้ประกาศให้ EAS รู้ หรือถูกเซ็นด้วยวิธีอื่น มันจะทำให้การส่งทั้งหมดล้ม ให้ประกาศ extension ไว้ใน config แล้ว build ใหม่
ถ้า codesign บอกว่าทุกอย่างถูกต้องแล้วต้องทำอย่างไร?
ตรวจโปรไฟล์ที่ฝังอยู่และ extension ทุกตัวด้วย ถ้าทุกอย่างเรียบร้อย ให้ส่งใหม่หนึ่งครั้งพร้อมเลข build ใหม่ ถ้า error ยังอยู่ ให้ส่งรายงานถึง Apple พร้อม IPA ผลลัพธ์ของ codesign และ log การส่ง

