Server-rendered web applications
The printer's website is the version of the printing application we have followed since the first lesson. You visit printer.example, sign in to your printer account, and each page arrives from the printer's servers already assembled. When you select Connect photo account, the redirect to the photo service, the callback, and the token request all pass through code that the printing company runs on its own backend.
That arrangement has a useful property. The OAuth client is the backend, the confidential client registered as photo-printer, and every token the photo service issues arrives in a direct response to it. Your browser carries the authorization request out and the code back, but it never needs to hold a token.
What the browser holds
After you sign in, the printer's response gives your browser one thing that matters here, the printer's own session cookie. Like every domain, token, and key in these examples, its value is fictional:
Set-Cookie: __Host-printer-session=demo-session-31; Path=/; Secure; HttpOnly; SameSite=Lax
These are the protections the Staying signed in lesson described. Secure keeps the cookie off unencrypted connections, HttpOnly keeps it out of reach of the page's scripts, SameSite=Lax limits when other sites can cause the browser to send it, and the __Host- prefix keeps it to printer.example alone.
The cookie identifies a printer session. It is not an access token, and the photo service would not recognize it. That matters when something goes wrong in the browser. A script injected into a printer page could misuse your printer session while the page is open, but it would find no access token or refresh token to carry away and use against the photo API from somewhere else, because none was ever sent to the browser.
The backend has to keep it that way. Tokens do not belong in the HTML it renders, in a script variable added for convenience, or in the response of an endpoint that the page calls. Once a token appears in a page, the website takes on the exposure of a browser application without any of the reasons for it.
Keeping tokens on the server
When the token response arrives, the backend saves it in a connection record: the printer's record of your photo account's connection, tied to your printer account rather than to the browser session that created it. A simplified record might look like this:
Connection: conn-5521
Printer account: your printer account
Authorization server: https://auth.photos.example
Client ID: photo-printer
Granted scope: photos.read
Access token: encrypted, expires 2026-10-01 09:10 UTC
Refresh token: encrypted
Status: active
Connected: 2026-10-01 09:00 UTC
The granted scope is the one the token response reported, which may be narrower than the printer requested. Tying the record to your printer account lets the connection outlive the visit that created it, and it makes the ownership rule easy to state: work done for one printer account must never be able to load another account's connection.
The refresh token is the valuable part. It can keep producing access tokens long after you have left, so the printer protects it like any other long-lived secret. The Refresh tokens and rotation lesson described how an authorization server can store refresh tokens as hashes, because it only needs to recognize one when it is presented. The printer cannot do that. It has to send the original value to the token endpoint, so it needs a form it can turn back into the token.
Instead, it encrypts the tokens before storing them, with a key held in a key management service rather than in the database or the application's configuration. A copy of the database then reveals nothing usable on its own, and only the components that call the photo API are allowed to ask for decryption. The same care applies wherever a token might pass. Request logs, error reports, analytics events, and support tools can record that a connection exists and whether it works, but never the tokens themselves.
Sessions and connections
Your printer session and your photo connection are now separate things, and they end in different ways:
| What happens | Printer session | Photo connection |
|---|---|---|
| You sign out of the printer | Ends | Stays active |
| You select Disconnect in the printer | Unaffected | Revoked, then deleted |
| You remove the printer at the photo service | Unaffected | Ended by the photo service |
Signing out ends the session. The printer invalidates its server-side session record and clears the cookie, as Staying signed in described, and leaves the connection alone. That is deliberate. You connected your photo account so the printer could prepare next December's calendar, and signing out of a shared computer at a library should not cancel that.
Disconnect is the action that ends the grant, by revoking the refresh token as the Token revocation lesson described. Removing the printer at the photo service ends the grant from the other side. Neither event touches your printer session, because the session was never what gave the printer access to your photos.
Work without a browser
In December, the calendar job runs on the printer's servers. Nobody is signed in, there is no browser, and there is no session cookie. All the job has is the connection record, and it works through it in order:
- Load the connection for the printer account whose calendar is due, and check that it is active.
- Decrypt the refresh token and send it to the token endpoint with the printer's client authentication.
- Save the replacement refresh token, if one is returned, before relying on the new access token.
- Request twelve recent photos from the photo API with the access token.
- If the token endpoint answers
invalid_grant, mark the connection as needing attention and send you a notice instead of retrying.
Steps 2 and 3 are the refresh token grant as you have already seen it, including the rule that only one refresh for a connection runs at a time.
The first step needs more care than it seems to. A background job usually receives its work from a queue, as a message such as "prepare the calendar for printer account 8812." It acts with whatever authority the connection record gives it, and no person is watching to notice a mistake. If a bug or a forged message could make the job load the wrong connection, it would print someone else's photos with entirely valid tokens. The job should find the connection through the printer account it is working for, rather than trusting a connection identifier carried in the message, and record which connection it used.
This is the comfortable case. The printing company runs the client on its own servers, keeps the tokens there, and gives your browser only a cookie that means nothing outside printer.example. The next lesson begins with an application that has no backend at all, and has to make the same decisions inside the browser.