In the authorization code flow the app never sees the password. It opens the provider's login page in the system browser (a Chrome 1 Custom Tab on Android, ASWebAuthenticationSession on iOS), the provider redirects to the app's URL with a one-time code, and the app trades the code for tokens. PKCE (RFC 7636) stops another app registered for the same URL scheme from using a stolen code: the app invents a random code verifier and sends only its SHA-256 hash, the code challenge:

A thief who intercepts step 3 lacks the verifier, so step 4 fails. useAuthRequest() does the app's half: it creates the verifier, challenge and state (a random value that must come back unchanged), builds the URL, and returns promptAsync(), which opens the browser:
const discovery = useAutoDiscovery(issuer); // GET /.well-known/openid-configuration
const [request, response, promptAsync] = useAuthRequest(
{ clientId, redirectUri, scopes: ['profile', 'orders'] }, // PKCE is on by default
discovery,
);
useEffect(() => {
if (response?.type !== 'success' || !request?.codeVerifier || !discovery) return;
exchangeCodeAsync({ clientId, redirectUri, code: response.params.code,
extraParams: { code_verifier: request.codeVerifier } }, discovery)
.then((t) => signIn(toTokens(t)))
.then(() => router.replace('/checkout'))src/auth/config.ts sets clientId ('booknest-app'), issuer (the practice API) and redirectUri, makeRedirectUri({ scheme: 'booknest', path: 'redirect' }), which is booknest://redirect. The button calls promptAsync(). RFC 8252 recommends a scheme based on a domain you own, such as com.example.booknest, because nothing stops another app from claiming booknest://; PKCE makes such a collision harmless.