Skip to content

Commit

Permalink
wip(EAV-243): add HTTP oauth
Browse files Browse the repository at this point in the history
  • Loading branch information
ianshade committed May 24, 2024
1 parent c782645 commit 0ad6b7a
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export interface HTTPSendOptions {
*/
resendTime?: number
makeReadyCommands?: HTTPSendCommandContent[]
oauthTokenHost?: string
oauthClientId?: string
oauthClientSecret?: string
oauthAudience?: string
}
export interface HTTPSendCommandContent {
type: TimelineContentTypeHTTP
Expand Down
2 changes: 2 additions & 0 deletions packages/timeline-state-resolver/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
"p-all": "^3.0.0",
"p-queue": "^6.6.2",
"p-timeout": "^3.2.0",
"simple-oauth2": "^5.0.0",
"sprintf-js": "^1.1.2",
"superfly-timeline": "^8.3.1",
"threadedclass": "^1.2.1",
Expand All @@ -129,6 +130,7 @@
]
},
"devDependencies": {
"@types/simple-oauth2": "^5.0.7",
"i18next-conv": "^13.1.1",
"i18next-parser": "^6.6.0",
"json-schema-to-typescript": "^10.1.5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,22 @@
"required": ["type", "url", "params"],
"additionalProperties": false
}
},
"oauthTokenHost": {
"type": "string",
"ui:title": "OAuth Token Host"
},
"oauthClientId": {
"type": "string",
"ui:title": "OAuth Client ID"
},
"oauthClientSecret": {
"type": "string",
"ui:title": "OAuth Client Secret"
},
"oauthAudience": {
"type": "string",
"ui:title": "OAuth Audience"
}
},
"required": ["host"],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { HTTPSendOptions } from 'timeline-state-resolver-types'
import { HTTPSendDevice, HttpSendDeviceCommand } from '.'
import { AccessToken, ClientCredentials } from 'simple-oauth2'

