From 75534aa5d39098cdc867a0c6091001e4ce74e01b Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 2 Nov 2023 00:42:45 +1100 Subject: [PATCH 1/3] login screen is working now --- client/src/components/navbar/Navbar.tsx | 25 +++++++++++++++++- client/src/interfaces/Users.ts | 10 ++++++++ server/docker-compose.yml | 22 ++++++++-------- server/src/auth/auth.controller.ts | 34 +++++++++++++------------ server/src/auth/login.guard.ts | 6 +++-- 5 files changed, 67 insertions(+), 30 deletions(-) create mode 100644 client/src/interfaces/Users.ts diff --git a/client/src/components/navbar/Navbar.tsx b/client/src/components/navbar/Navbar.tsx index 8d1187d21..7824e547c 100644 --- a/client/src/components/navbar/Navbar.tsx +++ b/client/src/components/navbar/Navbar.tsx @@ -1,5 +1,5 @@ import { Description, Info, Security, Settings as SettingsIcon } from '@mui/icons-material'; -import { AppBar, Toolbar, Typography, useMediaQuery, useTheme } from '@mui/material'; +import { AppBar, Button, Toolbar, Typography, useMediaQuery, useTheme } from '@mui/material'; import { styled } from '@mui/system'; import React, { useContext, useState } from 'react'; @@ -12,6 +12,7 @@ import Changelog from './Changelog'; import CustomModal from './CustomModal'; import Privacy from './Privacy'; import Settings from './Settings'; +import { User } from '../../interfaces/Users'; const LogoImg = styled('img')` height: 46px; @@ -51,9 +52,22 @@ const Weak = styled('span')` const Navbar: React.FC = () => { const [currLogo, setCurrLogo] = useState(notanglesLogo); const { term, termName, year } = useContext(AppContext); + const userData: User = {}; + const [user, setUser] = useState(userData); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const login = () => { + window.location.replace('http://localhost:3001/api/login'); + }; + const logout = () => { + window.location.replace('http://localhost:3001/api/logout'); + }; + // https://stackoverflow.com/a/32108184/1098564 + const isEmpty = (obj: Object) => { + return Object.keys(obj).length === 0 && obj.constructor === Object; + }; + return ( @@ -82,6 +96,15 @@ const Navbar: React.FC = () => { content={} /> } description={'Settings'} content={} /> + {isEmpty(user) ? ( + + ) : ( + + )} diff --git a/client/src/interfaces/Users.ts b/client/src/interfaces/Users.ts new file mode 100644 index 000000000..b610b989f --- /dev/null +++ b/client/src/interfaces/Users.ts @@ -0,0 +1,10 @@ +export interface User { + id_token?: string; + access_token?: string; + refresh_token?: string; + userinfo?: UserInfo; +} + +export interface UserInfo { + name?: string; +} diff --git a/server/docker-compose.yml b/server/docker-compose.yml index 96ccbc28c..c00bc5895 100644 --- a/server/docker-compose.yml +++ b/server/docker-compose.yml @@ -1,16 +1,16 @@ version: '3.7' services: - server: - container_name: notangles-server - image: notangles-server - restart: always - build: . - depends_on: - - database.notangles-db - ports: - - '3001:3001' - links: - - database.notangles-db + # server: + # container_name: notangles-server + # image: notangles-server + # restart: always + # build: . + # depends_on: + # - database.notangles-db + # ports: + # - '3001:3001' + # links: + # - database.notangles-db database.notangles-db: container_name: notangles-database diff --git a/server/src/auth/auth.controller.ts b/server/src/auth/auth.controller.ts index a7bd1430d..39bed7c59 100644 --- a/server/src/auth/auth.controller.ts +++ b/server/src/auth/auth.controller.ts @@ -1,6 +1,7 @@ import { Controller, Get, + Logger, Request, Res, UseGuards, @@ -11,42 +12,43 @@ import { LoginGuard } from './login.guard'; import { Issuer } from 'openid-client'; import { AuthDto } from './dtos'; -@Controller() +@Controller('auth') export class AuthController { - @UseGuards(LoginGuard) @Get('/login') login() {} @Get('/user') user(@Request() req) { - return req.user + return req.user; } - + @UseGuards(LoginGuard) - @Get('/callback') + @Get('/callback/csesoc') loginCallback(@Res() res: Response) { res.redirect('/'); } - + @Get('/logout') async logout(@Request() req, @Res() res: Response) { const id_token = req.user ? req.user.id_token : undefined; req.logout(); req.session.destroy(async (error: any) => { - const TrustIssuer = await Issuer.discover(`${process.env.OAUTH2_CLIENT_PROVIDER_OIDC_ISSUER}/.well-known/openid-configuration`); + const TrustIssuer = await Issuer.discover( + `${process.env.OAUTH2_CLIENT_PROVIDER_OIDC_ISSUER}/.well-known/openid-configuration`, + ); const end_session_endpoint = TrustIssuer.metadata.end_session_endpoint; if (end_session_endpoint) { - res.redirect(end_session_endpoint + - '?post_logout_redirect_uri=' + process.env.OAUTH2_CLIENT_REGISTRATION_LOGIN_POST_LOGOUT_REDIRECT_URI + - (id_token ? '&id_token_hint=' + id_token : '')); + res.redirect( + end_session_endpoint + + '?post_logout_redirect_uri=' + + process.env + .OAUTH2_CLIENT_REGISTRATION_LOGIN_POST_LOGOUT_REDIRECT_URI + + (id_token ? '&id_token_hint=' + id_token : ''), + ); } else { - res.redirect('/') + res.redirect('/'); } - }) + }); } } - - - - diff --git a/server/src/auth/login.guard.ts b/server/src/auth/login.guard.ts index 054999993..e35347826 100644 --- a/server/src/auth/login.guard.ts +++ b/server/src/auth/login.guard.ts @@ -1,4 +1,4 @@ -import { ExecutionContext, Injectable } from '@nestjs/common'; +import { ExecutionContext, Injectable, Logger } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; @Injectable() @@ -6,7 +6,9 @@ export class LoginGuard extends AuthGuard('oidc') { async canActivate(context: ExecutionContext) { const result = (await super.canActivate(context)) as boolean; const request = context.switchToHttp().getRequest(); + Logger.log('TESTTEST'); + await super.logIn(request); return result; } -} \ No newline at end of file +} From 7b789ac95c49a37dd5aa16441a5612f96e8b2688 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 2 Nov 2023 00:53:30 +1100 Subject: [PATCH 2/3] login screen is working now --- client/src/components/navbar/Navbar.tsx | 4 ++-- server/src/auth/login.guard.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/components/navbar/Navbar.tsx b/client/src/components/navbar/Navbar.tsx index 7824e547c..bc99b5b7c 100644 --- a/client/src/components/navbar/Navbar.tsx +++ b/client/src/components/navbar/Navbar.tsx @@ -58,10 +58,10 @@ const Navbar: React.FC = () => { const isMobile = useMediaQuery(theme.breakpoints.down('sm')); const login = () => { - window.location.replace('http://localhost:3001/api/login'); + window.location.replace('http://localhost:3001/api/auth/login'); }; const logout = () => { - window.location.replace('http://localhost:3001/api/logout'); + window.location.replace('http://localhost:3001/api/auth/logout'); }; // https://stackoverflow.com/a/32108184/1098564 const isEmpty = (obj: Object) => { diff --git a/server/src/auth/login.guard.ts b/server/src/auth/login.guard.ts index e35347826..c505ead5f 100644 --- a/server/src/auth/login.guard.ts +++ b/server/src/auth/login.guard.ts @@ -4,9 +4,10 @@ import { AuthGuard } from '@nestjs/passport'; @Injectable() export class LoginGuard extends AuthGuard('oidc') { async canActivate(context: ExecutionContext) { + Logger.log('TESTTEST'); + const result = (await super.canActivate(context)) as boolean; const request = context.switchToHttp().getRequest(); - Logger.log('TESTTEST'); await super.logIn(request); return result; From ca9d38f94aedfb53f1b80104cb52405417cde958 Mon Sep 17 00:00:00 2001 From: Rayahhhmed Date: Thu, 2 Nov 2023 11:50:37 +1100 Subject: [PATCH 3/3] need to fix the cookie issue and logout uri --- server/package.json | 1 + server/pnpm-lock.yaml | 63 +++++++++++++++++++++++++++++- server/src/auth/auth.controller.ts | 44 ++++++++++++--------- server/src/auth/login.guard.ts | 2 - server/src/auth/oidc.strategy.ts | 3 +- server/src/main.ts | 3 +- 6 files changed, 93 insertions(+), 23 deletions(-) diff --git a/server/package.json b/server/package.json index fc07c1476..bb196584c 100644 --- a/server/package.json +++ b/server/package.json @@ -45,6 +45,7 @@ "google-protobuf": "3.21.2", "grpc-tools": "1.12.4", "grpc_tools_node_protoc_ts": "5.3.3", + "http-proxy-middleware": "2.0.6", "minimist": "1.2.8", "openid-client": "5.6.1", "passport": "0.6.0", diff --git a/server/pnpm-lock.yaml b/server/pnpm-lock.yaml index 0626dd014..8baf9541b 100644 --- a/server/pnpm-lock.yaml +++ b/server/pnpm-lock.yaml @@ -71,6 +71,9 @@ dependencies: grpc_tools_node_protoc_ts: specifier: 5.3.3 version: 5.3.3 + http-proxy-middleware: + specifier: 2.0.6 + version: 2.0.6(@types/express@4.17.17) minimist: specifier: 1.2.8 version: 1.2.8 @@ -738,6 +741,12 @@ packages: /@types/http-errors@2.0.1: resolution: {integrity: sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==} + /@types/http-proxy@1.17.13: + resolution: {integrity: sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==} + dependencies: + '@types/node': 18.17.12 + dev: false + /@types/istanbul-lib-coverage@2.0.4: resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} dev: true @@ -1620,6 +1629,10 @@ packages: engines: {node: '>= 0.6'} dev: false + /eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + dev: false + /events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -1755,6 +1768,16 @@ packages: - supports-color dev: false + /follow-redirects@1.15.3: + resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + /fork-ts-checker-webpack-plugin@8.0.0(typescript@5.1.6)(webpack@5.88.2): resolution: {integrity: sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==} engines: {node: '>=12.13.0', yarn: '>=1.0.0'} @@ -1978,6 +2001,36 @@ packages: toidentifier: 1.0.1 dev: false + /http-proxy-middleware@2.0.6(@types/express@4.17.17): + resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/express': ^4.17.13 + peerDependenciesMeta: + '@types/express': + optional: true + dependencies: + '@types/express': 4.17.17 + '@types/http-proxy': 1.17.13 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.5 + transitivePeerDependencies: + - debug + dev: false + + /http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.3 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + dev: false + /https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -2118,6 +2171,11 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + /is-plain-obj@3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + dev: false + /is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -2349,7 +2407,6 @@ packages: dependencies: braces: 3.0.2 picomatch: 2.3.1 - dev: true /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} @@ -2866,6 +2923,10 @@ packages: engines: {node: '>=0.10.0'} dev: false + /requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + dev: false + /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} diff --git a/server/src/auth/auth.controller.ts b/server/src/auth/auth.controller.ts index 39bed7c59..717352b84 100644 --- a/server/src/auth/auth.controller.ts +++ b/server/src/auth/auth.controller.ts @@ -11,7 +11,7 @@ import { Response } from 'express'; import { LoginGuard } from './login.guard'; import { Issuer } from 'openid-client'; import { AuthDto } from './dtos'; - +const REDIRECT_LINK = 'http://localhost:5173/'; @Controller('auth') export class AuthController { @UseGuards(LoginGuard) @@ -20,35 +20,43 @@ export class AuthController { @Get('/user') user(@Request() req) { + return req.user; } @UseGuards(LoginGuard) @Get('/callback/csesoc') loginCallback(@Res() res: Response) { - res.redirect('/'); + res.redirect(REDIRECT_LINK); } @Get('/logout') async logout(@Request() req, @Res() res: Response) { + console.log("logout"); const id_token = req.user ? req.user.id_token : undefined; - req.logout(); - req.session.destroy(async (error: any) => { - const TrustIssuer = await Issuer.discover( - `${process.env.OAUTH2_CLIENT_PROVIDER_OIDC_ISSUER}/.well-known/openid-configuration`, - ); - const end_session_endpoint = TrustIssuer.metadata.end_session_endpoint; - if (end_session_endpoint) { - res.redirect( - end_session_endpoint + - '?post_logout_redirect_uri=' + - process.env - .OAUTH2_CLIENT_REGISTRATION_LOGIN_POST_LOGOUT_REDIRECT_URI + - (id_token ? '&id_token_hint=' + id_token : ''), - ); - } else { - res.redirect('/'); + req.logout((err) => { + if (err) { + console.log(err + "omahgod errors"); } + req.session.destroy(async (error: any) => { + const TrustIssuer = await Issuer.discover( + `${process.env.OAUTH2_CLIENT_PROVIDER_OIDC_ISSUER}/.well-known/openid-configuration`, + ); + const end_session_endpoint = TrustIssuer.metadata.end_session_endpoint; + console.log(id_token); + if (end_session_endpoint) { + res.redirect( + end_session_endpoint + + '?post_logout_redirect_uri=' + + process.env + .OAUTH2_CLIENT_REGISTRATION_LOGIN_POST_LOGOUT_REDIRECT_URI + + (id_token ? '&id_token_hint=' + id_token : ''), + ); + } else { + res.redirect(REDIRECT_LINK); + } + }); }); + } } diff --git a/server/src/auth/login.guard.ts b/server/src/auth/login.guard.ts index c505ead5f..95757613e 100644 --- a/server/src/auth/login.guard.ts +++ b/server/src/auth/login.guard.ts @@ -4,11 +4,9 @@ import { AuthGuard } from '@nestjs/passport'; @Injectable() export class LoginGuard extends AuthGuard('oidc') { async canActivate(context: ExecutionContext) { - Logger.log('TESTTEST'); const result = (await super.canActivate(context)) as boolean; const request = context.switchToHttp().getRequest(); - await super.logIn(request); return result; } diff --git a/server/src/auth/oidc.strategy.ts b/server/src/auth/oidc.strategy.ts index 6f27d0821..badeac349 100644 --- a/server/src/auth/oidc.strategy.ts +++ b/server/src/auth/oidc.strategy.ts @@ -32,7 +32,7 @@ export class OidcStrategy extends PassportStrategy(Strategy, 'oidc') { async validate(tokenset: TokenSet): Promise { const userinfo: UserinfoResponse = await this.client.userinfo(tokenset); - console.log("test"); + try { const id_token = tokenset.id_token const access_token = tokenset.access_token @@ -43,6 +43,7 @@ export class OidcStrategy extends PassportStrategy(Strategy, 'oidc') { refresh_token, userinfo, } + // console.log(user); return user; } catch (err) { throw new UnauthorizedException(); diff --git a/server/src/main.ts b/server/src/main.ts index 6e2f09b2b..02bae9a10 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -27,7 +27,8 @@ async function bootstrap() { rolling: true, // keep session alive cookie: { maxAge: 30 * 60 * 1000, // session expires in 1hr, refreshed by `rolling: true` option. - httpOnly: true, // so that cookie can't be accessed via client-side script + httpOnly: false, // so that cookie can't be accessed via client-side script + sameSite: true } })); app.use(passport.initialize());