Skip to content

Commit 4dfc602

Browse files
authored
fix session refresh detection (#118)
* fix session refresh detection * align some auth checks * remove complete profile stuff * ignore type issue * last one
1 parent 7602853 commit 4dfc602

File tree

8 files changed

+24
-57
lines changed

8 files changed

+24
-57
lines changed

admin/src/services/fetch.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
import { createFetch } from '@a-type/auth-fetch';
2-
import { AlefError } from '@alef/common';
32

43
export const fetch = createFetch({
54
refreshSessionEndpoint: `${import.meta.env.VITE_PUBLIC_API_ORIGIN}/auth/refresh`,
65
logoutEndpoint: `${import.meta.env.VITE_PUBLIC_API_ORIGIN}/auth/logout`,
7-
isSessionExpired: (res) => {
8-
const asAlefError = AlefError.fromResponse(res);
9-
if (asAlefError) {
10-
return asAlefError.code === AlefError.Code.SessionExpired;
11-
}
12-
return false;
13-
},
146
});

app/src/pages/HomePage.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,10 @@
11
import { Redirect } from '@/components/Redirect';
22
import { isHeadset } from '@/services/os';
3-
import { useMe } from '@/services/publicApi/userHooks';
4-
import { useNavigate } from '@verdant-web/react-router';
5-
import { lazy, useEffect } from 'react';
3+
import { lazy } from 'react';
64

75
const LazyMainScene = lazy(() => import('@/components/xr/MainScene'));
86

97
const HomePage = () => {
10-
const { data: session } = useMe();
11-
const navigate = useNavigate();
12-
const incompleteProfile = session && !session.emailVerifiedAt;
13-
useEffect(() => {
14-
// don't bother people on headsets with this
15-
if (!isHeadset && incompleteProfile) {
16-
navigate('/complete-signup');
17-
}
18-
}, [incompleteProfile, navigate]);
19-
208
if (!isHeadset) {
219
// on desktop/mobile, editor is the default page.
2210
return <Redirect to="/editor" />;

app/src/services/fetch.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
11
import { publicApiOrigin } from '@/env';
22
import { createFetch } from '@a-type/auth-fetch';
3-
import { AlefError } from '@alef/common';
43

54
export const fetch = createFetch({
65
refreshSessionEndpoint: `${publicApiOrigin}/auth/refresh`,
76
logoutEndpoint: `${publicApiOrigin}/auth/logout`,
8-
isSessionExpired: (res) => {
9-
const asAlefError = AlefError.fromResponse(res);
10-
if (asAlefError) {
11-
return asAlefError.code === AlefError.Code.SessionExpired;
12-
}
13-
return false;
14-
},
157
});

app/src/services/publicApi/utils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ export async function fallbackWhenOfflineOrError<TResponseData, TFallback = null
1515
try {
1616
const res = await req;
1717
if (!res.ok) {
18+
if (res.status === 401) {
19+
return fallback;
20+
}
1821
const asAlefError = AlefError.fromResponse(res);
1922
console.error(asAlefError);
2023
toast.error(!asAlefError ? 'Server error! Check your network.' : asAlefError.message);

packages/common/src/error.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
export enum AlefErrorCode {
22
BadRequest = 40000,
33
Unauthorized = 40100,
4-
SessionExpired = 40101,
5-
SessionInvalid = 40102,
64
Forbidden = 40300,
75
NotFound = 40400,
86
Conflict = 40900,

services/src/admin-api/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { furnitureRouter } from './routers/furniture.js';
1010
import { usersRouter } from './routers/users.js';
1111

1212
const adminApp = new Hono<Env>()
13-
.onError(handleError)
13+
.onError(handleError as any /* TODO: fix ctx type compatibility junk */)
1414
.use(requestId())
1515
.use(
1616
cors({

services/src/middleware/errors.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { AuthError } from '@a-type/auth';
22
import { AlefError } from '@alef/common';
3+
import { Context } from 'hono';
34
import { ZodError } from 'zod';
5+
import { sessions } from '../public-api/auth/session';
6+
import { Env } from '../public-api/config/ctx';
47

5-
export function handleError(reason: unknown): Response {
8+
export function handleError(reason: unknown, ctx: Context<Env>): Response {
69
if (AlefError.isInstance(reason)) {
710
if (reason.code > AlefError.Code.InternalServerError) {
811
console.error('Unexpected AlefError:', reason);
@@ -11,12 +14,19 @@ export function handleError(reason: unknown): Response {
1114
}
1215

1316
if (reason instanceof AuthError) {
14-
return new Response(reason.message, {
15-
status: reason.statusCode,
16-
headers: {
17-
'Content-Type': 'text/plain',
18-
},
19-
});
17+
// for invalid sessions, log the user out.
18+
if (reason.message === AuthError.Messages.InvalidSession || reason.message === AuthError.Messages.InvalidRefreshToken) {
19+
const { headers } = sessions.clearSession(ctx);
20+
return new Response(reason.message, {
21+
status: 401,
22+
headers: {
23+
'Content-Type': 'text/plain',
24+
'x-alef-error': AlefError.Code.Unauthorized.toString(),
25+
...headers,
26+
},
27+
});
28+
}
29+
return reason.toResponse();
2030
}
2131

2232
if (reason instanceof ZodError) {

services/src/middleware/session.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AuthError, Session } from '@a-type/auth';
1+
import { Session } from '@a-type/auth';
22
import { AlefError, assertPrefixedId, PrefixedId } from '@alef/common';
33
import { RpcStub } from 'cloudflare:workers';
44
import { Context } from 'hono';
@@ -12,23 +12,7 @@ export type SessionWithPrefixedIds = Omit<Session, 'userId'> & {
1212
};
1313

1414
async function getRequestSessionOrThrow(ctx: Context): Promise<SessionWithPrefixedIds> {
15-
let session: Session | null = null;
16-
try {
17-
session = await sessions.getSession(ctx);
18-
} catch (err) {
19-
if (err instanceof AuthError) {
20-
if (err.message === AuthError.Messages.SessionExpired) {
21-
throw new AlefError(AlefError.Code.SessionExpired, 'Session expired. Please refresh your session or log in again.', err);
22-
} else if (err.message === AuthError.Messages.InvalidSession) {
23-
// remove the invalid session
24-
const { headers } = sessions.clearSession(ctx);
25-
throw new AlefError(AlefError.Code.SessionInvalid, 'Invalid session. Please log in again.', err, {
26-
headers,
27-
});
28-
}
29-
}
30-
throw err;
31-
}
15+
const session = await sessions.getSession(ctx);
3216

3317
if (!session) {
3418
throw new AlefError(AlefError.Code.Unauthorized, 'You must be logged in to access this functionality.');

0 commit comments

Comments
 (0)