If you are setting up a Raspberry Pi 5 and hit an endless loop prompting for a password, or your headless boot fails to connect, you are likely staring at the "Authentication required by Wi-Fi network" GUI popup, or the CLI equivalent: Error: Connection activation failed: Secrets were required, but not provided.
The direct answer: This error on the Pi 5 is almost exclusively caused by the OS-level shift from wpa_supplicant to NetworkManager in Raspberry Pi OS Bookworm, combined with WPA3-SAE router transition modes or headless permission mismatches. The legacy wpa_supplicant.conf drop-in method is completely ignored on the Pi 5.
This guide targets the Raspberry Pi 5 (8GB variant) running Raspberry Pi OS Bookworm (64-bit). We will cover the exact nmcli commands to bypass the GUI, hardware debug pinouts for headless recovery, and a complete Python diagnostic script to monitor connection states via GPIO.
The Bookworm Shift: Why You See the Authentication Error
For years, Raspberry Pi users relied on dropping a wpa_supplicant.conf file into the boot partition to configure headless WiFi. With the release of the Pi 5 and Bookworm, the networking stack was overhauled. NetworkManager is now the default. If you attempt to use the old configuration files, the system simply ignores them, resulting in a state where the WiFi interface (wlan0) is up, but no security credentials are bound to the SSID.
When you try to connect via the desktop GUI without a properly configured NetworkManager profile, it throws the "Authentication required by Wi-Fi network" dialog. If you are SSH'd in via Ethernet or UART and use legacy commands, you will see the "Secrets were required" fatal error.
The First Three Things to Check When WiFi Fails
Before rewriting your network stack, verify these three physical and configuration baselines. I see these trip up even experienced makers migrating from Pi 4 to Pi 5.
- Verify the 27W USB-C PD Power Supply: The Pi 5 requires a 5V/5A (27W) USB-C PD power supply to maintain full peripheral power. If you use a standard 5V/3A phone charger, the Pi 5 will limit USB current and occasionally brownout the WiFi chip during the high-current TX burst of the WPA handshake. Check
vcgencmd get_throttled. If it returns anything other thanthrottled=0x0, your power is marginal. - Check Router WPA3-SAE Transition Modes: As mentioned, the Pi 5 struggles with transitional security modes. Log into your router and set the 2.4GHz or 5GHz band to strict WPA2-PSK (AES) or strict WPA3-SAE. Do not use 'Mixed' or 'Transitional' modes for the Pi's specific SSID.
- Confirm NetworkManager Permissions (Headless): If you created a NetworkManager connection profile using
sudo, the WiFi password (PSK) is stored in the root keyring. When your standard user (e.g., 'pi') tries to activate it, NetworkManager blocks access to the secret, throwing the authentication error. You must pass the--mode=sharedor explicitly store the PSK in the connection file usingwifi-sec.psk-flags=0.
NetworkManager Translation: Legacy vs. Modern Commands
To fix the authentication error via the command line, you must speak NetworkManager's language using nmcli. Here is the exact translation from the legacy wpa_supplicant workflow to the modern Bookworm workflow. Keep this table on your second monitor while debugging.
| Task | Legacy Method (Deprecated on Pi 5) | NetworkManager Method (Bookworm / Pi 5) | Exact Command / File Path |
|---|---|---|---|
| Config File Location | /boot/firmware/wpa_supplicant.conf |
/etc/NetworkManager/system-connections/ |
sudo nano /etc/NetworkManager/system-connections/MySSID.nmconnection |
| Scan for Networks | sudo iwlist wlan0 scan |
nmcli device wifi list |
nmcli -f SSID,SIGNAL,SECURITY dev wifi list |
| Connect to WPA2 | Auto via supplicant conf | nmcli device wifi connect |
nmcli dev wifi connect 'MySSID' password 'MyPass' --ask |
| Fix Headless Auth Error | N/A | Set PSK flags to 0 | nmcli con mod 'MySSID' wifi-sec.psk-flags 0 |
| Disable MAC Randomization | N/A | Set cloned-mac-address | nmcli con mod 'MySSID' wifi.cloned-mac-address preserve |
If you are stuck in the authentication loop, delete the broken profile and recreate it with explicit PSK flags:
sudo nmcli connection delete 'MySSID'
sudo nmcli dev wifi connect 'MySSID' password 'YourPasswordHere'
sudo nmcli connection modify 'MySSID' wifi-sec.psk-flags 0
sudo nmcli connection up 'MySSID'
Hardware Debugging: UART and GPIO Pin Mapping
When the WiFi authentication fails on a headless Pi 5, you lose SSH access. You need a hardwired backdoor. The Pi 5 exposes UART0 on the standard 40-pin header, allowing you to bypass the network entirely and fix the nmcli configuration via a serial console.
Below is the pin mapping for UART recovery and a GPIO status LED we will use in the Python script below.
| Function | BCM GPIO Pin | Physical Pin (40-pin Header) | Wire Color (Standard) | Notes / Constraints |
|---|---|---|---|---|
| UART0 TXD | GPIO 14 | Pin 8 | Yellow | Connect to USB-TTL adapter RX |
| UART0 RXD | GPIO 15 | Pin 10 | Orange | Connect to USB-TTL adapter TX |
| Ground (UART) | N/A | Pin 6 | Black | Common ground with adapter |
| WiFi Status LED | GPIO 21 | Pin 40 | Green | Use 330Ω resistor to LED anode |
| LED Ground | N/A | Pin 39 | Black | Connect to LED cathode |
Required Hardware: Raspberry Pi 5 (8GB), Official 27W USB-C PD Power Supply, Adafruit USB to TTL Serial Cable (PL2303HX), 5mm Green LED, 330Ω resistor, jumper wires.
Python WiFi Diagnostic Script with GPIO Feedback
To automate the monitoring of the WiFi authentication state without constantly polling nmcli manually, we can write a Python script. This script uses subprocess to query NetworkManager, parses the exact error strings, and drives the GPIO 21 LED to indicate status (Solid = Connected, Fast Blink = Auth Error, Slow Blink = Disconnected).
Board Target: Raspberry Pi 5 (8GB) running Bookworm 64-bit.
Dependencies: sudo apt install python3-gpiozero
#!/usr/bin/env python3
"""
Pi 5 NetworkManager WiFi Diagnostic Monitor
Monitors wlan0 state and provides GPIO 21 LED feedback.
"""
import subprocess
import time
import sys
from gpiozero import LED
# --- PIN DEFINITIONS ---
STATUS_LED_PIN = 21
status_led = LED(STATUS_LED_PIN)
def get_wifi_status():
"""Queries NetworkManager for active WiFi connection and security state."""
try:
# -t for terse (machine readable), -f for specific fields
cmd = ['nmcli', '-t', '-f', 'ACTIVE,SSID,SECURITY', 'dev', 'wifi']
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
for line in result.stdout.strip().split('\n'):
if not line:
continue
parts = line.split(':')
if len(parts) >= 3 and parts[0] == 'yes':
return 'CONNECTED', parts[1]
# Check if interface is disconnected or failing auth
cmd_state = ['nmcli', '-t', '-f', 'STATE', 'dev', 'show', 'wlan0']
state_res = subprocess.run(cmd_state, capture_output=True, text=True, check=True)
state = state_res.stdout.strip().split(':')[1] if ':' in state_res.stdout else 'unknown'
if state == 'disconnected':
# Check for the specific auth failure in journal or nmcli general
return 'AUTH_FAILED', None
return 'DISCONNECTED', None
except subprocess.CalledProcessError as e:
print(f'nmcli error: {e.stderr}')
return 'ERROR', None
except Exception as e:
print(f'Unexpected error: {e}')
return 'ERROR', None
def blink_led(pattern='slow'):
"""Blinks the GPIO 21 LED based on state."""
if pattern == 'fast':
status_led.blink(on_time=0.1, off_time=0.1, n=2, background=False)
elif pattern == 'slow':
status_led.blink(on_time=0.5, off_time=0.5, n=1, background=False)
else:
time.sleep(1)
def main():
print('Starting Pi 5 WiFi Diagnostic Monitor on GPIO 21...')
try:
while True:
state, ssid = get_wifi_status()
if state == 'CONNECTED':
print(f'[OK] Connected to {ssid}')
status_led.on()
time.sleep(5)
elif state == 'AUTH_FAILED':
print('[FAIL] Authentication required by Wi-Fi network / Secrets missing.')
blink_led('fast')
elif state == 'DISCONNECTED':
print('[WARN] wlan0 disconnected. Scanning...')
blink_led('slow')
else:
print('[ERR] Interface error or nmcli unavailable.')
blink_led('slow')
except KeyboardInterrupt:
print('\nMonitor stopped.')
status_led.off()
sys.exit(0)
if __name__ == '__main__':
main()
Error Handling Note: The script catches subprocess.CalledProcessError. If NetworkManager is completely crashed (which can happen if the /etc/NetworkManager/system-connections/ directory has malformed file permissions), nmcli will throw a non-zero exit code, and the script will safely default to the 'ERROR' state rather than crashing the loop.
Extending and Simplifying the Build
How to Simplify
If you do not want to manage nmcli commands or Python scripts, the simplest way to avoid the authentication error on a fresh Pi 5 is to use the Raspberry Pi Imager on your desktop PC before flashing the SD card. In the Imager's 'OS Customisation' menu (the gear icon), enter your SSID and password. The Imager correctly generates the Bookworm-compliant NetworkManager profile and injects it into the image, completely bypassing the headless authentication trap.
How to Extend
For remote deployments (e.g., a Pi 5 running a 3D printer farm or environmental sensors in a shed), extend the Python script above by adding an MQTT publisher. Instead of just blinking the GPIO 21 LED, have the script publish homeassistant/sensor/pi5_wifi/state with the exact nmcli error string. This allows you to receive an alert on your phone the moment the Pi 5 drops off the network due to a router-side WPA3 handshake failure, rather than discovering it hours later when your OctoPrint or Home Assistant dashboard goes offline.
For deeper network analysis, reference the official NetworkManager CLI documentation to explore nmcli monitor, which streams real-time state changes directly to your terminal, making it invaluable for catching the exact millisecond a WPA handshake times out.






