From 1d767ea7a1534748475c6b7ed17f63d59d3c2bc9 Mon Sep 17 00:00:00 2001 From: solufa Date: Fri, 21 Jun 2024 15:34:03 +0900 Subject: [PATCH] fix: set expires time in sec --- client/components/Auth/AuthLoader.tsx | 17 +++++++---------- server/api/private/hooks.ts | 2 +- server/api/public/session/controller.ts | 9 ++++++--- server/domain/user/service/genTokens.ts | 5 +++-- server/domain/user/useCase/authUseCase.ts | 3 ++- server/service/constants.ts | 3 +++ server/tests/api/public.test.ts | 5 +++-- 7 files changed, 25 insertions(+), 19 deletions(-) diff --git a/client/components/Auth/AuthLoader.tsx b/client/components/Auth/AuthLoader.tsx index 0f78ccf..b8fc868 100644 --- a/client/components/Auth/AuthLoader.tsx +++ b/client/components/Auth/AuthLoader.tsx @@ -1,4 +1,4 @@ -import { fetchAuthSession, signOut } from 'aws-amplify/auth'; +import { fetchAuthSession, getCurrentUser, signOut } from 'aws-amplify/auth'; import { Hub } from 'aws-amplify/utils'; import { isAxiosError } from 'axios'; import { useAlert } from 'components/Alert/useAlert'; @@ -25,14 +25,10 @@ export const AuthLoader = () => { }, [catchApiErr, setUser]); useEffect(() => { - const controller = new AbortController(); - apiClient.private.me - .$get({ config: { signal: controller.signal } }) - .then(setUser) - .catch((e) => (isAxiosError(e) && e.response?.status === 401 ? setUser(null) : null)); - - return () => controller.abort(); - }, [setUser]); + getCurrentUser() + .then(updateCookie) + .catch(() => setUser(null)); + }, [setUser, updateCookie]); useEffect(() => { const useId = apiAxios.interceptors.response.use(undefined, async (err) => { @@ -61,12 +57,13 @@ export const AuthLoader = () => { break; case 'signInWithRedirect_failure': break; + case 'tokenRefresh': + break; case 'signedOut': await apiClient.public.session.$delete().catch(catchApiErr); setUser(null); break; case 'signedIn': - case 'tokenRefresh': await updateCookie().catch(catchApiErr); break; case 'tokenRefresh_failure': diff --git a/server/api/private/hooks.ts b/server/api/private/hooks.ts index bf196ee..6854836 100644 --- a/server/api/private/hooks.ts +++ b/server/api/private/hooks.ts @@ -15,7 +15,7 @@ export default defineHooks(() => ({ try { await req.jwtVerify({ onlyCookie: true }); } catch (e) { - res.status(401).send(); + res.status(401).send((e as Error).message); return; } diff --git a/server/api/public/session/controller.ts b/server/api/public/session/controller.ts index 3c73380..e234380 100644 --- a/server/api/public/session/controller.ts +++ b/server/api/public/session/controller.ts @@ -16,18 +16,21 @@ const options: CookieSerializeOptions = { sameSite: 'none', }; -export default defineController(() => ({ +export default defineController((fastify) => ({ post: { validators: { body: z.object({ jwt: z.string() }) }, hooks: { preHandler: (req, reply, done) => { assert(req.body); - const expiresIn = 60 * 60 * 24 * 5 * 1000; + const decoded = z + .object({ payload: z.object({ exp: z.number() }).passthrough() }) + .passthrough() + .parse(fastify.jwt.decode(req.body.jwt)); reply.setCookie(COOKIE_NAME, req.body.jwt, { ...options, - expires: new Date(Date.now() + expiresIn), + expires: new Date(decoded.payload.exp * 1000), }); done(); diff --git a/server/domain/user/service/genTokens.ts b/server/domain/user/service/genTokens.ts index 318260d..b7d66a8 100644 --- a/server/domain/user/service/genTokens.ts +++ b/server/domain/user/service/genTokens.ts @@ -2,6 +2,7 @@ import type { Jwks } from 'api/@types/auth'; import type { EntityId } from 'api/@types/brandedId'; import type { UserEntity } from 'api/@types/user'; import { createSigner } from 'fast-jwt'; +import { EXPIRES_SEC } from 'service/constants'; import { PORT } from 'service/envValues'; import type { AccessTokenJwt, IdTokenJwt } from 'service/types'; import { ulid } from 'ulid'; @@ -17,14 +18,14 @@ export const genTokens = (params: { aud: params.userPoolClientId, header: { kid: params.jwks.keys[0].kid, alg: params.jwks.keys[0].alg }, }); - const now = Date.now(); + const now = Math.floor(Date.now() / 1000); const comomn = { sub: params.user.id, iss: `http://localhost:${PORT}/${params.user.userPoolId}`, origin_jti: ulid(), event_id: ulid(), auth_time: now, - exp: now + 3600 * 1000, + exp: now + EXPIRES_SEC, iat: now, jti: ulid(), }; diff --git a/server/domain/user/useCase/authUseCase.ts b/server/domain/user/useCase/authUseCase.ts index f837360..64e2727 100644 --- a/server/domain/user/useCase/authUseCase.ts +++ b/server/domain/user/useCase/authUseCase.ts @@ -17,6 +17,7 @@ import { genTokens } from 'domain/user/service/genTokens'; import { userPoolQuery } from 'domain/userPool/repository/userPoolQuery'; import { jwtDecode } from 'jwt-decode'; import { cognitoAssert } from 'service/cognitoAssert'; +import { EXPIRES_SEC } from 'service/constants'; import { transaction } from 'service/prismaClient'; import type { AccessTokenJwt } from 'service/types'; import { genCodeDeliveryDetails } from '../service/genCodeDeliveryDetails'; @@ -91,7 +92,7 @@ export const authUseCase = { jwks, user, }), - ExpiresIn: 3600, + ExpiresIn: EXPIRES_SEC, TokenType: 'Bearer', }, ChallengeParameters: {}, diff --git a/server/service/constants.ts b/server/service/constants.ts index 8d592b0..5241374 100644 --- a/server/service/constants.ts +++ b/server/service/constants.ts @@ -1,2 +1,5 @@ export const COOKIE_NAME = 'session'; + export const JWT_PROP_NAME = 'idToken'; + +export const EXPIRES_SEC = 3600; diff --git a/server/tests/api/public.test.ts b/server/tests/api/public.test.ts index 5cf01da..33c8fcd 100644 --- a/server/tests/api/public.test.ts +++ b/server/tests/api/public.test.ts @@ -1,4 +1,5 @@ -import { COOKIE_NAME } from 'service/constants'; +import { createSigner } from 'fast-jwt'; +import { COOKIE_NAME, EXPIRES_SEC } from 'service/constants'; import { DEFAULT_USER_POOL_CLIENT_ID, DEFAULT_USER_POOL_ID } from 'service/envValues'; import { expect, test } from 'vitest'; import { noCookieClient } from './apiClient'; @@ -38,7 +39,7 @@ test(GET(noCookieClient.public.defaults), async () => { }); test(POST(noCookieClient.public.session), async () => { - const jwt = 'dummy-jwt'; + const jwt = createSigner({ key: 'dummy' })({ exp: Math.floor(Date.now() / 1000) + EXPIRES_SEC }); const res = await noCookieClient.public.session.post({ body: { jwt } }); expect(res.headers['set-cookie'][0].startsWith(`${COOKIE_NAME}=${jwt};`)).toBeTruthy();