From bc5082dcf9367d5907937aa924bb34f8b5219538 Mon Sep 17 00:00:00 2001 From: Joxit Date: Fri, 9 Apr 2021 17:28:48 +0200 Subject: [PATCH] feat(token-auth-keycloak): remove custom dialog and use browser basic auth with nginx configuration --- .../token-auth-keycloak/conf/proxy/nginx.conf | 11 +++ .../dialogs/registry-authentication.riot | 71 ------------------- src/components/docker-registry-ui.riot | 34 ++++----- src/components/tag-list/remove-image.riot | 19 +++-- src/components/tag-list/tag-list.riot | 4 +- src/components/tag-list/tag-table.riot | 10 +-- src/index.html | 2 +- 7 files changed, 53 insertions(+), 98 deletions(-) delete mode 100644 src/components/dialogs/registry-authentication.riot diff --git a/examples/token-auth-keycloak/conf/proxy/nginx.conf b/examples/token-auth-keycloak/conf/proxy/nginx.conf index 681faff..3e0c7c5 100644 --- a/examples/token-auth-keycloak/conf/proxy/nginx.conf +++ b/examples/token-auth-keycloak/conf/proxy/nginx.conf @@ -34,6 +34,17 @@ server { proxy_pass http://keycloak:8080; } + location /auth/realms/master/protocol/docker-v2/auth { + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Host $host; + if ($http_authorization = "") { + add_header WWW-Authenticate 'Basic realm="Keycloak login"' always; + return 401; + } + proxy_pass http://keycloak:8080; + } + location /ui { proxy_pass http://ui/; } diff --git a/src/components/dialogs/registry-authentication.riot b/src/components/dialogs/registry-authentication.riot deleted file mode 100644 index 2a33645..0000000 --- a/src/components/dialogs/registry-authentication.riot +++ /dev/null @@ -1,71 +0,0 @@ - - - -
Sign In to your registry
-
- - -
-
- - Sign In - - - Cancel - -
-
- -
\ No newline at end of file diff --git a/src/components/docker-registry-ui.riot b/src/components/docker-registry-ui.riot index 3336716..341ed7c 100644 --- a/src/components/docker-registry-ui.riot +++ b/src/components/docker-registry-ui.riot @@ -39,7 +39,8 @@ along with this program. If not, see . + is-image-remove-activated="{ props.isImageRemoveActivated }" on-notify="{ notifySnackbar }" + on-authentication="{ onAuthentication }"> . import TagHistory from './tag-history/tag-history.riot'; import DialogsMenu from './dialogs/dialogs-menu.riot'; import SearchBar from './search-bar.riot' - import RegistryAuthentication from './dialogs/registry-authentication.riot'; import { stripHttps, getRegistryServers @@ -87,7 +87,6 @@ along with this program. If not, see . TagHistory, DialogsMenu, SearchBar, - RegistryAuthentication, Router, Route }, @@ -113,20 +112,23 @@ along with this program. If not, see . }) }, onAuthentication(opts, onAuthenticated) { - const bearer = { - token: localStorage.getItem('registry.token'), - issued_at: localStorage.getItem('registry.issued_at'), - expires_in: localStorage.getItem('registry.expires_in') - } - if (bearer.token && bearer.issued_at && bearer.expires_in && - (new Date().getTime() - new Date(bearer.issued_at).getTime()) < (bearer.expires_in * 1000)) { - onAuthenticated(bearer) - } else if (opts) { - this.update({ - authenticationDialogOpened: true, - onAuthenticated, - ...opts + if (opts && opts.realm && opts.service && opts.scope) { + const { + realm, + service, + scope, + } = opts; + const req = new XMLHttpRequest() + req.addEventListener('loadend', () => { + try { + const bearer = JSON.parse(req.responseText); + onAuthenticated(bearer) + } catch (e) { + this.notifySnackbar(`Failed to log in: ${e.message}`, true) + } }) + req.open('GET', `${realm}?service=${service}&scope=${scope}`) + req.send() } else { onAuthenticated() } diff --git a/src/components/tag-list/remove-image.riot b/src/components/tag-list/remove-image.riot index cd180e6..899386c 100644 --- a/src/components/tag-list/remove-image.riot +++ b/src/components/tag-list/remove-image.riot @@ -43,21 +43,32 @@ along with this program. If not, see . state.checked = props.checked; }, deleteImage(ignoreError) { - deleteImage(this.props.image, this.props.registryUrl, ignoreError, this.props.onNotify) + deleteImage(this.props.image, { + ...this.props, + ignoreError + }) }, handleCheckboxChange(checked) { this.props.handleCheckboxChange(checked, this.props.image); } } - export function deleteImage(image, registryUrl, ignoreError, onNotify) { + export function deleteImage(image, opts) { + const { + registryUrl, + ignoreError, + onNotify, + onAuthentication + } = opts; if (!image.digest) { onNotify(`Information for ${name}:${tag} are not yet loaded.`); return; } const name = image.name; const tag = image.tag; - const oReq = new Http(); + const oReq = new Http({ + onAuthentication: onAuthentication + }); oReq.addEventListener('loadend', function () { if (this.status == 200 || this.status == 202) { router.taglist(name); @@ -71,7 +82,7 @@ along with this program. If not, see . onNotify(this.responseText); } }); - oReq.open('DELETE', registryUrl + '/v2/' + name + '/manifests/' + image.digest); + oReq.open('DELETE', `${registryUrl}/v2/${name}/manifests/${image.digest}`); oReq.setRequestHeader('Accept', 'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json'); oReq.addEventListener('error', function () { diff --git a/src/components/tag-list/tag-list.riot b/src/components/tag-list/tag-list.riot index 280ae1f..a8cd1b3 100644 --- a/src/components/tag-list/tag-list.riot +++ b/src/components/tag-list/tag-list.riot @@ -39,7 +39,9 @@ along with this program. If not, see . + on-notify="{ props.onNotify }" filter-results="{ props.filterResults }" + on-authentication="{ props.onAuthentication }"> + diff --git a/src/components/tag-list/tag-table.riot b/src/components/tag-list/tag-table.riot index 9f99365..43d8e99 100644 --- a/src/components/tag-list/tag-table.riot +++ b/src/components/tag-list/tag-table.riot @@ -63,16 +63,13 @@ along with this program. If not, see . + on-notify="{ props.onNotify }" on-authentication="{ props.onAuthentication }" />