I have an endpoint in my kotlin app that looks like this:
either.eager<String, Unit> {
val sessionAndCookieUser = commonAuth.decryptCookieGetUser(getCookie(context), ::userTransform).bind()
val user = sessionAndCookieUser.session.user
val ctx = Ctx(ds, SystemSession, conf)
val dbUser = getUserEither(ctx, user.id).bind()
val signatureAlgorithm = SignatureAlgorithm.HS256
val signingKey = SecretKeySpec(conf.get(ZendeskJWTSecret).toByteArray(), signatureAlgorithm.jcaName)
val iat = Date(System.currentTimeMillis())
val exp = Date(System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000)
val token = Jwts.builder()
.claim("name", dbUser.name)
.claim("email", dbUser.email)
.setIssuer(conf.get(StreamAppName))
.setIssuedAt(iat)
.setExpiration(exp)
.signWith(signingKey, signatureAlgorithm)
.compact()
context.setResponseCode(StatusCode.OK)
.setResponseType("application/json")
.send(jsonObject("token" to token).toString())
}.mapLeft {
context.setResponseCode(StatusCode.UNAUTHORIZED)
}
I am setting a response where I should send a jsonObject
if a user is authenticated or UNAUTHORIZED
if the user is not authenticated.
When I am testing this endpoint in a browser I just get status unknown
for that request - when I was debugging the backend, otherwise I get 200
with no response data.
If I test it in postman I get json as a response.
I see that token is being built and everything looks good on the backend side, but then response is not being loaded in the browser.
I am fetching it like this from react:
export const fetchGet = (uriPath: string) =>
fetch(fullUrl(uriPath), {
method: 'GET',
credentials: 'include'
})
useEffect(() => {
console.log('got here')
fetchGet('/auth/token')
.then(res => {
console.log('res ', res)
return res.json()
})
.then(res => {
console.log('res.json ', res)
return res.ok ? setJwtToken(res.token) : Promise.reject(res.statusText)
})
.catch(error => {
console.log('err ', error)
setError(error.toString())
})
}, [])
In the console I can only see 'got here' being logged, nothing else, and frontend crushed with an error:
DevTools failed to load source map: Could not load content for data:application/json;charset=utf-8;base64, longTokenString...: Load canceled due to reload of inspected page
What am I doing wrong here?
Updated
I found an issue here, I had 2 more useEffect
functions, and they were redirecting before I had a result. I am not sure why was the useEffect
function where I am passing the error state variable running when there was no change from initial state?
Here is the full code:
const [jwtToken, setJwtToken] = useState(null)
const [error, setError] = useState(null)
useEffect(() => {
fetchGet('/auth/token')
.then(async res => {
const data = await res.json()
if (!res.ok) {
const error = data?.message || res.statusText
return Promise.reject(error)
}
return data
})
.then(({token}) => setJwtToken(token))
.catch(err => {
console.log('err ', err)
setError(err.toString())
})
}, [])
useEffect(() => {
if (jwtToken) {
// window.location.href = `/mypage.com?access/jwt?jwt=${jwtToken}&return_to=`
console.log(jwtToken)
}
}, [jwtToken])
useEffect(() => {
console.log(error)
//window.location.href = '/login'
}, [error])
Update nr. 2:
const [jwtToken, setJwtToken] = useState('')
const { search } = useLocation()
useEffect(() => {
fetchGet('/auth/token')
.then(async res => {
const data = await res.json()
if (!res.ok) {
const error = data?.message || res.statusText
return Promise.reject(error)
}
return data
})
.then(({token}) => setJwtToken(token))
.catch(() => window.location.href = '/login')
}, [])
useEffect(() => {
const params = new URLSearchParams(search)
const returnTo = params.get('return_to') ? `&return_to=${params.get('return_to')}` : ''
jwtToken !== '' ? window.location.href = `${url}/jwt?jwt=${jwtToken}${returnTo}` : null
}, [jwtToken])
return <p>Authenticating ...</p>
I have removed unnecessary error useEffect function, but now I get:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
I get this warning and it is also not redirecting after the token is fetched. What am I doing wrong this time around?
Every useEffect callback will be invoked on first mount. You should include a simple if statement to ensure an error is set before running your error handling logic.
useEffect(() => {
if(error) {
console.log(error)
//window.location.href = '/login'
}
}, [error])
There is likely an issue with the CORS configuration of your API.
Access-Control-Allow-Origin
response header must be set to the origin of your react app (it cannot be *
for credentialed requests) and Access-Control-Allow-Credentials
must be true
. Failing to include them will result in an opaque response.
https://fetch.spec.whatwg.org/#cors-protocol-and-credentials
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With