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.

Bench Note: The Pi 5's Broadcom BCM4345 WiFi chip is highly sensitive to WPA2/WPA3 transition modes on modern mesh routers (like Eero or TP-Link Deco). If your router is set to 'WPA2/WPA3 Transitional', the Pi 5 will often fail the 4-way handshake and default to an authentication error. Forcing the router to WPA2-only or WPA3-only (SAE) usually resolves this instantly.

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.

  1. 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 than throttled=0x0, your power is marginal.
  2. 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.
  3. 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=shared or explicitly store the PSK in the connection file using wifi-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.