Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7d65fd7
API Authentication/Authorization refactor
Lord-Grey Feb 20, 2023
0ee637e
Merge remote-tracking branch 'origin/master' into API_Auth
Lord-Grey Mar 17, 2024
7dccad3
Define default user and password as constants
Lord-Grey Mar 17, 2024
b056e12
Generate random TANS for every call
Lord-Grey Apr 11, 2024
4d90309
Fix dialog does not close
Lord-Grey Apr 11, 2024
d29a747
Refactor JSON-API and cleanups
Lord-Grey Apr 23, 2024
69f8b1f
Support direct instance addressing requests
Lord-Grey Apr 23, 2024
ec6a65b
JsonUtils.cpp aktualisieren
Lord-Grey Apr 23, 2024
7a604ee
Add Event Subscriptions & Instance specific replies
Lord-Grey Apr 25, 2024
ee4b1aa
UI - Remove requestRequiresAdminAuth as now always true
Lord-Grey Apr 25, 2024
42e8095
JSON-API Commands Overview
Lord-Grey Apr 25, 2024
12499c8
Ensure valid instance number
Lord-Grey Apr 25, 2024
5ab4b11
Revert streaming subscription names
Lord-Grey Apr 26, 2024
2e4a4ea
Align LogMsg subscription command
Lord-Grey Apr 26, 2024
bdc872c
Fix missing handleTokenResponse
Lord-Grey Apr 26, 2024
c14fc06
Revert streaming subscription names (2)
Lord-Grey Apr 28, 2024
6535cdd
Support Quit event
Lord-Grey Apr 28, 2024
30bd87c
Fix authorization default for nonlistener
Lord-Grey Apr 28, 2024
9fded23
Update changelog
Lord-Grey Apr 28, 2024
173c9ee
Update changelog
Lord-Grey Apr 28, 2024
e01e3e7
Address CodeQl finding
Lord-Grey Apr 28, 2024
722d6d7
Support direct or multiple instance addressing via single requests
Lord-Grey Apr 29, 2024
12ace5e
Address CodeQL finding
Lord-Grey Apr 29, 2024
c4b88a2
Separate handleInstanceCommand out
Lord-Grey Apr 29, 2024
4208018
Correct instance handling in reply
Lord-Grey Apr 29, 2024
571863b
Fix resetSubscriptions
Lord-Grey Apr 29, 2024
f3b0223
Fix Copy/Paste issue
Lord-Grey Apr 29, 2024
64fcea3
Fix modal dialog
Lord-Grey Apr 29, 2024
7590114
Merge remote-tracking branch 'origin/master' into API_Auth
Lord-Grey May 4, 2024
3b5a165
Correct indent
Lord-Grey May 4, 2024
5fe1b15
Remove comment
Lord-Grey May 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Breaking

