Clear the user's session cookie. @Summary Log out user @ID log-out-user @Security CoderSessionToken @Produce json @Tags Users @Success 200 {object} codersdk.Response @Router /api/v2/users/logout [post]
(rw http.ResponseWriter, r *http.Request)
| 687 | // @Success 200 {object} codersdk.Response |
| 688 | // @Router /api/v2/users/logout [post] |
| 689 | func (api *API) postLogout(rw http.ResponseWriter, r *http.Request) { |
| 690 | var ( |
| 691 | ctx = r.Context() |
| 692 | auditor = api.Auditor.Load() |
| 693 | aReq, commitAudit = audit.InitRequest[database.APIKey](rw, &audit.RequestParams{ |
| 694 | Audit: *auditor, |
| 695 | Log: api.Logger, |
| 696 | Request: r, |
| 697 | Action: database.AuditActionLogout, |
| 698 | }) |
| 699 | ) |
| 700 | defer commitAudit() |
| 701 | |
| 702 | // Get a blank token cookie. |
| 703 | cookie := &http.Cookie{ |
| 704 | // MaxAge < 0 means to delete the cookie now. |
| 705 | MaxAge: -1, |
| 706 | Name: codersdk.SessionTokenCookie, |
| 707 | Path: "/", |
| 708 | } |
| 709 | http.SetCookie(rw, api.DeploymentValues.HTTPCookies.Apply(cookie)) |
| 710 | |
| 711 | // Delete the session token from database. |
| 712 | apiKey := httpmw.APIKey(r) |
| 713 | aReq.Old = apiKey |
| 714 | |
| 715 | logger := api.Logger.Named(userAuthLoggerName) |
| 716 | |
| 717 | err := api.Database.DeleteAPIKeyByID(ctx, apiKey.ID) |
| 718 | if err != nil { |
| 719 | logger.Error(ctx, "unable to delete API key", slog.F("api_key", apiKey.ID), slog.Error(err)) |
| 720 | httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ |
| 721 | Message: "Internal error deleting API key.", |
| 722 | Detail: err.Error(), |
| 723 | }) |
| 724 | return |
| 725 | } |
| 726 | |
| 727 | // Invalidate all subdomain app tokens. This saves us from having to |
| 728 | // track which app tokens are associated which this browser session and |
| 729 | // doesn't inconvenience the user as they'll just get redirected if they try |
| 730 | // to access the app again. |
| 731 | err = api.Database.DeleteApplicationConnectAPIKeysByUserID(ctx, apiKey.UserID) |
| 732 | if err != nil { |
| 733 | logger.Error(ctx, "unable to invalidate subdomain app tokens", slog.F("user_id", apiKey.UserID), slog.Error(err)) |
| 734 | httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ |
| 735 | Message: "Internal error deleting app tokens.", |
| 736 | Detail: err.Error(), |
| 737 | }) |
| 738 | return |
| 739 | } |
| 740 | |
| 741 | aReq.New = database.APIKey{} |
| 742 | |
| 743 | httpapi.Write(ctx, rw, http.StatusOK, codersdk.Response{ |
| 744 | Message: "Logged out!", |
| 745 | }) |
| 746 | } |
nothing calls this directly
no test coverage detected