Logout and Token Cleanup
Two different logouts
When a user clicks “Log out” on your app, what should happen? There are two layers:
- Your app’s session: The cookie and server-side session record you created
- The provider’s access token: The token GitHub or Google issued during the OAuth flow
These are independent. Logging out of your app does not log the user out of GitHub. Revoking the access token does not destroy your app’s session.
Logging out of your app
This is the same as the auth course. Delete the session and clear the cookie:
// src/routes/auth.ts
import { route, group } from "@hectoday/http";
import { getSessionId, clearSessionCookie } from "../cookies.js";
import { deleteSession } from "../sessions.js";
export const authRoutes = group([
route.post("/logout", {
resolve: (c) => {
const sessionId = getSessionId(c.request);
if (sessionId) {
deleteSession(sessionId);
}
return Response.json(
{ message: "Logged out" },
{
status: 200,
headers: { "set-cookie": clearSessionCookie() },
},
);
},
}),
]); Add ...authRoutes to your app’s routes array. After logout, the user’s session cookie is cleared and the session is gone. They need to go through the OAuth flow again to log in.
Should you revoke the access token?
When the user logs out, should you also revoke the access token that GitHub or Google issued?
In most cases, no. The access token was used during the login flow to fetch the user’s profile. Unless you are storing it to make ongoing API calls (like reading the user’s repos or calendar), it has already served its purpose.
If you do store the token for ongoing API access, you should revoke it when the user disconnects their account (not necessarily when they log out). “Disconnect GitHub” is different from “Log out.”
Revoking a GitHub token
GitHub does not have a standard revocation endpoint for OAuth tokens. To revoke a token, you call a GitHub API endpoint:
await fetch(`https://api.github.com/applications/${clientId}/token`, {
method: "DELETE",
headers: {
authorization: `Basic ${btoa(`${clientId}:${clientSecret}`)}`,
"content-type": "application/json",
"user-agent": "oauth-course",
},
body: JSON.stringify({ access_token: token }),
}); This uses HTTP Basic auth with your client ID and secret. It is a server-to-server call.
Revoking a Google token
Google has a standard revocation endpoint:
await fetch(`https://oauth2.googleapis.com/revoke?token=${accessToken}`, {
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
}); When to revoke
Revoke the access token when:
- The user explicitly disconnects the provider (“Unlink my GitHub account”)
- You detect the user’s account has been compromised
- You no longer need API access
Do not revoke on every logout. The user will just re-authorize when they log in again, which is unnecessary friction.
Exercises
Exercise 1: Add the logout route to your app. Test the flow: log in with GitHub, visit /me, log out, verify /me returns 401, log in again.
Exercise 2: After logging out of your app, visit github.com. Are you still logged in to GitHub? This demonstrates that your app’s session and GitHub’s session are independent.
When should you revoke a provider's access token?