Skip to content

Commit

Permalink
fix: close websocket with reason on invalid token (#9744)
Browse files Browse the repository at this point in the history
Signed-off-by: Matt Krick <matt.krick@gmail.com>
  • Loading branch information
mattkrick committed May 9, 2024
1 parent 47224c1 commit a5d4bad
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 62 deletions.
2 changes: 1 addition & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"@emotion/styled": "^10.0.27",
"@mattkrick/graphql-trebuchet-client": "^2.2.1",
"@mattkrick/sanitize-svg": "0.4.0",
"@mattkrick/trebuchet-client": "^3.0.2",
"@mattkrick/trebuchet-client": "3.0.1",
"@mui/icons-material": "^5.8.4",
"@mui/material": "^5.9.2",
"@mui/x-date-pickers": "^6.3.1",
Expand Down
27 changes: 26 additions & 1 deletion packages/server/socketHandlers/handleOpen.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,46 @@
import {WebSocketBehavior} from 'uWebSockets.js'
import {TrebuchetCloseReason} from '../../client/types/constEnums'
import activeClients from '../activeClients'
import AuthToken from '../database/types/AuthToken'
import ConnectionContext from '../socketHelpers/ConnectionContext'
import keepAlive from '../socketHelpers/keepAlive'
import {sendEncodedMessage} from '../socketHelpers/sendEncodedMessage'
import {isAuthenticated} from '../utils/authorization'
import checkBlacklistJWT from '../utils/checkBlacklistJWT'
import sendToSentry from '../utils/sendToSentry'
import handleConnect from './handleConnect'

const APP_VERSION = process.env.npm_package_version
export type SocketUserData = {
connectionContext: ConnectionContext
authToken: AuthToken
ip: string
protocol: string
done?: true
}

const handleOpen: WebSocketBehavior<SocketUserData>['open'] = async (socket) => {
const {authToken, ip} = socket.getUserData()
const {authToken, ip, protocol} = socket.getUserData()
if (protocol !== 'trebuchet-ws') {
sendToSentry(new Error(`WebSocket error: invalid protocol: ${protocol}`))
// WS Error 1002 is roughly HTTP 412 Precondition Failed because we can't support the req header
socket.end(412, 'Invalid protocol')
return
}

if (!isAuthenticated(authToken)) {
socket.end(401, TrebuchetCloseReason.EXPIRED_SESSION)
return
}

// ALL async calls must come after the message listener, or we'll skip out on messages (e.g. resub after server restart)
const {sub: userId, iat} = authToken
const isBlacklistedJWT = await checkBlacklistJWT(userId, iat)
if (isBlacklistedJWT) {
socket.end(401, TrebuchetCloseReason.EXPIRED_SESSION)
return
}

const connectionContext = (socket.getUserData().connectionContext = new ConnectionContext(
socket,
authToken,
Expand Down
32 changes: 4 additions & 28 deletions packages/server/socketHandlers/handleUpgrade.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,14 @@
import {WebSocketBehavior} from 'uWebSockets.js'
import {TrebuchetCloseReason} from '../../client/types/constEnums'
import safetyPatchRes from '../safetyPatchRes'
import {isAuthenticated} from '../utils/authorization'
import checkBlacklistJWT from '../utils/checkBlacklistJWT'
import getQueryToken from '../utils/getQueryToken'
import sendToSentry from '../utils/sendToSentry'
import uwsGetIP from '../utils/uwsGetIP'

const handleUpgrade: WebSocketBehavior<void>['upgrade'] = async (res, req, context) => {
safetyPatchRes(res)
const protocol = req.getHeader('sec-websocket-protocol')
if (protocol !== 'trebuchet-ws') {
sendToSentry(new Error(`WebSocket error: invalid protocol: ${protocol}`))
// WS Error 1002 is roughly HTTP 412 Precondition Failed because we can't support the req header
res.writeStatus('412').end()
return
}
const authToken = getQueryToken(req)
if (!isAuthenticated(authToken)) {
res.writeStatus('401').end()
return
}

const handleUpgrade: WebSocketBehavior<void>['upgrade'] = (res, req, context) => {
const key = req.getHeader('sec-websocket-key')
const protocol = req.getHeader('sec-websocket-protocol')
const extensions = req.getHeader('sec-websocket-extensions')
const ip = uwsGetIP(res, req)
const {sub: userId, iat} = authToken
// ALL async calls must come after the message listener, or we'll skip out on messages (e.g. resub after server restart)
const isBlacklistedJWT = await checkBlacklistJWT(userId, iat)
if (isBlacklistedJWT) {
res.writeStatus('401').end(TrebuchetCloseReason.EXPIRED_SESSION)
return
}
res.upgrade({ip, authToken}, key, protocol, extensions, context)
const authToken = getQueryToken(req)
res.upgrade({ip, authToken, protocol}, key, protocol, extensions, context)
}

export default handleUpgrade
39 changes: 7 additions & 32 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4980,10 +4980,10 @@
resolved "https://registry.yarnpkg.com/@mattkrick/sanitize-svg/-/sanitize-svg-0.4.0.tgz#388c29614cf72aa0dd9803c77c9c9d070bd3cd2d"
integrity sha512-TnPI97WVAxo8SQcPy8aV3OF9/2WjXB5/+pRNVudIWR7Bhi5ZjtR/ur162So08GkvsvB914AXCW2sxFh1x6KhHA==

"@mattkrick/trebuchet-client@^3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@mattkrick/trebuchet-client/-/trebuchet-client-3.0.2.tgz#336d687256fb9ac7bb407f656bf2f69f35f817e1"
integrity sha512-JLOx8gd+cGkDeHhdnns0oor2UNv5uRZ8A/Jfw3NhQcVqQe6R+x9xIHW29M2T78TDHUWqItTgntX+cdDLqVjVvg==
"@mattkrick/trebuchet-client@3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@mattkrick/trebuchet-client/-/trebuchet-client-3.0.1.tgz#3fc49f7858652a55dca92cb0c14c0313df931619"
integrity sha512-5uHCldCqmVntoyujTzRfmGtjld8k4JuBdFN0SvhvRFf83FPaNeoit6Mh8VgrcxxxKujKeYCQDMQH6LWwpsshgQ==
dependencies:
"@mattkrick/fast-rtc-peer" "^0.4.1"
eventemitter3 "^4.0.7"
Expand Down Expand Up @@ -20311,7 +20311,7 @@ string-similarity@^3.0.0:
resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-3.0.0.tgz#07b0bc69fae200ad88ceef4983878d03793847c7"
integrity sha512-7kS7LyTp56OqOI2BDWQNVnLX/rCxIQn+/5M0op1WV6P8Xx6TZNdajpuqQdiJ7Xx+p1C5CsWMvdiBp9ApMhxzEQ==

"string-width-cjs@npm:string-width@^4.2.0":
"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
Expand All @@ -20329,15 +20329,6 @@ string-width@^1.0.1:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"

"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"

string-width@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.0.tgz#5ab00980cfb29f43e736b113a120a73a0fb569d3"
Expand Down Expand Up @@ -20414,7 +20405,7 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"

"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
Expand All @@ -20428,13 +20419,6 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1:
dependencies:
ansi-regex "^2.0.0"

strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"

strip-ansi@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2"
Expand Down Expand Up @@ -22287,7 +22271,7 @@ workbox-window@6.5.4:
"@types/trusted-types" "^2.0.2"
workbox-core "6.5.4"

"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
Expand All @@ -22305,15 +22289,6 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
Expand Down

0 comments on commit a5d4bad

Please sign in to comment.