plugins/full-stack-auth/skills/implement-logout/SKILL.md
Implements a complete logout flow for Scalekit FSA integrations by clearing application session cookies and redirecting the browser to Scalekit’s /oidc/logout endpoint to invalidate the Scalekit session. Use when adding or fixing logout in Node.js, Python, Go, or Java web apps that use Scalekit OIDC.
npx skillsauth add scalekit-inc/claude-code-authstack implementing-fsa-logoutInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Implement a single /logout endpoint that:
fetch/XHR from frontend and not a server-to-server API call.idToken) MUST be read BEFORE clearing cookies, because it is used as id_token_hint.post_logout_redirect_uri MUST be allowlisted in Scalekit Dashboard (Post Logout URLs).Ask for (or infer from the codebase):
accessToken, refreshToken, idToken) and cookie attributes (Path, Domain, SameSite).http://localhost:3000/login or your production login page).getLogoutUrl(...)./logout route:idToken (or equivalent) from cookies/session storage.postLogoutRedirectUri./oidc/logout, preferably using the Scalekit SDK helper if present.postLogoutRedirectUri under: Redirects → Post Logout URL.id_token_hint from cookie/session.logoutUrl = scalekit.getLogoutUrl(id_token_hint, post_logout_redirect_uri)302 -> logoutUrlapp.get('/logout', (req, res) => {
const idTokenHint = req.cookies?.idToken; // read BEFORE clearing
const postLogoutRedirectUri = process.env.POST_LOGOUT_REDIRECT_URI ?? 'http://localhost:3000/login';
// Prefer SDK helper if available in your project
const logoutUrl = scalekit.getLogoutUrl(idTokenHint, postLogoutRedirectUri);
// Clear cookies (match Path/Domain/SameSite used when setting them)
res.clearCookie('accessToken', { path: '/' });
res.clearCookie('refreshToken', { path: '/' });
res.clearCookie('idToken', { path: '/' });
return res.redirect(logoutUrl);
});
from flask import request, redirect, make_response
@app.get("/logout")
def logout():
id_token = request.cookies.get("idToken") # read BEFORE clearing
post_logout_redirect_uri = os.getenv("POST_LOGOUT_REDIRECT_URI", "http://localhost:3000/login")
logout_url = scalekit_client.get_logout_url(
id_token_hint=id_token,
post_logout_redirect_uri=post_logout_redirect_uri
)
resp = make_response(redirect(logout_url))
resp.set_cookie("accessToken", "", max_age=0, path="/")
resp.set_cookie("refreshToken", "", max_age=0, path="/")
resp.set_cookie("idToken", "", max_age=0, path="/")
return resp
func LogoutHandler(c *gin.Context) {
idToken, _ := c.Cookie("idToken") // read BEFORE clearing
postLogoutRedirectURI := os.Getenv("POST_LOGOUT_REDIRECT_URI")
if postLogoutRedirectURI == "" {
postLogoutRedirectURI = "http://localhost:3000/login"
}
logoutURL, err := scalekit.GetLogoutUrl(scalekit.LogoutUrlOptions{
IdTokenHint: idToken,
PostLogoutRedirectUri: postLogoutRedirectURI,
})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Clear cookies (match original attributes)
c.SetCookie("accessToken", "", -1, "/", "", true, true)
c.SetCookie("refreshToken", "", -1, "/", "", true, true)
c.SetCookie("idToken", "", -1, "/", "", true, true)
c.Redirect(http.StatusFound, logoutURL.String())
}
@GetMapping("/logout")
public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException {
String idToken = null;
if (request.getCookies() != null) {
for (Cookie c : request.getCookies()) {
if ("idToken".equals(c.getName())) {
idToken = c.getValue();
break;
}
}
}
String postLogoutRedirectUri = System.getenv().getOrDefault(
"POST_LOGOUT_REDIRECT_URI",
"http://localhost:3000/login"
);
URL logoutUrl = scalekitClient.authentication().getLogoutUrl(
idToken,
postLogoutRedirectUri
);
// Clear cookies (ensure Path/Domain match your app cookies)
Cookie access = new Cookie("accessToken", "");
access.setMaxAge(0);
access.setPath("/");
access.setHttpOnly(true);
access.setSecure(true);
response.addCookie(access);
Cookie refresh = new Cookie("refreshToken", "");
refresh.setMaxAge(0);
refresh.setPath("/");
refresh.setHttpOnly(true);
refresh.setSecure(true);
response.addCookie(refresh);
Cookie id = new Cookie("idToken", "");
id.setMaxAge(0);
id.setPath("/");
id.setHttpOnly(true);
id.setSecure(true);
response.addCookie(id);
response.sendRedirect(logoutUrl.toString());
}
/oidc/logout via the generated logout URL.post_logout_redirect_uri is allowlisted in Scalekit dashboard.post_logout_redirect_uri is not allowlisted in Scalekit dashboard.When asked to implement logout in a real repo, the assistant should:
/logout with the correct sequence (read id token → build logout URL → clear cookies → redirect).development
Walks through a structured production readiness checklist for Scalekit SSO implementations. Use when the user says they are going live, launching to production, doing a pre-launch review, hardening their SSO setup, or wants to verify their Scalekit implementation is production-ready.
data-ai
Implements complete SSO and authentication flows using Scalekit. Handles modular SSO, IdP-initiated login, user session management, and enterprise customer onboarding. Use when adding authentication, SSO, SAML, OIDC, or user login to applications.
testing
Implements Scalekit's admin portal for customer self-serve SSO and SCIM configuration. Generates portal links server-side and embeds the portal as an iframe in the app's settings UI. Use when the user asks to add an admin portal, customer self-serve SSO setup, iframe embed for SSO config, shareable setup link, or let customers configure their own SSO or SCIM connection.
development
Walks through a structured production readiness checklist for Scalekit SCIM provisioning implementations. Use when the user says they are going live, launching to production, doing a pre-launch review, or wants to verify their SCIM directory sync implementation is production-ready.