Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alpha1 Preparations #140

Merged
merged 10 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
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
7 changes: 5 additions & 2 deletions .github/workflows/test-and-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node-version: [16.x, 18.x, 20.x]
node-version: [16.x, 18.x, 20.x, 22.x]
os: [ubuntu-latest, windows-latest, macos-latest]

steps:
Expand Down Expand Up @@ -99,6 +99,9 @@ jobs:
BODY="${BODY//$'\n'/'%0A'}"
BODY="${BODY//$'\r'/'%0D'}"
echo "::set-output name=BODY::$BODY"
if [[ $VERSION == *"-"* ]] ; then
echo "::set-output name=TAG::--tag next"
fi

- name: Install Dependencies
run: npm ci
Expand All @@ -109,7 +112,7 @@ jobs:
run: |
npm config set //registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}
npm whoami
npm publish
npm publish ${{ steps.extract_release.outputs.TAG }}

- name: Create Github Release
id: create_release
Expand Down
52 changes: 26 additions & 26 deletions cert/cert.key
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCl2ofZKAqpOUtE
HOaedkYs3pv86P6CV3tRKXCV6BMoF0oj2HhYD6jxL92L0YyMjVi+Ysv4sWGjFB3L
UburXuDxKsU8EoksRFVFxRKRQFjtIO2tfnnkVWkdcyXUcnSgEBWfj8Gwt0Ouunxl
lS9OLUp/1zKaAk+mTU22nNkc/dy6D8REDj28UsAae4iuw5No4RYVNY28lvUbMLrP
fPVOhOMUU8cUvvrnpf7/9FkP8Sm2nG4vVpO6efYJ0wz7UiGmJUQQYRQEE/AZZSC0
O7wwNBtkxY5JO6nnLZ3MoOPHXJkF1ptUikOBNh9Db46/DHIr0JJZSaACkLsKta8C
4MM74bTZAgMBAAECggEAJDAD3x5tARJmuURjD2U4F5c0yuCdk5v55LIZhiPeditq
ulqDm5dDIejzOows0ggPOm89GRS+/IGppJC/VXt8sjJGWb6jnnyEbJY84GN9Y7QB
GA9WEjuOlWXn9axJhRktVqTbuq6p/mhjNxjveuvH6w/t0wu5DEymrbcYakp7zD7F
c9Q6iLd7MNt+EGFJQ9HXIFfvd8aGC3lUWTfVIqhQ1YjBeQXHWuK8Z6FKj/ecJ6kV
VBD2pmTPvCS2oc5/TuEstfWkhUXbJkDJUx37SqOtp5F/N/IGUndOYZGcQM5QZ0dk
eQUzslFqxmiOur6ncYO0c9DdMS/iHbF7BOLJrLVG/wKBgQDWO4vdR5BGDyRADxm4
avfdCi05lc7mAjD1ZKSzCZONOWXdKXtAk8W7UPDbTZtJ/nHXVui+gSMVSzpkqEvQ
gRs1E5m6lsp5NHwq6Q6/nrpn7aAlo9q2hBKXT6VZFkpqKQQQZfa/4Gb9KSCmNvoI
Dm62K+vx8BtWFUiXZMYIJca1MwKBgQDGMF3QG38VZehVPQpCTnr4SSCEx8x5p5sC
RJMO+mogDR43FW4Pn0olFNKqxVlV/SjBIQT0cupLq1oQjbmzQPoPk2fpBrKXMpvl
frUsm6mfEd4iBVLyLcn5NzBgOlkQrUtaz5w/L4lbDfDBZAksX8x4rGp4qI28lQuL
o3qLi7WVwwKBgD1Qe55Qbh1vFfvzlnPuwZQU5o61rqqr8+E39d98HSvtQpdC2RDJ
em07JERP+OL7nQ95w1FK2oSsrEDE3jYFzYiqXHRH1hlMiUEqxNrZDhbSruQ2+lEE
ieGenP9bXt71cEFVPYL7Md7BF6Qa1gLaRpuDBJuREfHYU5do8zi/vxh7AoGAD9S/
OadooFnylBR7JE7Gjdyxh0m6cKFNxYGayaCBJ6xElJvWndLYhlvCdDetaiv9vGeZ
0Lj5NDAs0pOvmL0A/IuGyltpmqBFSbC0YirRAs7XkpogRQ4ZSxn4eEdQ4/8jvM5G
qdlvPGHBsIEAJpZEbANBwf+cysqREIdve4QebicCgYBSTgudClfJIObL/KhR9ET5
yiJuye80x6cvGOFrkmI1XVRIykpIqtbvM32kBBN/2EmPVkOf9O79ohJnET4B6tTG
d2SMBjm/tBW6KhP0wQ8t69RWPMp3i/2HKGNqZvHQOKLbLTzEehNqnc616yx3d+UX
JM3DmzgTfECrhsicFzzoYA==
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDIOEfVJ4LFb3Dx
jbTgi/2giXy86Ty1zbIUCg43vaoM+6vSKfKwKSMW7gA01nsTRVuOzWCWsPhUdymy
UCZBWG2E1yI04LP30SpPqBaE9FfUN6dzI92C1bRe6t/iJxJLa1SgHcdjgSiRUo6Y
8xSzwd/TKNiRc3qxGGg/eSvYRasvg2QQC2arncmF4LI1yvz+dgrtRdoF1jr8NPXY
6bdSuAsGfMnmt74UH7Z7cDVfZsYuLVHMVW+fqxaxWr/2vLbygFcttEXxEx7Dspav
R36oX0MsI7yZCsxiVxXxO9ey8Ax4nes8/C2OISUnxH8EE9t6GvI9TyqETCrA4gzr
Pv1D18xjAgMBAAECggEAGSX14nsU/Nwzhn5IaCU36nslFMwC7nRIrXsEhXx9fdCl
Uz97lnmESR6vHfPhVO6oQmE02Zie3b/Il/djPAqcWaF1UB5NMeUEIyniB48dR7A5
3cd1IjgvcKCgav/XV2vCybMT1pa5froCOTSHDCZfiQlKB8hGcooLRgsKi8lXEson
6/C9LPyUMUKPAM1+Dy90LE7iOz38vOhxEm7DNu0H7u0hXYbTTBldRj2I3e+cioR6
DTbOMdkaDSyi7XGuKu6POaZmfsvsNPrRjc9oGochx+k5zOBZMj+GlvQ839mDBR7O
NwyKwX11GvQiF1kZwXriUxK6VrhsbGiQ160WOTuoCQKBgQD6E1r1Pa1ql9PLaKBc
MXkuVSgZC8S7pR+hON0BDqfy7suvAirvi8T+Q8+tb1SN27//qa2P/twpFaUivGTd
KYOzen2tZ6XQqd7O+Ybl6kfMXCEr7/4Boxlf09SNdxln7A9vs1hH01Je7XGJYIZk
wyB7lPFL1HzT0UZPlu0uOYrwbwKBgQDM9pAV8YnfOFAr+dyX99j2Oj7+H+4l/ATG
o7l67XGAeU+WxbwlQsj/Ms1ffnCU3qypuzaTd1KlzS11MKmnfRo4cSjNzdKDSK7T
6Zilnqc3e4CZaA7U+HZWjVs6jpJU74U0WwpFuOTGMb5a0kdXeQ9uOyd+yxdsbk7F
Zbd50WG1TQKBgBMmxlF/vrcqF3s9cQJ+e3RT6zU31II2XBzBuRMqpywQo6KsfNNJ
lfWPBemXXBddG/Adc4BSmVPAJ5xoZyUU19Q37kYIaQd46upY677R2VvKNnQh9gb0
Ea5oD6Ah3d06k9gPGRSvF2DTuF03+jLfSq6MMoqHJGQoY8UWnuVqXLybAoGAc2pE
KJcis/fZ7Wl9tnVyTvTtk9wXFnybk9+OCpK6X0Xwc05VbAX3ePz6eNOSQcJCKDGr
wc5nU8X92wfUAOSJZ08RUxKbgCHlkJ7xvhFgx/VbrQbTk0l2GbbvsEGoVPurXpgF
aM18xb4tGqdeVPtunPvieZuTTROwd6eXcZleE+ECgYEAgHKVr8N9UDU3o3DLIdlR
GFLj8yct7Ui1YV3F2aYu+ihG4QHLsc6MAHkcaswNvzbyEHtHpyKHTMiIYcIGxdvi
bqFXDSQRowxXsgyRDWmnP6u2fEF68dSXlJ5BOtgqqF2OCaCjHnl+E7x28WeksZRJ
fYPhkGQ3UceMHd9oEWo//Uo=
-----END PRIVATE KEY-----
42 changes: 21 additions & 21 deletions cert/cert.pem
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEFTCCAv2gAwIBAgIUcjAWwfDOv7FkmvXGaNs3oxLmsyIwDQYJKoZIhvcNAQEL
BQAwgY0xCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVTdGF0ZTERMA8GA1UEBwwITG9j
MIID8TCCAtmgAwIBAgIUTl+duPkIUXI1h7w2hiMbymkFUx8wDQYJKoZIhvcNAQEL
BQAwgYExCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVTdGF0ZTERMA8GA1UEBwwITG9j
YXRpb24xGjAYBgNVBAoMEU9yZ2FuaXphdGlvbiBOYW1lMRwwGgYDVQQLDBNPcmdh
bml6YXRpb25hbCBVbml0MSEwHwYDVQQDDBhkYWlraW4tb25lY3RhMm1xdHQubG9j
YWwwHhcNMjQwNjI4MDc1MjEwWhcNMzQwNjI2MDc1MjEwWjCBjTELMAkGA1UEBhMC
VVMxDjAMBgNVBAgMBVN0YXRlMREwDwYDVQQHDAhMb2NhdGlvbjEaMBgGA1UECgwR
T3JnYW5pemF0aW9uIE5hbWUxHDAaBgNVBAsME09yZ2FuaXphdGlvbmFsIFVuaXQx
ITAfBgNVBAMMGGRhaWtpbi1vbmVjdGEybXF0dC5sb2NhbDCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAKXah9koCqk5S0Qc5p52Rizem/zo/oJXe1EpcJXo
EygXSiPYeFgPqPEv3YvRjIyNWL5iy/ixYaMUHctRu6te4PEqxTwSiSxEVUXFEpFA
WO0g7a1+eeRVaR1zJdRydKAQFZ+PwbC3Q666fGWVL04tSn/XMpoCT6ZNTbac2Rz9
3LoPxEQOPbxSwBp7iK7Dk2jhFhU1jbyW9Rswus989U6E4xRTxxS++uel/v/0WQ/x
Kbacbi9Wk7p59gnTDPtSIaYlRBBhFAQT8BllILQ7vDA0G2TFjkk7qectncyg48dc
mQXWm1SKQ4E2H0Nvjr8McivQkllJoAKQuwq1rwLgwzvhtNkCAwEAAaNrMGkwDgYD
VR0PAQH/BAQDAgOIMBMGA1UdJQQMMAoGCCsGAQUFBwMBMCMGA1UdEQQcMBqCGGRh
aWtpbi1vbmVjdGEybXF0dC5sb2NhbDAdBgNVHQ4EFgQUPxzrRNuFqDHzBmOnSv/t
IuL36mswDQYJKoZIhvcNAQELBQADggEBAClB4bQdPo50TlRODy/5WAWqq6i5HSqO
sylSvRJN6Qzcy4oiKTaUuUHR5yBL3mXzfiZc9LiSRDB3kTOzJv50Bm8S8dct3vFP
2WjMQm7bwk6yxYKZdVPqBXuAxzzW+4t5NkuepZp3lfbYS6tNNrnDnzdZBDKXWrB1
1YUEi2mtTp0cFE3klMYfcJtUV+EgyjKMjbYcp2HFHYN2l2yV5jkH+Uik7pdzEfS+
xWQ+v5TkVKcXCS+scDocAFz1r+mHJArycXfTv2BLpdmAWSFBrsEFl72BiIW4XZ+f
avgUUJSZcEW1yxpS3YXzq44MFmUJe6Xqpu8788Wl0xCJ3dLNRUHiL1w=
bml6YXRpb25hbCBVbml0MRUwEwYDVQQDDAxkYWlraW4ubG9jYWwwHhcNMjQwNzAy
MTAxNDI3WhcNMzQwNjMwMTAxNDI3WjCBgTELMAkGA1UEBhMCVVMxDjAMBgNVBAgM
BVN0YXRlMREwDwYDVQQHDAhMb2NhdGlvbjEaMBgGA1UECgwRT3JnYW5pemF0aW9u
IE5hbWUxHDAaBgNVBAsME09yZ2FuaXphdGlvbmFsIFVuaXQxFTATBgNVBAMMDGRh
aWtpbi5sb2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMg4R9Un
gsVvcPGNtOCL/aCJfLzpPLXNshQKDje9qgz7q9Ip8rApIxbuADTWexNFW47NYJaw
+FR3KbJQJkFYbYTXIjTgs/fRKk+oFoT0V9Q3p3Mj3YLVtF7q3+InEktrVKAdx2OB
KJFSjpjzFLPB39Mo2JFzerEYaD95K9hFqy+DZBALZqudyYXgsjXK/P52Cu1F2gXW
Ovw09djpt1K4CwZ8yea3vhQftntwNV9mxi4tUcxVb5+rFrFav/a8tvKAVy20RfET
HsOylq9HfqhfQywjvJkKzGJXFfE717LwDHid6zz8LY4hJSfEfwQT23oa8j1PKoRM
KsDiDOs+/UPXzGMCAwEAAaNfMF0wDgYDVR0PAQH/BAQDAgOIMBMGA1UdJQQMMAoG
CCsGAQUFBwMBMBcGA1UdEQQQMA6CDGRhaWtpbi5sb2NhbDAdBgNVHQ4EFgQUtMiA
5rZoHyT32uu5Uw5WF9mUKXEwDQYJKoZIhvcNAQELBQADggEBAIH7BId2vX8XWs2A
qcBHAlGpt2GEdC0xSdGx/L70t/pFvYcwYLnTFYgPaDU/XzaBtwPSH71wTGTujjPF
GgDevYQxCU6/92vXO2GLgX2OAooD0+r53OO1H+dKMoRqpkX4IAqSMgZ7D5UxF76l
pG0N+bNu5TvkIXxLRojhpAmO1H82/hSRV6mObPUqL3rKHzMb5yGuCBXMbfqiF68e
QaKeHEuwBt9EiC+QJbu1GLVuh38Yih2v2TtfZQEkasisZqr7wjJSSCosZ04U56t0
qbx3M8TrjsNWJB51WOGCzmWIqh+26DK2T8KXFmfJg2W+thygEItFAhXMCILhAOwQ
UpMJ67w=
-----END CERTIFICATE-----
Empty file modified cert/generate.sh
100644 → 100755
Empty file.
6 changes: 3 additions & 3 deletions cert/req.cnf
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ C = US
ST = State
L = Location
O = Organization Name
OU = Organizational Unit
CN = daikin-onecta2mqtt.local
OU = Organizational Unit
CN = daikin.local
[v3_req]
keyUsage = critical, digitalSignature, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = daikin-onecta2mqtt.local
DNS.1 = daikin.local
5 changes: 1 addition & 4 deletions src/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class DaikinCloudDevice {
* Constructor, called from DaikinCloud class when initializing all devices
*
* @param deviceDescription object with device description from Cloud request
* @param cloudInstance Instance of DaikinCloud used for communication
* @param client Instance of DaikinCloud used for communication
*/
constructor(deviceDescription: any, client: OnectaClient) {
this.managementPoints = {};
Expand Down Expand Up @@ -239,7 +239,4 @@ export class DaikinCloudDevice {
} as const;
return this.client.requestResource(setPath, setOptions);
}

}

