Sensitive
in package
What must never be echoed into a chat channel.
The generic dispatcher can reach every repository method, which includes
streams.key — that returns the broadcaster's live stream key, and anyone
holding it can broadcast to their channel. Printing one into a public Twitch
chat would be an unrecoverable mistake made in one keystroke, so it is
guarded twice over:
- isSecret() marks whole methods whose purpose is to return a credential. Those are refused on Twitch outright and answered by DM on Discord.
- redact() runs over every rendered response regardless, masking fields whose names look like credentials. This is the one that catches the endpoint nobody thought about — including ones added to TwitchPHP after this file was last read.
Belt and braces, deliberately: the first list is a judgement about today's API surface, and it will be out of date eventually. The second is not.
Tags
Table of Contents
Constants
- SECRET_CALLS : array<int, string> = [ // The big one: a live stream key. 'streams.k...
- Methods that exist in order to hand back a credential or private detail.
- SECRET_FIELDS : array<int, string> = ['stream_key', 'key', 'secret', 'token', 'acces...
- Field names whose values are masked in any rendered response.
Methods
- isSecret() : bool
- Whether `repository.method` is one whose result is a credential.
- isSecretField() : bool
- Whether a field name looks like it holds a credential.
- redact() : mixed
- Masks credential-looking fields anywhere in a decoded response.
- mask() : string
- Replaces a value with a marker, keeping enough to be recognisable but not enough to be usable.
Constants
SECRET_CALLS
Methods that exist in order to hand back a credential or private detail.
private
array<int, string>
SECRET_CALLS
= [
// The big one: a live stream key.
'streams.key',
// Returns the authenticated user's email address when the token
// carries `user:read:email`.
'users.me',
// Pre-signed report URLs — a link is as good as the data.
'analytics.*',
// Extension configuration and signing secrets.
'extensions.*secret*',
'extensions.*jwt*',
]
Matched as repository.method, case-insensitively.
SECRET_FIELDS
Field names whose values are masked in any rendered response.
private
array<int, string>
SECRET_FIELDS
= ['stream_key', 'key', 'secret', 'token', 'access_token', 'refresh_token', 'client_secret', 'password', 'email', 'url']
Methods
isSecret()
Whether `repository.method` is one whose result is a credential.
public
static isSecret(string $call) : bool
Parameters
- $call : string
Return values
boolisSecretField()
Whether a field name looks like it holds a credential.
public
static isSecretField(string $name) : bool
Parameters
- $name : string
Return values
boolredact()
Masks credential-looking fields anywhere in a decoded response.
public
static redact(mixed $value) : mixed
url is included in the field list, which is blunt, so it is qualified
here: only URLs carrying a query string are masked, because those are
the pre-signed ones where the signature is the credential. A plain
https://twitch.tv/foo or a profile image survives intact, since
blanking those would make half the API's output unreadable for no gain.
Parameters
- $value : mixed
mask()
Replaces a value with a marker, keeping enough to be recognisable but not enough to be usable.
private
static mask(string $field, string $value) : string
Parameters
- $field : string
- $value : string