-
Notifications
You must be signed in to change notification settings - Fork 351
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3318941
commit 1f4c490
Showing
12 changed files
with
836 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
import jwtDecode from 'jwt-decode' | ||
import { isObject, pick } from 'lodash' | ||
import { | ||
AUTH_STORAGE_SSO_PROVIDERS, | ||
AUTH_STORAGE_URL_SEARCH_PARAMS | ||
} from './constants' | ||
import { addSearchParamsInBrowserHistory, authLog } from './helpers' | ||
import { | ||
mandatoryKeysForSSOProviderParams, | ||
mandatoryKeysForSSOProviders, | ||
searchParamsToSaveForAfterAuthRedirect | ||
} from './settings' | ||
import { parse as parseQueryString } from 'querystring' | ||
|
||
export const getInitialisationParameters = ( | ||
urlSearchParams = window.location.search, | ||
urlHashParams = window.location.hash | ||
) => { | ||
let initParams = {} | ||
try { | ||
initParams = { | ||
...parseQueryString(urlSearchParams.replace(/^\?/, '')), | ||
...parseQueryString(urlHashParams.replace(/^#/, '')) | ||
} | ||
Object.keys(initParams).forEach(key => { | ||
if (initParams[key].trim().length === 0) { | ||
initParams[key] = null | ||
} | ||
}) | ||
} catch (exc) { | ||
console.warn('Exception occured while parsing Browser URL parameters', exc) | ||
} | ||
return initParams | ||
} | ||
|
||
export const checkAndMergeSSOProviders = ( | ||
discoveredSSOProviders, | ||
isLocalhostOrigin | ||
) => { | ||
if (!discoveredSSOProviders || !discoveredSSOProviders.length) { | ||
authLog('Invalid discovered SSO providers') | ||
return | ||
} | ||
|
||
let currentSSOProviders = | ||
JSON.parse(window.sessionStorage.getItem(AUTH_STORAGE_SSO_PROVIDERS)) || [] | ||
if (!Array.isArray(currentSSOProviders)) { | ||
authLog( | ||
'Found SSO providers in storage are defect, consider clearing the SSO provider state and reload', | ||
'warn' | ||
) | ||
currentSSOProviders = [] | ||
} | ||
|
||
discoveredSSOProviders.forEach(provider => { | ||
if (!provider) return | ||
if ( | ||
!mandatoryKeysForSSOProviders.every(key => provider.hasOwnProperty(key)) | ||
) { | ||
authLog( | ||
`Dropping invalid discovered SSO provider with id: "${provider.id}", missing key` | ||
) | ||
return | ||
} | ||
if ( | ||
!mandatoryKeysForSSOProviderParams.every(key => | ||
provider?.params?.hasOwnProperty(key) | ||
) | ||
) { | ||
authLog( | ||
`Dropping invalid discovered SSO provider with id: "${provider.id}", missing params key` | ||
) | ||
return | ||
} | ||
if ( | ||
currentSSOProviders.find(crntProvider => crntProvider.id === provider.id) | ||
) { | ||
if (isLocalhostOrigin) { | ||
const idx = currentSSOProviders.findIndex( | ||
crntProvider => crntProvider.id === provider.id | ||
) | ||
currentSSOProviders.splice(idx, 1) | ||
authLog(`Updating SSO provider with id: "${provider.id}"`) | ||
} else { | ||
authLog( | ||
`Not accepting discovered SSO provider with id: "${provider.id}", id exists already` | ||
) | ||
return | ||
} | ||
} | ||
currentSSOProviders.push(provider) | ||
}) | ||
|
||
window.sessionStorage.setItem( | ||
AUTH_STORAGE_SSO_PROVIDERS, | ||
JSON.stringify(currentSSOProviders) | ||
) | ||
authLog('Checked and merged SSO providers') | ||
} | ||
|
||
export const getSSOProvidersFromStorage = () => { | ||
const ssoProviders = JSON.parse( | ||
window.sessionStorage.getItem(AUTH_STORAGE_SSO_PROVIDERS) | ||
) | ||
if (!ssoProviders || !ssoProviders.length) { | ||
authLog('No SSO providers in (local) storage found') | ||
return [] | ||
} | ||
return ssoProviders | ||
} | ||
|
||
export const getSSOProviderByIdpId = idpId => { | ||
const ssoProviders = getSSOProvidersFromStorage() | ||
|
||
const selectedSSOProvider = ssoProviders.find( | ||
provider => provider.id === idpId | ||
) | ||
if (!selectedSSOProvider) { | ||
authLog(`No matching SSO provider to passed in argument: ${idpId}`, 'warn') | ||
return null | ||
} | ||
return selectedSSOProvider | ||
} | ||
|
||
export const getCredentialsFromAuthResult = (result, idpId) => { | ||
const _parseJWTAndSetCredentials = toParseToken => { | ||
const parsedJWT = jwtDecode(toParseToken) | ||
|
||
// TODO: remove this | ||
console.log('Parsed JWT: ', parsedJWT) | ||
|
||
if (!parsedJWT) { | ||
authLog(`Could not parse JWT for idp_id: ${idpId}, aborting`, 'warn') | ||
return { username: '', password: '' } | ||
} | ||
|
||
const email = parsedJWT[principal] || parsedJWT.email || parsedJWT.sub | ||
authLog(`Credentials assembly, username: ${email}`) | ||
|
||
return { username: email, password: result.access_token } | ||
} | ||
|
||
let credentials = {} | ||
authLog(`Attempting to assemble credentials for idp_id: ${idpId}`) | ||
|
||
if (!result || !idpId) { | ||
authLog('No result or idp_id passed in', 'warn') | ||
return credentials | ||
} | ||
|
||
const selectedSSOProvider = getSSOProviderByIdpId(idpId) | ||
if (!selectedSSOProvider) return | ||
|
||
const principal = selectedSSOProvider.config?.principal || '' | ||
authLog(`Credentials, principal: ${principal}`) | ||
|
||
switch (idpId) { | ||
case 'google-oidc': | ||
if (!result.id_token) { | ||
authLog('No id_token in google-oidc result!', 'warn') | ||
authLog( | ||
`We do not support auth_flow: "${selectedSSOProvider.auth_flow}" for idp_id: "${idpId}" at the moment`, | ||
'warn' | ||
) | ||
// INFO: Another HTTP call would be needed to get an id_token. | ||
credentials = { username: '', password: '' } | ||
break | ||
} | ||
credentials = _parseJWTAndSetCredentials(result.id_token) | ||
break | ||
default: | ||
credentials = _parseJWTAndSetCredentials(result.access_token) | ||
break | ||
} | ||
return credentials | ||
} | ||
|
||
export const temporarlyStoreUrlSearchParams = () => { | ||
const currentBrowserURLParams = getInitialisationParameters() | ||
const toSaveSearchParams = pick( | ||
currentBrowserURLParams, | ||
searchParamsToSaveForAfterAuthRedirect | ||
) | ||
|
||
authLog( | ||
`Temporarly storing the url search params. data: "${JSON.stringify( | ||
toSaveSearchParams | ||
)}"` | ||
) | ||
window.sessionStorage.setItem( | ||
AUTH_STORAGE_URL_SEARCH_PARAMS, | ||
JSON.stringify(toSaveSearchParams) | ||
) | ||
} | ||
|
||
export const addStoredUrlSearchParamsToBrowserHistory = ( | ||
toRetrieveParams, | ||
isClearStore = false | ||
) => { | ||
if (!toRetrieveParams || !toRetrieveParams.length) { | ||
authLog( | ||
'Invalid arguments provided for retrieving temporarly stored url search params, aborting' | ||
) | ||
return | ||
} | ||
|
||
authLog( | ||
`Retrieving temporarly stored url search params, params: "${toRetrieveParams}"` | ||
) | ||
try { | ||
const storedParams = JSON.parse( | ||
window.sessionStorage.getItem(AUTH_STORAGE_URL_SEARCH_PARAMS) | ||
) | ||
|
||
if (isClearStore) { | ||
window.sessionStorage.setItem(AUTH_STORAGE_URL_SEARCH_PARAMS, '') | ||
} | ||
|
||
if (isObject(storedParams)) { | ||
const retrievedParams = pick(storedParams, toRetrieveParams) | ||
addSearchParamsInBrowserHistory(retrievedParams) | ||
return retrievedParams | ||
} else { | ||
authLog('Invalid temporarly stored url search params') | ||
return null | ||
} | ||
} catch (err) { | ||
authLog( | ||
`Error when parsing temporarly stored url search params, err: ${err}` | ||
) | ||
return null | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export const REDIRECT_URI = 'redirect_uri' | ||
export const SSO_REDIRECT = 'sso_redirect' | ||
export const BEARER = 'bearer' | ||
export const PKCE = 'pkce' | ||
export const IMPLICIT = 'implicit' | ||
|
||
export const AUTH_LOGGING_PREFIX = 'OIDC/OAuth#' | ||
|
||
const AUTH_STORAGE_PREFIX = '/auth#' | ||
export const AUTH_STORAGE_SSO_PROVIDERS = `${AUTH_STORAGE_PREFIX}sso_providers` | ||
export const AUTH_STORAGE_STATE = `${AUTH_STORAGE_PREFIX}state` | ||
export const AUTH_STORAGE_CODE_VERIFIER = `${AUTH_STORAGE_PREFIX}code_verifier` | ||
export const AUTH_STORAGE_URL_SEARCH_PARAMS = `${AUTH_STORAGE_PREFIX}url_search_params` |
Oops, something went wrong.