Skip to content

Commit ef191a9

Browse files
committed
fix wrong cooke settings
1 parent 691518e commit ef191a9

File tree

5 files changed

+54
-20
lines changed

5 files changed

+54
-20
lines changed

artist-insight-service/src/main/kotlin/org/taonity/artistinsightservice/mvc/security/OAuth2AuthenticationFailureHandler.kt

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package org.taonity.artistinsightservice.mvc.security
22

3-
import jakarta.servlet.http.Cookie
43
import jakarta.servlet.http.HttpServletRequest
54
import jakarta.servlet.http.HttpServletResponse
65
import mu.KotlinLogging
76
import org.springframework.beans.factory.annotation.Value
7+
import org.springframework.http.ResponseCookie
88
import org.springframework.security.core.AuthenticationException
99
import org.springframework.security.oauth2.core.OAuth2AuthenticationException
1010
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler
@@ -17,7 +17,8 @@ enum class AuthenticationErrorCode {
1717

1818
@Component
1919
class OAuth2AuthenticationFailureHandler(
20-
@Value("\${app.login-url}") private val loginUrl: String
20+
@Value("\${app.login-url}") private val loginUrl: String,
21+
@Value("\${server.servlet.session.cookie.domain}") private val cookieDomain: String
2122
) : SimpleUrlAuthenticationFailureHandler() {
2223

2324
companion object {
@@ -41,11 +42,15 @@ class OAuth2AuthenticationFailureHandler(
4142
}
4243
}
4344

44-
val cookie = Cookie(AUTH_ERROR_COOKIE_NAME, errorCode.name)
45-
cookie.path = "/"
46-
cookie.maxAge = 60
47-
cookie.isHttpOnly = false
48-
response.addCookie(cookie)
45+
val cookie = ResponseCookie.from(AUTH_ERROR_COOKIE_NAME, errorCode.name)
46+
.path("/")
47+
.maxAge(60)
48+
.httpOnly(false)
49+
.secure(loginUrl.startsWith("https"))
50+
.sameSite(if (loginUrl.startsWith("https")) "None" else "Lax")
51+
.domain(cookieDomain)
52+
.build()
53+
response.addHeader("Set-Cookie", cookie.toString())
4954

5055
redirectStrategy.sendRedirect(request, response, loginUrl)
5156
}

frontend/src/app/login/page.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Image from 'next/image'
77
import ErrorNotification from '../../components/ErrorNotification'
88
import BackgroundPhrases from '../../components/BackgroundPhrases'
99
import DevelopmentAccessNotification from '../../components/DevelopmentAccessNotification'
10+
import { logError, logDebug } from '@/utils/logger'
1011

1112
const righteous = Righteous({
1213
weight: '400',
@@ -38,12 +39,15 @@ function LoginContent() {
3839
useEffect(() => {
3940
// Check for error code from OAuth2 authentication failure (stored in cookie)
4041
const authErrorCode = getCookie('auth_error')
42+
logDebug('LoginPage', 'authErrorCode is ' + authErrorCode)
4143
if (authErrorCode) {
4244
deleteCookie('auth_error') // Remove cookie after reading
4345

4446
if (authErrorCode === 'UNAUTHORIZED_SPOTIFY_ACCOUNT') {
47+
logError('LoginPage', 'Unauthorized Spotify account')
4548
setShowAccessRequestForm(true)
4649
} else if (authErrorCode === 'AUTHENTICATION_FAILED') {
50+
logError('LoginPage', 'Authentication failed')
4751
setErrorMessage('Authentication failed. Please try again.')
4852
}
4953
return
@@ -59,13 +63,18 @@ function LoginContent() {
5963
window.location.href = '/'
6064
}
6165
} else if (res.status === 504) {
66+
logError('LoginPage', 'User fetch timed out with 504 status')
6267
setErrorMessage('Request timed out. Please try again.')
68+
} else {
69+
logError('LoginPage', 'User fetch failed with status: ' + res.status)
6370
}
6471
})
6572
.catch((err) => {
6673
if (err.name === 'AbortError') {
74+
logError('LoginPage', 'User fetch aborted due to timeout')
6775
setErrorMessage('Request timed out. Please try again.')
6876
} else {
77+
logError('LoginPage', 'User fetch network error', err)
6978
setErrorMessage('Unable to connect to the server. Please check your connection.')
7079
}
7180
})
@@ -90,15 +99,18 @@ function LoginContent() {
9099
const response = await fetch('/api/actuator/health/liveness', { signal: controller.signal })
91100
const data = await response.json()
92101
if (!response.ok || data.status !== 'UP') {
102+
logError('LoginPage', 'Liveness check failed', { status: response.status, data })
93103
setErrorMessage('Backend server is currently unavailable. Please try again later.')
94104
setLivenessLoading(false)
95105
return
96106
}
97107
window.location.href = '/api/oauth2/authorization/spotify-artist-insight-service'
98108
} catch (err: any) {
99109
if (err.name === 'AbortError') {
110+
logError('LoginPage', 'Liveness check timed out')
100111
setErrorMessage('Request timed out. Please try again.')
101112
} else {
113+
logError('LoginPage', 'Liveness check network error', err)
102114
setErrorMessage('Unable to connect to the server. Please check your connection.')
103115
}
104116
} finally {

frontend/src/app/settings/page.tsx

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,11 @@ import Header from '@/components/Header'
55
import ErrorNotification from '@/components/ErrorNotification'
66
import { useUser } from '@/hooks/useUser'
77
import { getRuntimeConfig } from '@/lib/runtimeConfig'
8+
import { logError } from '@/utils/logger'
89

910
const csrfErrorMessage = 'Unable to verify your request. Please refresh the page and try again.'
1011
const networkErrorMessage = 'Unable to connect to the server. Please check your connection.'
1112

12-
function logError(message: string, error?: any) {
13-
if (typeof window !== 'undefined' && localStorage.getItem('artist-insight-debug') === 'true') {
14-
console.error(`[SettingsPage] ${message}`, error)
15-
}
16-
}
17-
1813
function getCookie(name: string) {
1914
if (typeof document === 'undefined') {
2015
return null
@@ -48,7 +43,7 @@ export default function SettingsPage() {
4843
const handleLogout = async () => {
4944
const xsrfToken = getCookie(csrfCookieName)
5045
if (!xsrfToken) {
51-
logError('CSRF token not found for logout with CSRF_COOKIE_NAME=' + csrfCookieName)
46+
logError('SettingsPage', 'CSRF token not found for logout with CSRF_COOKIE_NAME=' + csrfCookieName)
5247
setErrorMessage(csrfErrorMessage)
5348
return
5449
}
@@ -58,7 +53,7 @@ export default function SettingsPage() {
5853
await requestLogout(xsrfToken)
5954
window.location.href = '/login'
6055
} catch (err) {
61-
logError('Logout failed', err)
56+
logError('SettingsPage', 'Logout failed', err)
6257
setErrorMessage('Unable to log out. Please try again.')
6358
} finally {
6459
setIsProcessing(false)
@@ -72,7 +67,7 @@ export default function SettingsPage() {
7267

7368
const xsrfToken = getCookie(csrfCookieName)
7469
if (!xsrfToken) {
75-
logError('CSRF token not found for delete account with CSRF_COOKIE_NAME=' + csrfCookieName)
70+
logError('SettingsPage', 'CSRF token not found for delete account with CSRF_COOKIE_NAME=' + csrfCookieName)
7671
setErrorMessage(csrfErrorMessage)
7772
return
7873
}
@@ -91,27 +86,27 @@ export default function SettingsPage() {
9186
}
9287

9388
if (res.status === 403) {
94-
logError('Delete account forbidden - CSRF validation failed')
89+
logError('SettingsPage', 'Delete account forbidden - CSRF validation failed')
9590
setErrorMessage(csrfErrorMessage)
9691
return
9792
}
9893

9994
if (!res.ok && res.status !== 204) {
100-
logError('Delete account failed with status: ' + res.status)
95+
logError('SettingsPage', 'Delete account failed with status: ' + res.status)
10196
setErrorMessage('Failed to delete your account. Please try again.')
10297
return
10398
}
10499

105100
try {
106101
await requestLogout(xsrfToken)
107102
} catch (err) {
108-
logError('Logout after delete account failed', err)
103+
logError('SettingsPage', 'Logout after delete account failed', err)
109104
// Ignore logout failures here and continue redirecting the user.
110105
}
111106

112107
window.location.href = '/login'
113108
} catch (err) {
114-
logError('Delete account network error', err)
109+
logError('SettingsPage', 'Delete account network error', err)
115110
setErrorMessage(networkErrorMessage)
116111
} finally {
117112
setIsProcessing(false)

frontend/src/utils/logger.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Logs error messages to the console when debug mode is enabled.
3+
* Debug mode is activated by setting 'artist-insight-debug' to 'true' in localStorage.
4+
*
5+
* @param context - The context or component name where the error occurred
6+
* @param message - The error message to log
7+
* @param error - Optional error object or additional details
8+
*/
9+
export function logError(context: string, message: string, error?: any) {
10+
if (typeof window !== 'undefined' && localStorage.getItem('artist-insight-debug') === 'true') {
11+
console.error(`[${context}] ${message}`, error)
12+
}
13+
}
14+
15+
16+
export function logDebug(context: string, message: string, error?: any) {
17+
if (typeof window !== 'undefined' && localStorage.getItem('artist-insight-debug') === 'true') {
18+
console.debug(`[${context}] ${message}`, error)
19+
}
20+
}

templates/docker/.test-env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ ADMIN_EMAIL=
1313
ORGANISATION_EMAIL=
1414
ORGANISATION_EMAIL_PASSWORD=
1515
DEFAULT_SUCCESS_URL=http://127.0.0.1:3002
16+
LOGIN_URL=http://127.0.0.1:3002/login
1617
SPRING_PROFILES_ACTIVE=postgres,prod-spotify,stub-openai,stub-kofi,local
1718

1819
LOCAL_BACKEND_URL: http://app:9016
1920
PUBLIC_BACKEND_URL=http://127.0.0.1:9016
21+
NEXT_PUBLIC_CSRF_COOKIE_NAME=XSRF-TOKEN-LOCAL
2022

0 commit comments

Comments
 (0)