export class AuthenticatedHTTPSendDevice extends HTTPSendDevice {
private tokenPromise: Promise<AccessToken> | undefined
private authOptions: { clientId: string; clientSecret: string; tokenHost: string; audience?: string } | undefined

async init(options: HTTPSendOptions): Promise<boolean> {
if (options.oauthClientId && options.oauthClientSecret && options.oauthTokenHost) {
this.authOptions = {
clientId: options.oauthClientId,
clientSecret: options.oauthClientSecret,
audience: options.oauthAudience,
tokenHost: options.oauthTokenHost,
}
const promise = this.requestAccessToken()
promise.catch(
(e) => {
this.emit('error', 'AuthenticatedHTTPSendDevice', e)
}
// retry
)
this.tokenPromise = promise
}
return super.init(options)
}

async requestAccessToken(): Promise<AccessToken> {
if (!this.authOptions) {
throw Error('authOptions missing')
}
const token = await new ClientCredentials({
client: {
id: this.authOptions.clientId,
secret: this.authOptions.clientSecret,
},
auth: {
tokenHost: this.authOptions.tokenHost,
},
}).getToken({})
return token
}

async sendCommand({ tlObjId, context, command }: HttpSendDeviceCommand): Promise<void> {
if (this.options) {
const bearerToken = await this.tokenPromise
if (bearerToken) {
if (bearerToken.expired()) {
// todo: this should happen only once
this.tokenPromise = bearerToken.refresh()
}
command = {
...command,
content: {
...command.content,
headers: { ...command.content.headers, ['Authorization']: `Bearer ${bearerToken.token.access_token}` },
},
}
}
}
return super.sendCommand({ tlObjId, context, command })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ export class HTTPSendDevice
extends EventEmitter<DeviceEvents>
implements Device<HTTPSendOptions, HttpSendDeviceState, HttpSendDeviceCommand>
{
private options: HTTPSendOptions
protected options: HTTPSendOptions
/** Maps layers -> sent command-hashes */
private trackedState = new Map<string, string>()
private _terminated = false
protected trackedState = new Map<string, string>()
protected _terminated = false

async init(options: HTTPSendOptions): Promise<boolean> {
this.options = options
Expand Down
4 changes: 2 additions & 2 deletions packages/timeline-state-resolver/src/service/devices.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { OscDevice } from '../integrations/osc'
import { HTTPSendDevice } from '../integrations/httpSend'
import { DeviceType } from 'timeline-state-resolver-types'
import { Device } from './device'
import { AuthenticatedHTTPSendDevice } from '../integrations/httpSend/AuthenticatedHTTPSendDevice'

export interface DeviceEntry {
deviceClass: new () => Device<any, any, any>
Expand All @@ -21,7 +21,7 @@ export const DevicesDict: Record<ImplementedDeviceTypes, DeviceEntry> = {
executionMode: () => 'salvo',
},
[DeviceType.HTTPSEND]: {
deviceClass: HTTPSendDevice,
deviceClass: AuthenticatedHTTPSendDevice,
canConnect: false,
deviceName: (deviceId: string) => 'HTTPSend ' + deviceId,
executionMode: () => 'sequential', // todo - config?
Expand Down
114 changes: 114 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,63 @@ __metadata:
languageName: node
linkType: hard

"@hapi/boom@npm:^10.0.1":
version: 10.0.1
resolution: "@hapi/boom@npm:10.0.1"
dependencies:
"@hapi/hoek": ^11.0.2
checksum: c80f76e86386c65fb5e3f2aae489e82c318615b52c1462af913b1db3d05ebf1564336e2cd88f1ee79d66a8b6f48fa075089c617bfe93ad88e6e1a695d0cde499
languageName: node
linkType: hard

"@hapi/bourne@npm:^3.0.0":
version: 3.0.0
resolution: "@hapi/bourne@npm:3.0.0"
checksum: 7174cab6c33191918fcdb1953fe3169a1106e6ac79a67ef5fd08b351f0813f8f608170f2239786cbe5519e03cdfe5ab748ea1635caa06dcd5802410295514ef8
languageName: node
linkType: hard

"@hapi/hoek@npm:^10.0.1":
version: 10.0.1
resolution: "@hapi/hoek@npm:10.0.1"
checksum: 6dbcd7ae138fc751b2d81169516668bc6e4b878bb2bfdfab5eb3d51fdfd361544cc791ff12375587bf71dbeb801810cd62105f5d744dfa457140fb1709bbea6f
languageName: node
linkType: hard

"@hapi/hoek@npm:^11.0.2":
version: 11.0.4
resolution: "@hapi/hoek@npm:11.0.4"
checksum: 67dc9782a8235e066e3885352e40faa3c239621d7de29bfc88a72aba60eeb8df76b5c05d77962c734c8b0ef3fc7f818cc692689003d270a1b73ea98ba1508c5b
languageName: node
linkType: hard

"@hapi/hoek@npm:^9.0.0, @hapi/hoek@npm:^9.3.0":
version: 9.3.0
resolution: "@hapi/hoek@npm:9.3.0"
checksum: 4771c7a776242c3c022b168046af4e324d116a9d2e1d60631ee64f474c6e38d1bb07092d898bf95c7bc5d334c5582798a1456321b2e53ca817d4e7c88bc25b43
languageName: node
linkType: hard

"@hapi/topo@npm:^5.1.0":
version: 5.1.0
resolution: "@hapi/topo@npm:5.1.0"
dependencies:
"@hapi/hoek": ^9.0.0
checksum: 604dfd5dde76d5c334bd03f9001fce69c7ce529883acf92da96f4fe7e51221bf5e5110e964caca287a6a616ba027c071748ab636ff178ad750547fba611d6014
languageName: node
linkType: hard

"@hapi/wreck@npm:^18.0.0":
version: 18.1.0
resolution: "@hapi/wreck@npm:18.1.0"
dependencies:
"@hapi/boom": ^10.0.1
"@hapi/bourne": ^3.0.0
"@hapi/hoek": ^11.0.2
checksum: 08e20e829a46fcdd1595b7181d3c0f94bc1cd2966aaf272138a6b80fa5266852295189295169903be20ef53bb35ba7b9a9080ce7e1147116ffce4db492b99bec
languageName: node
linkType: hard

"@humanwhocodes/config-array@npm:^0.11.8":
version: 0.11.8
resolution: "@humanwhocodes/config-array@npm:0.11.8"
Expand Down Expand Up @@ -1577,6 +1634,29 @@ __metadata:
languageName: node
linkType: hard

"@sideway/address@npm:^4.1.5":
version: 4.1.5
resolution: "@sideway/address@npm:4.1.5"
dependencies:
"@hapi/hoek": ^9.0.0
checksum: 3e3ea0f00b4765d86509282290368a4a5fd39a7995fdc6de42116ca19a96120858e56c2c995081def06e1c53e1f8bccc7d013f6326602bec9d56b72ee2772b9d
languageName: node
linkType: hard

"@sideway/formula@npm:^3.0.1":
version: 3.0.1
resolution: "@sideway/formula@npm:3.0.1"
checksum: e4beeebc9dbe2ff4ef0def15cec0165e00d1612e3d7cea0bc9ce5175c3263fc2c818b679bd558957f49400ee7be9d4e5ac90487e1625b4932e15c4aa7919c57a
languageName: node
linkType: hard

"@sideway/pinpoint@npm:^2.0.0":
version: 2.0.0
resolution: "@sideway/pinpoint@npm:2.0.0"
checksum: 0f4491e5897fcf5bf02c46f5c359c56a314e90ba243f42f0c100437935daa2488f20482f0f77186bd6bf43345095a95d8143ecf8b1f4d876a7bc0806aba9c3d2
languageName: node
linkType: hard

"@sigstore/protobuf-specs@npm:^0.1.0":
version: 0.1.0
resolution: "@sigstore/protobuf-specs@npm:0.1.0"
Expand Down Expand Up @@ -1934,6 +2014,13 @@ __metadata:
languageName: node
linkType: hard

"@types/simple-oauth2@npm:^5.0.7":
version: 5.0.7
resolution: "@types/simple-oauth2@npm:5.0.7"
checksum: 4d02d4473465589f51039889bb1a4aed3d7929c43cd16a595a09f154502bae2fc348d41be0b06ffdd0bbb1648be63fa617d2c2715d7a4f7e57244cd0d30576a9
languageName: node
linkType: hard

"@types/sprintf-js@npm:^1.1.2":
version: 1.1.2
resolution: "@types/sprintf-js@npm:1.1.2"
Expand Down Expand Up @@ -6893,6 +6980,19 @@ asn1@evs-broadcast/node-asn1:
languageName: node
linkType: hard

"joi@npm:^17.6.4":
version: 17.13.1
resolution: "joi@npm:17.13.1"
dependencies:
"@hapi/hoek": ^9.3.0
"@hapi/topo": ^5.1.0
"@sideway/address": ^4.1.5
"@sideway/formula": ^3.0.1
"@sideway/pinpoint": ^2.0.0
checksum: e755140446a0e0fb679c0f512d20dfe1625691de368abe8069507c9bccae5216b5bb56b5a83100a600808b1753ab44fdfdc9933026268417f84b6e0832a9604e
languageName: node
linkType: hard

"js-sdsl@npm:^4.1.4":
version: 4.4.0
resolution: "js-sdsl@npm:4.4.0"
Expand Down Expand Up @@ -10321,6 +10421,18 @@ asn1@evs-broadcast/node-asn1:
languageName: node
linkType: hard

"simple-oauth2@npm:^5.0.0":
version: 5.0.0
resolution: "simple-oauth2@npm:5.0.0"
dependencies:
"@hapi/hoek": ^10.0.1
"@hapi/wreck": ^18.0.0
debug: ^4.3.4
joi: ^17.6.4
checksum: 1cdf7fba0c8e7d1f5d4eb39507ad9cbafc0347813b4bdf067e853514cbd12f2770c278719ec508f2f055e5b60dd10ef153f75a477c2fd59345e5b8d2d82e8248
languageName: node
linkType: hard

"sisteransi@npm:^1.0.5":
version: 1.0.5
resolution: "sisteransi@npm:1.0.5"
Expand Down Expand Up @@ -11045,6 +11157,7 @@ asn1@evs-broadcast/node-asn1:
resolution: "timeline-state-resolver@workspace:packages/timeline-state-resolver"
dependencies:
"@tv2media/v-connection": ^7.3.2
"@types/simple-oauth2": ^5.0.7
atem-connection: 2.5.0
atem-state: 0.13.0
casparcg-connection: 6.2.1
Expand All @@ -11064,6 +11177,7 @@ asn1@evs-broadcast/node-asn1:
p-all: ^3.0.0
p-queue: ^6.6.2
p-timeout: ^3.2.0
simple-oauth2: ^5.0.0
sprintf-js: ^1.1.2
superfly-timeline: ^8.3.1
threadedclass: ^1.2.1
Expand Down

0 comments on commit 0ad6b7a

Please sign in to comment.