fix: remove special character requirement from stream keys (#4754)

Some broadcasting software (e.g., Prism Live Studio) strips special
characters from stream keys, making Owncast-generated keys incompatible.

Changes:
- Create separate STREAM_KEY_COMPLEXITY_RULES without special char requirement
- Update generateRndKey() to only use alphanumeric characters
- Keep PASSWORD_COMPLEXITY_RULES unchanged for admin password security
- Update tooltip text to reflect new requirements
- Add comprehensive tests for stream key generation

Fixes #4690

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
John Costa
2026-01-28 11:51:57 -08:00
committed by GitHub
co-authored by Claude Opus 4.5
parent 93b482871f
commit 397ec95d9b
3 changed files with 64 additions and 20 deletions
+32 -3
View File
@@ -1,10 +1,23 @@
import { generateRndKey } from '../components/admin/config/server/StreamKeys';
import { REGEX_STREAM_KEY } from '../utils/config-constants';
describe('generateRndKey', () => {
test('should generate a key that matches the regular expression', () => {
test('should generate a key that matches the stream key regex', () => {
const key = generateRndKey();
const regex = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!@#$^&*]).{8,192}$/;
expect(regex.test(key)).toBe(true);
// Use the same regex constant that the implementation uses
expect(REGEX_STREAM_KEY.test(key)).toBe(true);
});
test('should only contain alphanumeric characters (no special characters for broadcasting software compatibility)', () => {
const key = generateRndKey();
// Keys should be purely alphanumeric for compatibility with broadcasting software
expect(key).toMatch(/^[a-zA-Z0-9]+$/);
});
test('should not contain dashes', () => {
const key = generateRndKey();
// Dashes are explicitly forbidden as they can break RTMP URL parsing
expect(key).not.toContain('-');
});
test('returns a string', () => {
@@ -23,4 +36,20 @@ describe('generateRndKey', () => {
const key2 = generateRndKey();
expect(key1).not.toBe(key2);
});
test('should contain at least one uppercase letter, one lowercase letter, and one digit', () => {
const key = generateRndKey();
expect(key).toMatch(/[A-Z]/); // has uppercase
expect(key).toMatch(/[a-z]/); // has lowercase
expect(key).toMatch(/[0-9]/); // has digit
});
test('should consistently generate valid keys across multiple invocations', () => {
// Generate multiple keys to ensure consistency
for (let i = 0; i < 10; i++) {
const key = generateRndKey();
expect(REGEX_STREAM_KEY.test(key)).toBe(true);
expect(key).toMatch(/^[a-zA-Z0-9]+$/);
}
});
});