놀아 Account
Contents

Security checklist

Eight checks before you ship — why each one matters and what breaks if you skip it.

Look through this list before you ship. For each item, we explain why it matters and what happens if you skip it.

1. Keep client_secret on the server only

Why — The secret is the only value that proves “this request really came from that service.”

If you skip it — If you put it in front-end JS or a mobile app bundle, anyone can pull it out, and someone else can get tokens issued while pretending to be your service.

Do the token exchange (POST /oauth/token) always on your server. Don't commit it to your source repository; keep it in an environment variable or a secrets store.

2. Create a state, and always check it when it comes back

Why — It stops an attack (login CSRF) in which an attacker feeds their own authorization code into a victim's browser so that the attacker's account gets linked to the victim's account.

If you skip it — A user can end up signed in to the attacker's account without knowing it, or the other way around.

놀아 Account makes state required. But checking the value that comes back is your service's job. If you send it and never check it, it means nothing.

if (!hash_equals($_SESSION['nolaa_state'] ?? '', $_GET['state'] ?? '')) {
    // Stop. Do not go on to the token exchange
}

3. Keep the PKCE code_verifier in the session

Why — Even if an authorization code is intercepted along the way, it cannot be exchanged for tokens without the code_verifier.

If you skip it — If you carry it around in a cookie or a URL parameter, there is no point in using PKCE.

놀아 Account requires PKCE and accepts only S256. Create the code_verifier fresh for every request, store it in the server session, and delete it after you use it once.

4. Use redirect_uri only exactly as registered

Why — It is the address the authorization code will be delivered to. If this check is loose, codes go to the wrong place.

If you skip it — 놀아 Account rejects anything that does not match the registered value exactly, so sign-in simply fails. (That is safer than leaving it loosely open.)

Don't build redirect_uri from user input. Fix it as a constant.

5. Store tokens on the server, and don't send them down to the browser

Why — An access_token is, by itself, a key to read the user's information.

If you skip it — If you keep it in localStorage, a single XSS exposes everything.

Keep it in the server session, and send the browser only your own service's session cookie. Set HttpOnly, Secure and SameSite on the cookie.

6. Use HTTPS everywhere

Why — Authorization codes and tokens travel back and forth.

If you skip it — Anyone on the same network can intercept them in plain text.

Both the service URL and the callback URL must be https://.

7. When you get a 401, sign the user out quietly

Why — 놀아 Account has no public revoke endpoint, so 401 invalid_token is the only way your service can learn that the user has cleaned up the connection.

If you skip it — You keep sending requests over a connection that is already cut, and show error screens.

When you receive invalid_token, delete the stored token and send the user to the sign-in screen.

8. Request only the scopes you need

Why — The scopes you request appear on the consent screen as they are.

If you skip it — Asking for information you don't even use makes the consent screen longer and users drop off. And the information you receive comes with a duty to look after it.

Final check before you ship

  • Is client_secret absent from your repository and front-end code?
  • Are you checking state (not just sending it)?
  • Is code_verifier in the server session?
  • Is redirect_uri fixed as a constant?
  • Are tokens never exposed to the browser?
  • Is the callback on HTTPS?
  • Do you have handling for when you receive a 401?