fix(review): harden payment, oauth, and migration paths
This commit is contained in:
@@ -937,7 +937,19 @@ func clearOAuthBindAccessTokenCookie(c *gin.Context, secure bool) {
|
||||
Value: "",
|
||||
Path: oauthBindAccessTokenCookiePath,
|
||||
MaxAge: -1,
|
||||
HttpOnly: false,
|
||||
HttpOnly: true,
|
||||
Secure: secure,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
}
|
||||
|
||||
func setOAuthBindAccessTokenCookie(c *gin.Context, token string, secure bool) {
|
||||
http.SetCookie(c.Writer, &http.Cookie{
|
||||
Name: oauthBindAccessTokenCookieName,
|
||||
Value: url.QueryEscape(strings.TrimSpace(token)),
|
||||
Path: oauthBindAccessTokenCookiePath,
|
||||
MaxAge: linuxDoOAuthCookieMaxAgeSec,
|
||||
HttpOnly: true,
|
||||
Secure: secure,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
@@ -1021,6 +1033,26 @@ func (h *AuthHandler) buildOAuthBindUserCookieFromContext(c *gin.Context) (strin
|
||||
return buildOAuthBindUserCookieValue(*userID, h.oauthBindCookieSecret())
|
||||
}
|
||||
|
||||
func (h *AuthHandler) PrepareOAuthBindAccessTokenCookie(c *gin.Context) {
|
||||
const bearerPrefix = "Bearer "
|
||||
|
||||
authHeader := strings.TrimSpace(c.GetHeader("Authorization"))
|
||||
if !strings.HasPrefix(strings.ToLower(authHeader), strings.ToLower(bearerPrefix)) {
|
||||
response.ErrorFrom(c, infraerrors.Unauthorized("UNAUTHORIZED", "authentication required"))
|
||||
return
|
||||
}
|
||||
|
||||
token := strings.TrimSpace(authHeader[len(bearerPrefix):])
|
||||
if token == "" {
|
||||
response.ErrorFrom(c, infraerrors.Unauthorized("UNAUTHORIZED", "authentication required"))
|
||||
return
|
||||
}
|
||||
|
||||
setOAuthBindAccessTokenCookie(c, token, isRequestHTTPS(c))
|
||||
c.Status(http.StatusNoContent)
|
||||
c.Writer.WriteHeaderNow()
|
||||
}
|
||||
|
||||
func (h *AuthHandler) resolveOAuthBindTargetUserID(c *gin.Context) (*int64, error) {
|
||||
if subject, ok := servermiddleware.GetAuthSubjectFromContext(c); ok && subject.UserID > 0 {
|
||||
return &subject.UserID, nil
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -226,6 +227,27 @@ func TestLinuxDoOAuthBindStartAcceptsAccessTokenCookie(t *testing.T) {
|
||||
require.Equal(t, -1, accessTokenCookie.MaxAge)
|
||||
}
|
||||
|
||||
func TestPrepareOAuthBindAccessTokenCookieSetsHttpOnlyCookie(t *testing.T) {
|
||||
handler, client := newLinuxDoOAuthHandlerAndClient(t, false, config.LinuxDoConnectConfig{})
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/oauth/bind-token", nil)
|
||||
req.Header.Set("Authorization", "Bearer access-token-value")
|
||||
c.Request = req
|
||||
|
||||
handler.PrepareOAuthBindAccessTokenCookie(c)
|
||||
|
||||
require.Equal(t, http.StatusNoContent, recorder.Code)
|
||||
accessTokenCookie := findCookie(recorder.Result().Cookies(), oauthBindAccessTokenCookieName)
|
||||
require.NotNil(t, accessTokenCookie)
|
||||
require.Equal(t, oauthBindAccessTokenCookiePath, accessTokenCookie.Path)
|
||||
require.Equal(t, linuxDoOAuthCookieMaxAgeSec, accessTokenCookie.MaxAge)
|
||||
require.True(t, accessTokenCookie.HttpOnly)
|
||||
require.Equal(t, url.QueryEscape("access-token-value"), accessTokenCookie.Value)
|
||||
}
|
||||
|
||||
func TestLinuxDoOAuthCallbackCreatesLoginPendingSessionForExistingIdentityUser(t *testing.T) {
|
||||
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
|
||||
Reference in New Issue
Block a user