Skip to content

Commit

Permalink
#1591 improve refresh of browser, re-using stored token from local st…
Browse files Browse the repository at this point in the history
…orage / oidc-library
  • Loading branch information
thjaeckle committed Sep 26, 2024
1 parent 71066ff commit a7611f2
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 90 deletions.
8 changes: 7 additions & 1 deletion ui/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,18 @@ tbody {
display: inline;
}

.toast-header {
.toast-header-warn {
color: #842029;
background-color: #f8d7da;
border-color: #f5c2c7;
}

.toast-header-info {
color: #842029;
background-color: #ebd7f8;
border-color: #fbfbfb;
}

textarea {
white-space: pre;
overflow-wrap: normal;
Expand Down
176 changes: 109 additions & 67 deletions ui/modules/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { EventSourcePolyfill } from 'event-source-polyfill';
import * as Environments from './environments/environments.js';
import { AuthMethod } from './environments/environments.js';
import * as Utils from './utils.js';
import { showError } from './utils.js';


const config = {
Expand Down Expand Up @@ -280,36 +281,65 @@ let authHeaderValue;
* @param {boolean} forDevOps if true, the credentials for the dev ops api will be used.
*/
export function setAuthHeader(forDevOps: boolean) {
authHeaderValue = undefined;
let environment = Environments.current();
if (forDevOps) {
let devopsAuthMethod = environment.authSettings?.devops?.method;
if (devopsAuthMethod === AuthMethod.basic) {
authHeaderKey = 'Authorization';
authHeaderValue = 'Basic ' + window.btoa(environment.authSettings.devops.basic.usernamePassword);
if (environment.authSettings.devops.basic.usernamePassword) {
authHeaderKey = 'Authorization';
authHeaderValue = 'Basic ' + window.btoa(environment.authSettings.devops.basic.usernamePassword);
} else {
showError('DevOps Username/password missing')
}
} else if (devopsAuthMethod === AuthMethod.bearer) {
authHeaderKey = 'Authorization';
authHeaderValue = 'Bearer ' + environment.authSettings.devops.bearer.bearerToken;
if (environment.authSettings.devops.bearer.bearerToken) {
authHeaderKey = 'Authorization';
authHeaderValue = 'Bearer ' + environment.authSettings.devops.bearer.bearerToken;
} else {
showError('DevOps Bearer token missing')
}
} else if (devopsAuthMethod === AuthMethod.oidc) {
authHeaderKey = 'Authorization';
authHeaderValue = 'Bearer ' + environment.authSettings.devops.oidc.bearerToken;
if (environment.authSettings.devops.oidc.bearerToken) {
authHeaderKey = 'Authorization';
authHeaderValue = 'Bearer ' + environment.authSettings.devops.oidc.bearerToken;
} else {
showError('DevOps SSO (Bearer) token missing')
}
} else {
authHeaderKey = 'Authorization';
authHeaderValue = 'Basic';
}
} else {
let mainAuthMethod = environment.authSettings?.main?.method;
if (mainAuthMethod === AuthMethod.basic) {
authHeaderKey = 'Authorization';
authHeaderValue = 'Basic ' + window.btoa(environment.authSettings.main.basic.usernamePassword);
if (environment.authSettings.main.basic.usernamePassword) {
authHeaderKey = 'Authorization';
authHeaderValue = 'Basic ' + window.btoa(environment.authSettings.main.basic.usernamePassword);
} else {
showError('Username/password missing')
}
} else if (mainAuthMethod === AuthMethod.pre) {
authHeaderKey = 'x-ditto-pre-authenticated';
authHeaderValue = environment.authSettings.main.pre.dittoPreAuthenticatedUsername;
if (environment.authSettings.main.pre.dittoPreAuthenticatedUsername) {
authHeaderKey = 'x-ditto-pre-authenticated';
authHeaderValue = environment.authSettings.main.pre.dittoPreAuthenticatedUsername;
} else {
showError('Pre-Authenticated username missing')
}
} else if (mainAuthMethod === AuthMethod.bearer) {
authHeaderKey = 'Authorization';
authHeaderValue = 'Bearer ' + environment.authSettings.main.bearer.bearerToken;
if (environment.authSettings.main.bearer.bearerToken) {
authHeaderKey = 'Authorization';
authHeaderValue = 'Bearer ' + environment.authSettings.main.bearer.bearerToken;
} else {
showError('Bearer token missing')
}
} else if (mainAuthMethod === AuthMethod.oidc) {
authHeaderKey = 'Authorization';
authHeaderValue = 'Bearer ' + environment.authSettings.main.oidc.bearerToken;
if (environment.authSettings.main.oidc.bearerToken) {
authHeaderKey = 'Authorization';
authHeaderValue = 'Bearer ' + environment.authSettings.main.oidc.bearerToken;
} else {
showError('SSO (Bearer) token missing')
}
} else {
authHeaderKey = 'Authorization';
authHeaderValue = 'Basic';
Expand Down Expand Up @@ -351,62 +381,70 @@ export async function callDittoREST(method: string,
returnHeaders = false,
devOps = false,
returnErrorJson = false): Promise<any> {
let response;
const contentType = method === 'PATCH' ? 'application/merge-patch+json' : 'application/json';
try {
response = await fetch(Environments.current().api_uri + (devOps ? '' : '/api/2') + path, {
method: method,
headers: {
'Content-Type': contentType,
[authHeaderKey]: authHeaderValue,
...additionalHeaders,
},
...(method !== 'GET' && method !== 'DELETE' && body !== undefined) && {body: JSON.stringify(body)},
});
} catch (err) {
Utils.showError(err);
throw err;
}
if (!response.ok) {
if (returnErrorJson) {
if (authHeaderValue) {
let response;
const contentType = method === 'PATCH' ? 'application/merge-patch+json' : 'application/json';
try {
response = await fetch(Environments.current().api_uri + (devOps ? '' : '/api/2') + path, {
method: method,
headers: {
'Content-Type': contentType,
[authHeaderKey]: authHeaderValue,
...additionalHeaders,
},
...(method !== 'GET' && method !== 'DELETE' && body !== undefined) && {body: JSON.stringify(body)},
});
} catch (err) {
Utils.showError(err);
throw err;
}
if (!response.ok) {
if (returnErrorJson) {
if (returnHeaders) {
return response;
} else {
return response.json().then((dittoErr) => {
showDittoError(dittoErr, response);
return dittoErr;
});
}
} else {
response.json()
.then((dittoErr) => {
showDittoError(dittoErr, response);
})
.catch((err) => {
Utils.showError('No error details from Ditto', response.statusText, response.status);
});
throw new Error('An error occurred: ' + response.status);
}
}
if (response.status !== 204) {
if (returnHeaders) {
return response;
} else {
return response.json().then((dittoErr) => {
showDittoError(dittoErr, response);
return dittoErr;
});
return response.json();
}
} else {
response.json()
.then((dittoErr) => {
showDittoError(dittoErr, response);
})
.catch((err) => {
Utils.showError('No error details from Ditto', response.statusText, response.status);
});
throw new Error('An error occurred: ' + response.status);
}
}
if (response.status !== 204) {
if (returnHeaders) {
return response;
} else {
return response.json();
return null;
}
} else {
return null;
throw new Error("Authentication missing");
}
}

export function getEventSource(thingIds, urlParams) {
return new EventSourcePolyfill(
if (authHeaderValue) {
return new EventSourcePolyfill(
`${Environments.current().api_uri}/api/2/things?ids=${thingIds}${urlParams ? '&' + urlParams : ''}`, {
headers: {
[authHeaderKey]: authHeaderValue,
},
},
);
);
} else {
throw new Error("Authentication missing");
}
}

/**
Expand All @@ -433,19 +471,23 @@ export async function callConnectionsAPI(operation, successCallback, connectionI
body = command;
}

try {
response = await fetch(Environments.current().api_uri + params.path
.replace('{{connectionId}}', connectionId), {
method: params.method,
headers: {
'Content-Type': operation === 'connectionCommand' ? 'text/plain' : 'application/json',
[authHeaderKey]: authHeaderValue,
},
...(body) && {body: body},
});
} catch (err) {
Utils.showError(err);
throw err;
if (authHeaderValue) {
try {
response = await fetch(Environments.current().api_uri + params.path
.replace('{{connectionId}}', connectionId), {
method: params.method,
headers: {
'Content-Type': operation === 'connectionCommand' ? 'text/plain' : 'application/json',
[authHeaderKey]: authHeaderValue,
},
...(body) && {body: body},
});
} catch (err) {
Utils.showError(err);
throw err;
}
} else {
throw new Error("Authentication missing");
}

if (!response.ok) {
Expand Down
4 changes: 2 additions & 2 deletions ui/modules/environments/authorization.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ <h5>Main authentication</h5>
<label for="oidcProvider" class="input-group-text"><small>SSO provider</small></label>
<select class="form-select form-select-sm me-2" id="oidcProvider"></select>
<button class="btn btn-outline-secondary btn-sm" id="main-oidc-login">Login</button>
<button class="btn btn-outline-secondary btn-sm" id="main-oidc-logout">Logout</button>
<button class="btn btn-outline-secondary btn-sm" id="main-oidc-logout" data-bs-dismiss="modal">Logout</button>
</div>
</div>
</div>
Expand Down Expand Up @@ -93,7 +93,7 @@ <h5>DevOps authentication</h5>
<label for="devOpsOidcProvider" class="input-group-text"><small>SSO provider</small></label>
<select class="form-select form-select-sm me-2" id="devOpsOidcProvider"></select>
<button class="btn btn-outline-secondary btn-sm" id="devops-oidc-login">Login</button>
<button class="btn btn-outline-secondary btn-sm" id="devops-oidc-logout">Logout</button>
<button class="btn btn-outline-secondary btn-sm" id="devops-oidc-logout" data-bs-dismiss="modal">Logout</button>
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit a7611f2

Please sign in to comment.