11import { faGithub } from '@fortawesome/free-brands-svg-icons' ;
22import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' ;
3+ import { verify } from 'jsonwebtoken' ;
34import { observer } from 'mobx-react' ;
45import { compose } from 'next-ssr-middleware' ;
56import { FC , useContext } from 'react' ;
67import { Button , Container } from 'react-bootstrap' ;
78
89import { PageHead } from '../../components/layout/PageHead' ;
10+ import { JWT_SECRET } from '../../configuration' ;
911import { I18nContext } from '../../models/Base/Translation' ;
1012import { GITHUB_OAUTH_SCOPES , githubSigner , jwtSigner } from '../api/core' ;
1113
@@ -19,12 +21,30 @@ export const getServerSideProps = compose<SignInPageProps>(
1921 const { query, req } = context ;
2022 const callback = ( query . callback as string ) || '/' ;
2123
22- const result = await next ( ) ;
24+ // If there is a `code` param, this is the OAuth callback — run the auth
25+ // middleware chain (githubSigner exchanges the code for a token cookie,
26+ // jwtSigner then signs a JWT and returns jwtPayload in props).
27+ if ( query . code ) {
28+ const result = await next ( ) ;
2329
24- if ( 'props' in result && ( result . props as any ) . jwtPayload ) {
30+ if ( 'props' in result && ( result . props as any ) . jwtPayload )
31+ return { redirect : { destination : callback , permanent : false } } ;
32+
33+ return result ;
34+ }
35+
36+ // If the user is already logged in, skip the sign-in page.
37+ const { JWT : jwtCookie = '' } = req . cookies ;
38+
39+ try {
40+ verify ( jwtCookie , JWT_SECRET ! ) ;
2541 return { redirect : { destination : callback , permanent : false } } ;
42+ } catch {
43+ // Not logged in — fall through to render the sign-in page.
2644 }
2745
46+ // Build the GitHub OAuth URL pointing back to this page so the callback
47+ // lands here and is processed by the middleware chain above.
2848 const proto =
2949 ( req . headers [ 'x-forwarded-proto' ] as string ) ||
3050 ( ( req as any ) . socket ?. encrypted ? 'https' : 'http' ) ;
@@ -42,21 +62,19 @@ const SignInPage: FC<SignInPageProps> = observer(({ githubOAuthURL }) => {
4262 const { t } = useContext ( I18nContext ) ;
4363
4464 return (
45- < >
65+ < Container className = "d-flex flex-column align-items-center justify-content-center min-vh-100 gap-3" >
4666 < PageHead title = { t ( 'sign_in' ) } />
47- < Container className = "d-flex flex-column align-items-center justify-content-center min-vh-100 gap-3" >
48- < h1 > { t ( 'sign_in' ) } </ h1 >
49- < Button
50- as = "a"
51- href = { githubOAuthURL }
52- size = "lg"
53- className = "d-flex align-items-center gap-2"
54- >
55- < FontAwesomeIcon icon = { faGithub } />
56- { t ( 'sign_in_with_github' ) }
57- </ Button >
58- </ Container >
59- </ >
67+ < h1 > { t ( 'sign_in' ) } </ h1 >
68+ < Button
69+ as = "a"
70+ href = { githubOAuthURL }
71+ size = "lg"
72+ className = "d-flex align-items-center gap-2"
73+ >
74+ < FontAwesomeIcon icon = { faGithub } />
75+ { t ( 'sign_in_with' ) ( 'GitHub' ) }
76+ </ Button >
77+ </ Container >
6078 ) ;
6179} ) ;
6280
0 commit comments