1
0
Fork 0
mirror of https://github.com/plankanban/planka.git synced 2025-07-27 17:19:43 +02:00

fix: Add state parameter to OIDC authorization url

Closes #558
This commit is contained in:
Maksim Eltyshev 2023-12-09 17:06:45 +01:00
parent 28c3f28e01
commit ca6fb3b962

View file

@ -32,15 +32,29 @@ export function* authenticate(data) {
export function* authenticateUsingOidc() { export function* authenticateUsingOidc() {
const oidcConfig = yield select(selectors.selectOidcConfig); const oidcConfig = yield select(selectors.selectOidcConfig);
const state = nanoid();
window.sessionStorage.setItem('oidc-state', state);
const nonce = nanoid(); const nonce = nanoid();
window.sessionStorage.setItem('oidc-nonce', nonce); 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() { export function* authenticateUsingOidcCallback() {
// https://github.com/plankanban/planka/issues/511#issuecomment-1771385639 // https://github.com/plankanban/planka/issues/511#issuecomment-1771385639
const params = new URLSearchParams(window.location.hash.substring(1) || window.location.search); 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)); yield put(replace(Paths.LOGIN));
if (params.get('error') !== null) { if (params.get('error') !== null) {
@ -54,7 +68,23 @@ export function* authenticateUsingOidcCallback() {
return; 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) { if (nonce === null) {
yield put( yield put(
actions.authenticateUsingOidc.failure( actions.authenticateUsingOidc.failure(
@ -64,31 +94,19 @@ export function* authenticateUsingOidcCallback() {
return; return;
} }
const code = params.get('code'); let accessToken;
if (code === null) { try {
yield put( ({ item: accessToken } = yield call(api.exchangeForAccessTokenUsingOidc, {
actions.authenticateUsingOidc.failure(new Error('Invalid OIDC response: no code parameter')), code,
); nonce,
}));
} catch (error) {
yield put(actions.authenticateUsingOidc.failure(error));
return; return;
} }
window.sessionStorage.removeItem('oidc-nonce'); yield call(setAccessToken, accessToken);
yield put(actions.authenticateUsingOidc.success(accessToken));
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));
}
} }
export function* clearAuthenticateError() { export function* clearAuthenticateError() {