module.exports = DaikinCloudDevice;
16 changes: 11 additions & 5 deletions src/example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ if (!oidc_client_id || !oidc_client_secret) {
// Create a new instance of the Onecta API client. Note that the
// `oidc_callback_server_baseurl` **must** be set as the application's
// "Redirect URI" within the Daikin Developer Portal.
// See https://developer.cloud.daikineurope.com .
// See https://developer.cloud.daikineurope.com .
// ============================================================================

const controller = new DaikinCloudController({
Expand All @@ -26,15 +26,16 @@ const controller = new DaikinCloudController({
/* OIDC client secret */
oidc_client_secret,
/* network interface that the HTTP server should bind to */
oidc_callback_server_addr: '127.0.0.1',
oidc_callback_server_addr: '0.0.0.0',
Apollon77 marked this conversation as resolved.
Show resolved Hide resolved
/* port that the HTTP server should bind to */
oidc_callback_server_port: 8765,
/* OIDC Redirect URI */
oidc_callback_server_baseurl: 'https://daikin.local:8765',
oidc_callback_server_baseurl: 'https://192.168.68.23:8765', // or use local IP address where server is reachable
/* path of file used to cache the OIDC tokenset */
oidc_tokenset_file_path: resolve(homedir(), '.daikin-controller-cloud-tokenset'),
/* time to wait for the user to go through the authorization grant flow before giving up (in seconds) */
oidc_authorization_timeout: 120,
certificate_path: resolve(__dirname, '..', 'cert'),
});

// ============================================================================
Expand All @@ -45,15 +46,20 @@ const controller = new DaikinCloudController({
// ============================================================================

controller.on('authorization_request', (url) => {
console.log('Please navigate to %s', url);
console.log(`
Please make sure that ${url} is set as "Redirect URL" in your Daikin Developer Portal account for the used Client!

Then please open the URL ${url} in your browser and accept the security warning for the self signed certificate (if you open this for the first time).

Afterwards you are redirected to Daikin to approve the access and then redirected back.`);
});

(async () => {

// ==========================================================================
// OIDC authentication, authorization and token management are all abstracted
// away. The public methods exposed by the client map to the endpoints
// provided by the Onecta API.
// provided by the Onecta API.
// See https://developer.cloud.daikineurope.com/spec/b0dffcaa-7b51-428a-bdff-a7c8a64195c0/70b10aca-1b4c-470b-907d-56879784ea9c
// ==========================================================================

Expand Down
19 changes: 13 additions & 6 deletions src/onecta/oidc-callback-server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

import type { IncomingMessage, ServerResponse } from 'node:http';

import { resolve } from 'node:path';
import { resolve, join } from 'node:path';
import { createServer, Server } from 'node:https';
import { readFile } from 'node:fs/promises';
import { OnectaClientConfig, onecta_oidc_auth_thank_you_html } from './oidc-utils.js';
Expand All @@ -14,10 +14,11 @@ export type OnectaOIDCCallbackServerRequestListener<
/**
* Creates and starts a HTTPS server
*/
export const startOnectaOIDCCallbackServer = async (config: OnectaClientConfig, oidc_state: string): Promise<string> => {
export const startOnectaOIDCCallbackServer = async (config: OnectaClientConfig, oidc_state: string, auth_url: string): Promise<string> => {
const certificatePath = config.certificate_path ?? resolve(__dirname, '..', '..', 'cert');
const server = createServer({
key: await readFile(resolve(__dirname, '..', '..', 'cert', 'cert.key')),
cert: await readFile(resolve(__dirname, '..', '..', 'cert', 'cert.pem')),
key: await readFile(join(certificatePath, 'cert.key')),
cert: await readFile(join(certificatePath, 'cert.pem')),
});
await new Promise<void>((resolve, reject) => {
const cleanup = () => {
Expand Down Expand Up @@ -63,9 +64,15 @@ export const startOnectaOIDCCallbackServer = async (config: OnectaClientConfig,
const auth_code = url.searchParams.get('code');
if (res_state === oidc_state && auth_code) {
res.statusCode = 200;
res.write(onecta_oidc_auth_thank_you_html);
res.write(config.onecta_oidc_auth_thank_you_html ?? onecta_oidc_auth_thank_you_html);
res.once('finish', () => onAuthCode(auth_code));
} else {
} else if (!res_state && !auth_code && (req.url ?? '/') === '/') {
//Redirect to auth_url
res.writeHead(302, {
'Location': auth_url,
});
}
else {
res.statusCode = 400;
}
res.end();
Expand Down
7 changes: 5 additions & 2 deletions src/onecta/oidc-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ export class OnectaClient {
state: req_state,
redirect_uri,
});
this._emitter.emit('authorization_request', auth_url);
const auth_code = await startOnectaOIDCCallbackServer(this._config, req_state);
this._emitter.emit('authorization_request', _config.oidc_callback_server_baseurl);
const auth_code =
_config.custom_oidc_code_receiver
? await _config.custom_oidc_code_receiver(auth_url, req_state)
: await startOnectaOIDCCallbackServer(this._config, req_state, auth_url);
const token_set = await _client.grant({
grant_type: 'authorization_code',
client_id: _config.oidc_client_id,
Expand Down
5 changes: 4 additions & 1 deletion src/onecta/oidc-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const onecta_oidc_auth_thank_you_html = `
</head>
<body>
<h1>Authorization complete</h1>
<p>Thank you for authorizing <code>daikin-onecta2mqtt</code> to access your devices.</p>
<p>Thank you for authorizing <code>daikin-controller-cloud</code> to access your devices.</p>
</body>
</html>
`;
Expand All @@ -45,4 +45,7 @@ export interface OnectaClientConfig {
oidc_callback_server_addr: string;
oidc_authorization_timeout: number;
oidc_tokenset_file_path: string;
certificate_path: string;
Apollon77 marked this conversation as resolved.
Show resolved Hide resolved
onecta_oidc_auth_thank_you_html?: string;
custom_oidc_code_receiver?: (auth_url: string, state: string) => Promise<string>;
}
Loading