diff --git a/.github/workflows/helm-chart-release.yml b/.github/workflows/helm-chart-release.yml index e539e3fe..44313e1b 100644 --- a/.github/workflows/helm-chart-release.yml +++ b/.github/workflows/helm-chart-release.yml @@ -35,7 +35,7 @@ jobs: done - name: Run chart-releaser for stable - uses: helm/chart-releaser-action@v1.5.0 + uses: helm/chart-releaser-action@v1.6.0 with: charts_dir: charts mark_as_latest: false diff --git a/README.md b/README.md index e3b54ab0..9b273c30 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Planka -#### Elegant open source project tracking +#### Elegant open source project tracking. ![David (path)](https://img.shields.io/github/package-json/v/plankanban/planka) ![Docker Pulls](https://img.shields.io/docker/pulls/meltyshev/planka) ![GitHub](https://img.shields.io/github/license/plankanban/planka) @@ -20,9 +20,7 @@ ## How to deploy Planka -There are many ways to install Planka - -[Check them out](https://docs.planka.cloud/docs/intro) +There are many ways to install Planka, [check them out](https://docs.planka.cloud/docs/intro). For configuration, please see the [configuration section](https://docs.planka.cloud/docs/category/configuration). diff --git a/charts/planka/Chart.yaml b/charts/planka/Chart.yaml index 615e3593..e964d321 100644 --- a/charts/planka/Chart.yaml +++ b/charts/planka/Chart.yaml @@ -15,13 +15,13 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.11 +version: 0.1.12 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "1.15.0" +appVersion: "1.15.1" dependencies: - alias: postgresql diff --git a/client/.env b/client/.env index 4590d2cc..914e3d56 100644 --- a/client/.env +++ b/client/.env @@ -1 +1 @@ -REACT_APP_VERSION=1.15.0 +REACT_APP_VERSION=1.15.1 diff --git a/client/src/sagas/core/services/socket.js b/client/src/sagas/core/services/socket.js index a52c7d25..a5f1abaf 100644 --- a/client/src/sagas/core/services/socket.js +++ b/client/src/sagas/core/services/socket.js @@ -14,24 +14,45 @@ export function* handleSocketReconnect() { yield put(actions.handleSocketReconnect.fetchCore(currentUserId, boardId)); - const { - user, - board, - users, - projects, - projectManagers, - boards, - boardMemberships, - labels, - lists, - cards, - cardMemberships, - cardLabels, - tasks, - attachments, - activities, - notifications, - } = yield call(requests.fetchCore); // TODO: handle error + let user; + let board; + let users; + let projects; + let projectManagers; + let boards; + let boardMemberships; + let labels; + let lists; + let cards; + let cardMemberships; + let cardLabels; + let tasks; + let attachments; + let activities; + let notifications; + + try { + ({ + user, + board, + users, + projects, + projectManagers, + boards, + boardMemberships, + labels, + lists, + cards, + cardMemberships, + cardLabels, + tasks, + attachments, + activities, + notifications, + } = yield call(requests.fetchCore)); + } catch (error) { + return; + } yield put( actions.handleSocketReconnect( diff --git a/client/src/sagas/login/services/login.js b/client/src/sagas/login/services/login.js index 1b842e80..ef02a38c 100644 --- a/client/src/sagas/login/services/login.js +++ b/client/src/sagas/login/services/login.js @@ -32,15 +32,29 @@ export function* authenticate(data) { export function* authenticateUsingOidc() { const oidcConfig = yield select(selectors.selectOidcConfig); + const state = nanoid(); + window.sessionStorage.setItem('oidc-state', state); + const nonce = nanoid(); window.sessionStorage.setItem('oidc-nonce', nonce); - window.location.href = `${oidcConfig.authorizationUrl}&nonce=${encodeURIComponent(nonce)}`; + + let redirectUrl = `${oidcConfig.authorizationUrl}`; + redirectUrl += `&state=${encodeURIComponent(state)}`; + redirectUrl += `&nonce=${encodeURIComponent(nonce)}`; + + window.location.href = redirectUrl; } export function* authenticateUsingOidcCallback() { // https://github.com/plankanban/planka/issues/511#issuecomment-1771385639 const params = new URLSearchParams(window.location.hash.substring(1) || window.location.search); + const state = window.sessionStorage.getItem('oidc-state'); + window.sessionStorage.removeItem('oidc-state'); + + const nonce = window.sessionStorage.getItem('oidc-nonce'); + window.sessionStorage.removeItem('oidc-nonce'); + yield put(replace(Paths.LOGIN)); if (params.get('error') !== null) { @@ -54,7 +68,23 @@ export function* authenticateUsingOidcCallback() { return; } - const nonce = window.sessionStorage.getItem('oidc-nonce'); + const code = params.get('code'); + if (code === null) { + yield put( + actions.authenticateUsingOidc.failure(new Error('Invalid OIDC response: no code parameter')), + ); + return; + } + + if (params.get('state') !== state) { + yield put( + actions.authenticateUsingOidc.failure( + new Error('Unable to process OIDC response: state mismatch'), + ), + ); + return; + } + if (nonce === null) { yield put( actions.authenticateUsingOidc.failure( @@ -64,31 +94,19 @@ export function* authenticateUsingOidcCallback() { return; } - const code = params.get('code'); - if (code === null) { - yield put( - actions.authenticateUsingOidc.failure(new Error('Invalid OIDC response: no code parameter')), - ); + let accessToken; + try { + ({ item: accessToken } = yield call(api.exchangeForAccessTokenUsingOidc, { + code, + nonce, + })); + } catch (error) { + yield put(actions.authenticateUsingOidc.failure(error)); return; } - window.sessionStorage.removeItem('oidc-nonce'); - - if (code !== null) { - let accessToken; - try { - ({ item: accessToken } = yield call(api.exchangeForAccessTokenUsingOidc, { - code, - nonce, - })); - } catch (error) { - yield put(actions.authenticateUsingOidc.failure(error)); - return; - } - - yield call(setAccessToken, accessToken); - yield put(actions.authenticateUsingOidc.success(accessToken)); - } + yield call(setAccessToken, accessToken); + yield put(actions.authenticateUsingOidc.success(accessToken)); } export function* clearAuthenticateError() { diff --git a/package-lock.json b/package-lock.json index 3a01824a..ea1e05aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "planka", - "version": "1.15.0", + "version": "1.15.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "planka", - "version": "1.15.0", + "version": "1.15.1", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index b6659ba8..8621f75c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "planka", - "version": "1.15.0", + "version": "1.15.1", "private": true, "homepage": "https://plankanban.github.io/planka", "repository": { diff --git a/server/api/helpers/users/get-or-create-one-using-oidc.js b/server/api/helpers/users/get-or-create-one-using-oidc.js index 6a862022..6d1c49f0 100644 --- a/server/api/helpers/users/get-or-create-one-using-oidc.js +++ b/server/api/helpers/users/get-or-create-one-using-oidc.js @@ -24,8 +24,13 @@ module.exports = { try { const tokenSet = await client.callback( sails.config.custom.oidcRedirectUri, - { code: inputs.code }, - { nonce: inputs.nonce }, + { + iss: sails.config.custom.oidcIssuer, + code: inputs.code, + }, + { + nonce: inputs.nonce, + }, ); userInfo = await client.userinfo(tokenSet); } catch (e) {