How does code authenticate to a password protected tag?
By sending the chip's authentication command with the password, checking the chip's answer, and only then reading or writing the protected pages, all on the same connection. The authentication lasts at most as long as the tag stays powered, so each new connection starts without it. The command itself belongs to the chip, not to the tag type.
The sequence
A password protected tag refuses the protected operations until it receives the right password, on the chips that offer one; the setting and its scope are covered on the password page. The code's side is a short sequence on a single connection.
It connects, with NfcA on Android or through a tag session on iOS, and sends the chip's authentication command with the password, through transceive() or sendMiFareCommand. It checks the answer: on the NTAG21x family, the 32 bit password comes with a 16 bit acknowledgement, PACK, according to the NTAG213 fiche on wakdev.com, and code compares the acknowledgement it receives with the one it configured. Only then does it read or write the protected pages, before closing.
The command is not part of any tag type. Its code and format belong to the chip, and NTAG21x, MIFARE Ultralight C, ICODE SLIX and NTAG 424 DNA each have their own; the chip fiches on wakdev.com link to the datasheets that define them. On ISO/IEC 15693 chips that have passwords, the commands that handle them sit in the custom command range, as the ISO/IEC 15693 page explains.
What ends the authentication
A passive tag draws its power from the reader's field, as the powering page explains, and an authentication is state held in the chip. It ends at the latest when the tag leaves the field; the chip's datasheet says which other events end it.
So a retry starts from the beginning. After TagLostException on Android or readerTransceiveErrorTagConnectionLost on iOS, the tag that comes back is unauthenticated, and code that resumes with the protected write gets a refusal. The same holds for a new tag session on iOS, and for the new Tag object Android creates each time the tag comes back into range.
Keep the authentication and the operations it unlocks on one connection and one technology class. Opening another class can make Android reselect the tag: in the open source stack, the connection code can do so on ISO-DEP and MIFARE Classic tags, when the new class needs another interface of the controller, and does nothing on a Type 2 tag. Whether a reselect ends the authentication is set by the chip's datasheet, and a phone maker's stack can decide differently, so staying on one class is the choice that holds on every phone.
Where the password lives
The code sends the password, so it has to hold it. A single password compiled into an app is in every copy of the app, and whoever extracts it can rewrite every tag it protects. A password per tag moves the problem to a table the app fetches, the record the password page calls a database you must not lose.
A password is also short. The NTAG21x password is 32 bits, and some chip families limit failed attempts, a setting the password page recommends enabling where it exists.
None of this authenticates the tag to the app. A copy of the content carries no password, as the password against authentication page explains, so an app that needs to know whether a tag is genuine needs a chip that answers a cryptographic challenge.
What the platform APIs do not do
Neither platform's NDEF API takes a password. Ndef.writeNdefMessage() on Android and writeNDEF on iOS write to a tag that accepts writing, and on a protected tag they fail like any refused write, the failure the protection error page describes from the user's side.
The dependable course is to authenticate with a raw command and write the protected pages with raw commands too, which means building the NDEF bytes and writing them in a safe order, as the interrupted writes page describes. Web NFC offers neither step.
Frequently asked questions
Can Ndef.writeNdefMessage write to a password protected tag?
Not by itself. The NDEF APIs take no password, so authenticate with a raw command first and write on the same connection, with raw commands to be safe.
Why does my write fail after a retry?
The tag left the field and came back unauthenticated. Send the authentication command again before the protected operations.
Does the password protect the content from being read?
Only on chips and settings that protect reading. Most configurations protect writing alone, as the password page explains.
Can an app keep the password secret?
Not from someone who extracts it from the app. Any app that authenticates holds the password it sends, so treat it as a lock against casual rewriting.