Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add logout route + tests #291

Merged
merged 1 commit into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 68 additions & 2 deletions backend/internal/tests/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"KonferCA/SPUR/internal/jwt"
"KonferCA/SPUR/internal/server"
"KonferCA/SPUR/internal/v1/v1_auth"
"KonferCA/SPUR/internal/v1/v1_common"
"KonferCA/SPUR/internal/v1/v1_common"

"bytes"
"context"
"encoding/json"
Expand Down Expand Up @@ -448,5 +448,71 @@ func TestServer(t *testing.T) {
assert.Equal(t, v1_common.ErrorTypeBadRequest, apiErr.Type)
assert.Equal(t, "Failed to verify email. Invalid or expired token.", apiErr.Message)
})

t.Run("/api/v1/auth/logout - 200 OK - successfully logout", func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
defer cancel()

// register user
email := "[email protected]"
password := "mypassword123"
authReq := v1_auth.AuthRequest{
Email: email,
Password: password,
}
data, err := json.Marshal(authReq)
assert.NoError(t, err)
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/register", bytes.NewReader(data))
req.Header.Add(echo.HeaderContentType, echo.MIMEApplicationJSON)
rec := httptest.NewRecorder()

s.Echo.ServeHTTP(rec, req)
assert.Equal(t, http.StatusCreated, rec.Code)
defer removeTestUser(ctx, email, s)

// get the cookie
cookies := rec.Result().Cookies()
var tokenCookie *http.Cookie
for _, cookie := range cookies {
if cookie.Name == v1_auth.COOKIE_REFRESH_TOKEN {
tokenCookie = cookie
break
}
}
if tokenCookie == nil {
t.Fatal("Refresh token cookie not found")
}
assert.NoError(t, err)
assert.NotNil(t, tokenCookie)
assert.NotEmpty(t, tokenCookie.Value)

req = httptest.NewRequest(http.MethodGet, "/api/v1/auth/logout", nil)
req.AddCookie(tokenCookie)
rec = httptest.NewRecorder()

s.Echo.ServeHTTP(rec, req)

assert.Equal(t, http.StatusOK, rec.Code)

// make sure the cookie value has been unset
tokenCookie = nil
cookies = rec.Result().Cookies()
for _, cookie := range cookies {
if cookie.Name == v1_auth.COOKIE_REFRESH_TOKEN {
tokenCookie = cookie
break
}
}
if tokenCookie == nil {
t.Fatal("Refresh token cookie not found")
}
assert.NoError(t, err)
assert.NotNil(t, tokenCookie)
assert.Empty(t, tokenCookie.Value)
// make sure the expiration date is less than right now
// and max-age is negative to indicate the browser to remove the cookie
assert.True(t, time.Now().After(tokenCookie.Expires))
assert.Equal(t, -1, tokenCookie.MaxAge)
})
})
}
8 changes: 8 additions & 0 deletions backend/internal/v1/v1_auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,3 +319,11 @@ func (h *Handler) handleVerifyCookie(c echo.Context) error {
},
})
}

/*
Handle incoming logout requests. This will empty out the refresh token cookie.
*/
func (h *Handler) handleLogout(c echo.Context) error {
unsetRefreshTokenCookie(c)
return v1_common.Success(c, http.StatusOK, "Successfully logged out.")
}
13 changes: 13 additions & 0 deletions backend/internal/v1/v1_auth/cookies.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,16 @@ func setRefreshTokenCookie(c echo.Context, value string) {
cookie.Value = value
c.SetCookie(cookie)
}

/*
Unsets the refresh token cookie. Make the right configuration
that tells the browser to remove the cookie.
*/
func unsetRefreshTokenCookie(c echo.Context) {
cookie := getRefreshTokenCookieConfig()
cookie.Value = ""
// expires and max-age tells the browser to remove the cookie
cookie.Expires = time.Now().UTC()
cookie.MaxAge = -1
c.SetCookie(cookie)
}
1 change: 1 addition & 0 deletions backend/internal/v1/v1_auth/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ func SetupAuthRoutes(e *echo.Group, s interfaces.CoreServer) {
e.GET("/auth/verify", h.handleVerifyCookie)
e.GET("/auth/verify-email", h.handleVerifyEmail, authLimiter.RateLimit())
e.POST("/auth/register", h.handleRegister, authLimiter.RateLimit())
e.GET("/auth/logout", h.handleLogout, authLimiter.RateLimit())
}
Loading