Codes, links, and approval prompts
Another way to sign in
After entering a password at Cedar Inc., Alex is asked for a code. On another site, Alex can sign in by clicking a link sent by email. Both methods rely on a short-lived secret, but the way Alex receives it and the checks the service performs can differ.
Delivered codes and links
For a text-message code, the service sends a temporary secret to the phone number Alex registered earlier. Alex types that code into the sign-in page. A correct code shows access to messages sent to that number at that moment. It does not prove that Alex alone controls the number or phone.
That distinction matters because phone numbers can be reassigned and an attacker can sometimes move a number to another SIM. A message can also be seen by someone other than its intended recipient.
An email code depends on access to Alex's mailbox. A magic link works similarly, except the secret is part of a link that the service checks when Alex opens it. Someone who can read or forward Alex's mail may be able to use either method.
A delivered code or link should work only for its intended account, purpose, and short time window. Once used, it must not work again, even if two requests arrive together. Email services sometimes open links automatically to scan them, so merely fetching a magic link should not unexpectedly sign Alex in or consume it.
Authenticator-app codes
An authenticator app generates codes without waiting for a new message. During enrollment, the service and app receive the same secret, often through a QR code. If someone copies that enrollment code, they may be able to generate Alex's future sign-in codes too.
Time-based one-time passwords (TOTP) use the shared secret and the current time to calculate a short code. The service calculates the expected code independently. In the next lesson, public-key methods will work differently: the service will not hold the private key that produces the response.
Because clocks can differ slightly, the service may accept codes within a small time window. It also limits guesses and must not accept a code again after a successful use. If Alex types a current code into a fake site, however, someone can relay it to the real service before it expires. A changing code is still something a phishing page can ask for.
Approval prompts
Instead of asking Alex to type a code, a service can send an approval request to an enrolled app. The response must come from that app and belong to the sign-in attempt Alex is completing.
If someone else starts a sign-in with Alex's password, Alex might receive a prompt without expecting one. Repeated prompts can wear people down. Number matching and details about the request can help Alex notice a mismatch, but they cannot stop someone from approving a request they did not start.
Alex should deny an unexpected prompt and investigate through a trusted route. If the request is denied, expires, or cannot reach the app, the sign-in attempt has not succeeded.
Following a code
Here is a simulated request for a delivered code. The address and values are fictional; the example does not send a real request.
POST https://login.cedar.example/sign-in/verify-code
Content-Type: application/json
{"attempt_id":"example-attempt","code":"000000"}
HTTP/1.1 400 Bad Request
Content-Type: application/json
{"error":"Code could not be accepted. Start a new attempt."}
Suppose those digits match a code sent earlier, but the sign-in attempt has expired. The response rejects it. Matching digits alone would not be enough; the service also needs to check:
| Check | Why it matters |
|---|---|
| Account and purpose | A recovery code must not accidentally become a sign-in or email-change approval. |
| Pending attempt | Evidence must complete the intended interaction. |
| Lifetime and unused state | An expired or consumed secret must fail, including concurrent reuse. |
| Guess limits | A short code has a small search space and needs abuse controls. |