**JSON-API**
- Align JSON subscription update elements. `ledcolors-imagestream-update, ledcolors-ledstream-update, logmsg-update` now return data via `data` and not `result

### Added

- Support gaps on Matrix Layout (#1696)

**JSON-API**
- New subscription support for event updates, i.e. `Suspend, Resume, Idle, idleResume, Restart, Quit`.
- Support direct or multiple instance addressing via single requests (#809)
- Support of `serverinfo` subcommands: `getInfo, subscribe, unsubscribe, getSubscriptions, getSubscriptionCommands`
- [Overview](https://github.com/hyperion-project/hyperion.ng/blob/API_Auth/doc/development/JSON-API%20_Commands_Overview.md) of API commands and subscription updates

### Changed

- Fixed: Cross Site Scripting Vulnerability (CVE-2024-4174, CVE-2024-4175)
- Fixed: hyperion-v4l2 taking screenshot failed (#1722)
- Nanoleaf: Support new devices and do not restore ExtControl state
- Workaround to address Web UI keeps forcing browser to download the html instead (#1692)
- Fixed: Kodi Color Calibration, Refactor Wizards (#1674)
- Fixed: Token Dialog not closing

**JSON-API**
- Refactored JSON-API to ensure consistent authorization behaviour across sessions and single requests with token authorization.
- Provide additional error details with API responses, esp. on JSON parsing, validation or token errors.
- Generate random TANs for every API request from the Hyperion UI
- Fixed: Handling of IP4 addresses wrapped in IPv6 for external network connections-

### Removed

**JSON-API**
- Removed ability to enable/disable local admin authorization. All admin commands require authorization, i.e. `authorize-adminRequired` will always be `true`.
- Removed `session-updates` subscription
- `serverinfo/subscribe` element will be deprecated and replaced by corresponding subcommand

## [2.0.16](https://github.com/hyperion-project/hyperion.ng/releases/tag/2.0.16) - 2024-01

### Added
Expand Down
16 changes: 7 additions & 9 deletions assets/webconfig/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@
"conf_network_json_intro": "The JSON-RPC-Port of all Hyperion instances, used for remote control.",
"conf_network_net_intro": "Network related settings which are applied to all network services.",
"conf_network_proto_intro": "The PROTO-Port of all Hyperion instances, used for picture streams (HyperionScreenCap, Kodi Addon, Android Hyperion Grabber, ...)",
"conf_network_tok_idhead": "ID",
"conf_network_tok_cidhead": "Description",
"conf_network_tok_comment_title": "Token description",
"conf_network_tok_desc": "Tokens grant other applications access to the Hyperion API, an application can request a token where you need to accept it or you create them on your own below. These tokens are just required when \"API Authorization\" is enabled in network settings.",
Expand Down Expand Up @@ -500,19 +501,16 @@
"edt_conf_log_level_expl": "Depending on loglevel you see less or more messages in your log.",
"edt_conf_log_level_title": "Log-Level",
"edt_conf_net_apiAuth_expl": "Enforce all applications that use the Hyperion API to authenticate themself against Hyperion (Exception: see \"Local API Authentication\"). Higher security, as you control the access and revoke it at any time.",
"edt_conf_net_apiAuth_title": "API Authentication",
"edt_conf_net_heading_title": "Network",
"edt_conf_net_internetAccessAPI_expl": "Allow access to the Hyperion API/Webinterface from the internet. Disable for higher security.",
"edt_conf_net_internetAccessAPI_expl": "Allow access to the Hyperion API/Web Interface from the Internet. Disable for increased security.",
"edt_conf_net_internetAccessAPI_title": "Internet API Access",
"edt_conf_net_ipWhitelist_expl": "You can whitelist IP addresses instead allowing all connections from internet to connect to the Hyperion API/Webinterface.",
"edt_conf_net_ipWhitelist_title": "Whitelisted IP's",
"edt_conf_net_ipWhitelist_expl": "Define whitelisted IP addresses from which API requests from the Internet are allowed. All other external connections will be denied.",
"edt_conf_net_ipWhitelist_title": "Whitelisted IP addresses",
"edt_conf_net_ip_itemtitle": "IP",
"edt_conf_net_localAdminAuth_expl": "When enabled, administration access from your local network needs a password.",
"edt_conf_net_localAdminAuth_title": "Local Admin API Authentication",
"edt_conf_net_localApiAuth_expl": "When enabled, connections from your home network needs to authenticate themselves against Hyperion with a token.",
"edt_conf_net_localApiAuth_expl": "When disabled, API authorisation via password or token is not required for local connections. The exception is administrative commands.",
"edt_conf_net_localApiAuth_title": "Local API Authentication",
"edt_conf_net_restirctedInternetAccessAPI_expl": "You can restrict the access to the API through the internet to certain IP's.",
"edt_conf_net_restirctedInternetAccessAPI_title": "Restrict to IP's",
"edt_conf_net_restirctedInternetAccessAPI_expl": "You can restrict API requests over the Internet to only those IP addresses on the whitelist.",
"edt_conf_net_restirctedInternetAccessAPI_title": "Restrict to IP addresses",
"edt_conf_os_events_lockEnable_title": "Listen to lock events",
"edt_conf_os_events_lockEnable_expl": "Listen to screen lock/unlock events",
"edt_conf_os_events_suspendEnable_title": "Listen to suspend events",
Expand Down
53 changes: 24 additions & 29 deletions assets/webconfig/js/content_index.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,26 +73,30 @@ $(document).ready(function () {
//End language selection

$(window.hyperion).on("cmd-authorize-tokenRequest cmd-authorize-getPendingTokenRequests", function (event) {
var val = event.response.info;
if (Array.isArray(event.response.info)) {
if (event.response.info.length == 0) {
return

if (event.response && event.response.info !== undefined) {
var val = event.response.info;

if (Array.isArray(event.response.info)) {
if (event.response.info.length == 0) {
return
}
val = event.response.info[0]
if (val.comment == '')
$('#modal_dialog').modal('hide');
}
val = event.response.info[0]
if (val.comment == '')
$('#modal_dialog').modal('hide');
}

showInfoDialog("grantToken", $.i18n('conf_network_tok_grantT'), $.i18n('conf_network_tok_grantMsg') + '<br><span style="font-weight:bold">App: ' + val.comment + '</span><br><span style="font-weight:bold">Code: ' + val.id + '</span>')
$("#tok_grant_acc").off().on('click', function () {
tokenList.push(val)
// forward event, in case we need to rebuild the list now
$(window.hyperion).trigger({ type: "build-token-list" });
requestHandleTokenRequest(val.id, true)
});
$("#tok_deny_acc").off().on('click', function () {
requestHandleTokenRequest(val.id, false)
});
showInfoDialog("grantToken", $.i18n('conf_network_tok_grantT'), $.i18n('conf_network_tok_grantMsg') + '<br><span style="font-weight:bold">App: ' + val.comment + '</span><br><span style="font-weight:bold">Code: ' + val.id + '</span>')
$("#tok_grant_acc").off().on('click', function () {
tokenList.push(val)
// forward event, in case we need to rebuild the list now
$(window.hyperion).trigger({ type: "build-token-list" });
requestHandleTokenRequest(val.id, true)
});
$("#tok_deny_acc").off().on('click', function () {
requestHandleTokenRequest(val.id, false)
});
}
});

$(window.hyperion).one("cmd-authorize-getTokenList", function (event) {
Expand Down Expand Up @@ -186,21 +190,12 @@ $(document).ready(function () {
}
});

$(window.hyperion).on("cmd-authorize-adminRequired", function (event) {
//Check if a admin login is required.
//If yes: check if default pw is set. If no: go ahead to get server config and render page
if (event.response.info.adminRequired === true)
requestRequiresDefaultPasswortChange();
else
requestServerConfigSchema();
});

$(window.hyperion).on("error", function (event) {
//If we are getting an error "No Authorization" back with a set loginToken we will forward to new Login (Token is expired.
//e.g.: hyperiond was started new in the meantime)
if (event.reason == "No Authorization" && getStorage("loginToken")) {
removeStorage("loginToken");
requestRequiresAdminAuth();
requestRequiresDefaultPasswortChange();
}
else if (event.reason == "Selected Hyperion instance isn't running") {
//Switch to default instance
Expand All @@ -211,7 +206,7 @@ $(document).ready(function () {
});

$(window.hyperion).on("open", function (event) {
requestRequiresAdminAuth();
requestRequiresDefaultPasswortChange();
});

$(window.hyperion).on("ready", function (event) {
Expand Down
9 changes: 6 additions & 3 deletions assets/webconfig/js/content_logging.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ var createdCont = false;
var isScroll = true;

performTranslation();
requestLoggingStop();

$(document).ready(function () {

window.addEventListener('hashchange', function(event) {
requestLoggingStop();
});

requestLoggingStart();

$('#conf_cont').append(createOptPanel('fa-reorder', $.i18n("edt_conf_log_heading_title"), 'editor_container', 'btn_submit'));
Expand Down Expand Up @@ -178,9 +181,9 @@ $(document).ready(function () {
if (!window.loggingHandlerInstalled) {
window.loggingHandlerInstalled = true;

$(window.hyperion).on("cmd-logging-update", function (event) {
$(window.hyperion).on("cmd-logmsg-update", function (event) {

var messages = (event.response.result.messages);
var messages = (event.response.data.messages);

if (messages.length != 0) {
if (!createdCont) {
Expand Down
4 changes: 2 additions & 2 deletions assets/webconfig/js/content_network.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,13 +213,13 @@ $(document).ready(function () {
for (var key in tokenList) {
var lastUse = (tokenList[key].last_use) ? tokenList[key].last_use : "-";
var btn = '<button id="tok' + tokenList[key].id + '" type="button" class="btn btn-danger">' + $.i18n('general_btn_delete') + '</button>';
$('.tktbody').append(createTableRow([tokenList[key].comment, lastUse, btn], false, true));
$('.tktbody').append(createTableRow([tokenList[key].id, tokenList[key].comment, lastUse, btn], false, true));
$('#tok' + tokenList[key].id).off().on('click', handleDeleteToken);
}
}

createTable('tkthead', 'tktbody', 'tktable');
$('.tkthead').html(createTableRow([$.i18n('conf_network_tok_cidhead'), $.i18n('conf_network_tok_lastuse'), $.i18n('general_btn_delete')], true, true));
$('.tkthead').html(createTableRow([$.i18n('conf_network_tok_idhead'), $.i18n('conf_network_tok_cidhead'), $.i18n('conf_network_tok_lastuse'), $.i18n('general_btn_delete')], true, true));
buildTokenList();

function handleDeleteToken(e) {
Expand Down
15 changes: 8 additions & 7 deletions assets/webconfig/js/hyperion.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ function sendToHyperion(command, subcommand, msg)
else
msg = "";

window.wsTan = Math.floor(Math.random() * 1000)
window.websocket.send('{"command":"'+command+'", "tan":'+window.wsTan+subcommand+msg+'}');
}

Expand All @@ -187,7 +188,7 @@ function sendToHyperion(command, subcommand, msg)
// data: The json data as Object
// tan: The optional tan, default 1. If the tan is -1, we skip global response error handling
// Returns data of response or false if timeout
async function sendAsyncToHyperion (command, subcommand, data, tan = 1) {
async function sendAsyncToHyperion (command, subcommand, data, tan = Math.floor(Math.random() * 1000) ) {
let obj = { command, tan }
if (subcommand) {Object.assign(obj, {subcommand})}
if (data) { Object.assign(obj, data) }
Expand Down Expand Up @@ -486,38 +487,38 @@ async function requestLedDeviceDiscovery(type, params)
{
let data = { ledDeviceType: type, params: params };

return sendAsyncToHyperion("leddevice", "discover", data, Math.floor(Math.random() * 1000) );
return sendAsyncToHyperion("leddevice", "discover", data);
}

async function requestLedDeviceProperties(type, params)
{
let data = { ledDeviceType: type, params: params };

return sendAsyncToHyperion("leddevice", "getProperties", data, Math.floor(Math.random() * 1000));
return sendAsyncToHyperion("leddevice", "getProperties", data);
}

function requestLedDeviceIdentification(type, params)
{
let data = { ledDeviceType: type, params: params };

return sendAsyncToHyperion("leddevice", "identify", data, Math.floor(Math.random() * 1000));
return sendAsyncToHyperion("leddevice", "identify", data);
}

async function requestLedDeviceAddAuthorization(type, params) {
let data = { ledDeviceType: type, params: params };

return sendAsyncToHyperion("leddevice", "addAuthorization", data, Math.floor(Math.random() * 1000));
return sendAsyncToHyperion("leddevice", "addAuthorization", data);
}

async function requestInputSourcesDiscovery(type, params) {
let data = { sourceType: type, params: params };

return sendAsyncToHyperion("inputsource", "discover", data, Math.floor(Math.random() * 1000));
return sendAsyncToHyperion("inputsource", "discover", data);
}

async function requestServiceDiscovery(type, params) {
let data = { serviceType: type, params: params };

return sendAsyncToHyperion("service", "discover", data, Math.floor(Math.random() * 1000));
return sendAsyncToHyperion("service", "discover", data);
}

4 changes: 2 additions & 2 deletions assets/webconfig/js/ledsim.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ $(document).ready(function () {
$("body").get(0).style.setProperty("--background-var", "none");
}
else {
printLedsToCanvas(event.response.result.leds)
printLedsToCanvas(event.response.data.leds)
$("body").get(0).style.setProperty("--background-var", "url(" + ($('#leds_preview_canv')[0]).toDataURL("image/jpg") + ") no-repeat top left");
}
});
Expand All @@ -275,7 +275,7 @@ $(document).ready(function () {
}
}
else {
var imageData = (event.response.result.image);
var imageData = (event.response.data.image);

var image = new Image();
image.onload = function () {
Expand Down
6 changes: 3 additions & 3 deletions assets/webconfig/js/ui_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,9 @@ function showInfoDialog(type, header, message) {
});

$(document).on('click', '[data-dismiss-modal]', function () {
var target = $(this).attr('data-dismiss-modal');
$.find(target).modal('hide');
});
var target = $(this).data('dismiss-modal');
$($.find(target)).modal('hide');
});
}

function createHintH(type, text, container) {
Expand Down
4 changes: 1 addition & 3 deletions config/hyperion.config.json.default
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,7 @@
"internetAccessAPI": false,
"restirctedInternetAccessAPI": false,
"ipWhitelist": [],
"apiAuth": true,
"localApiAuth": false,
"localAdminAuth": true
"localApiAuth": false
},

"ledConfig": {
Expand Down
Loading