From 4e43b9aea8d7cb298be657c57984dd46c983851a Mon Sep 17 00:00:00 2001 From: Rakov Date: Wed, 4 Oct 2023 17:21:31 +0300 Subject: [PATCH 1/4] fix(insport.live): insport.live deploy --- .drone.yml | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/.drone.yml b/.drone.yml index 02b7db11..e0fc8e13 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1007,3 +1007,56 @@ steps: - aws cloudfront create-invalidation --distribution-id E15IFY23VM147K --paths "/*" depends_on: - make-rustat + +--- +kind: pipeline +type: docker +name: deploy insport.live + +concurrency: + limit: 1 + +platform: + os: linux + arch: amd64 + +trigger: + ref: + - refs/heads/insport.live + +steps: + - name: npm-install + image: node:16-alpine + environment: + REACT_APP_STRIPE_PK: + from_secret: REACT_APP_STRIPE_PK + commands: + - apk add --no-cache make + - npm install --legacy-peer-deps + + - name: make-insport-live + image: node:16-alpine + environment: + REACT_APP_STRIPE_PK: + from_secret: REACT_APP_STRIPE_PK + commands: + - apk add --no-cache make + - make insport-live-prod + depends_on: + - npm-install + + - name: deploy-insport-live + image: amazon/aws-cli:latest + environment: + AWS_ACCESS_KEY_ID: + from_secret: AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY: + from_secret: AWS_SECRET_ACCESS_KEY + AWS_DEFAULT_REGION: + from_secret: AWS_DEFAULT_REGION + AWS_MAX_ATTEMPTS: 10 + commands: + - aws s3 sync build_insport_live s3://insports-live --delete + - aws cloudfront create-invalidation --distribution-id E1LBC88VYP6XVB --paths "/*" + depends_on: + - make-insport-live \ No newline at end of file -- 2.30.2 From 3152372c39d9b8749e97c7dce21bdb95a12424e6 Mon Sep 17 00:00:00 2001 From: Rakov Date: Wed, 4 Oct 2023 17:29:13 +0300 Subject: [PATCH 2/4] fix(inposrt.live): insport.live makefile build --- Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Makefile b/Makefile index 61a42fb1..813debb9 100644 --- a/Makefile +++ b/Makefile @@ -225,6 +225,15 @@ rustat-prod: BUILD_PATH=build_rustat \ npm run build && cp -r .well-known build_rustat +insport-live-prod: + rm -rf build_insport_live && \ + REACT_APP_TYPE=ott \ + REACT_APP_ENV=staging \ + REACT_APP_CLIENT=lff \ + REACT_APP_STRIPE_PK=pk_live_51J5TEYEDSxVnTgDW5XxhC6ntKZKddXgKHq5HOCDmJTdfSKluMYCdLHOcUA3Miuy8HesxG1eS4c0dQRQpMsEHRrQL00USpu5xIq \ + BUILD_PATH=build_insport_live \ + npm run build && cp -r .well-known build_insport_live + deploy-all: prod preprod facr-prod lff-prod diwansport-prod india-prod fqtv-prod rustat-prod test: -- 2.30.2 From ccb265cb2e2624492390fbd4fc3cc7f9afb0c500 Mon Sep 17 00:00:00 2001 From: Rakov Date: Wed, 4 Oct 2023 17:13:58 +0300 Subject: [PATCH 3/4] Revert "fix(#699): auth token" This reverts commit fc3a3c052c5667985c24a7d4425b60d618dcc43e. --- public/silent-refresh.html | 41 +++---------------- src/features/AuthStore/hooks/useAuth.tsx | 28 ++----------- src/features/SystemSettings/hooks.tsx | 1 - src/helpers/cookie/index.tsx | 2 +- src/requests/getCredentials.tsx | 51 ------------------------ 5 files changed, 9 insertions(+), 114 deletions(-) delete mode 100644 src/requests/getCredentials.tsx diff --git a/public/silent-refresh.html b/public/silent-refresh.html index 56cfb515..852cc138 100644 --- a/public/silent-refresh.html +++ b/public/silent-refresh.html @@ -1,46 +1,15 @@ - - - + - - \ No newline at end of file + diff --git a/src/features/AuthStore/hooks/useAuth.tsx b/src/features/AuthStore/hooks/useAuth.tsx index 41ec48e9..115a0a28 100644 --- a/src/features/AuthStore/hooks/useAuth.tsx +++ b/src/features/AuthStore/hooks/useAuth.tsx @@ -14,7 +14,7 @@ import isString from 'lodash/isString' import isBoolean from 'lodash/isBoolean' import includes from 'lodash/includes' -import { PAGES, isIOS } from 'config' +import { PAGES } from 'config' import { addLanguageUrlParam, @@ -24,7 +24,6 @@ import { setCookie, removeCookie, isMatchPage, - getDomain, } from 'helpers' import { @@ -66,14 +65,6 @@ export const useAuth = () => { }) } - const parseJwt = (value: string) => { - const base64Url = value.split('.')[1] - const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/') - const jsonPayload = decodeURIComponent(window.atob(base64).split('').map((c) => `%${(`00${c.charCodeAt(0).toString(16)}`).slice(-2)}`).join('')) - - return JSON.parse(jsonPayload) - } - const login = useCallback(async () => { userManager.signinRedirect({ extraQueryParams: { lang } }) }, [lang]) @@ -88,7 +79,6 @@ export const useAuth = () => { removeToken() if (key !== 'saveToken') { removeCookie('access_token') - removeCookie('refresh_token') } // eslint-disable-next-line react-hooks/exhaustive-deps }, [lang]) @@ -168,21 +158,12 @@ export const useAuth = () => { } } - const saveRefreshToken = (value: string) => { - const ref = parseJwt(value) - const expires = `expires=${new Date((ref.exp * 1000)).toUTCString()}` - document.cookie = `refresh_token=${value};${expires};path=/;domain=${getDomain()};secure;SameSite=None` - } - - const signinRedirectCallback = useCallback(async (refreshToken: string | null) => { + const signinRedirectCallback = useCallback(() => { setPage(history.location.pathname) userManager.signinRedirectCallback() .then((loadedUser) => { storeUser(loadedUser) - - if (isIOS && refreshToken) saveRefreshToken(refreshToken) - queryParamStorage.clear() if (page.includes(PAGES.useraccount)) { history.push(PAGES.home) @@ -206,13 +187,10 @@ export const useAuth = () => { const searchToken = urlSearch.get('access_token') const searchRefToken = urlSearch.get('id_token') const searchExp = urlSearch.get('expires_in') - const refreshToken = urlSearch.get('refresh_token') const isRedirectedBackFromAuthProvider = Boolean(searchToken && searchRefToken && searchExp) - isRedirectedBackFromAuthProvider - ? signinRedirectCallback(refreshToken) - : checkUser() + isRedirectedBackFromAuthProvider ? signinRedirectCallback() : checkUser() // eslint-disable-next-line react-hooks/exhaustive-deps }, [ checkUser, diff --git a/src/features/SystemSettings/hooks.tsx b/src/features/SystemSettings/hooks.tsx index fb200f3e..8ab7df2e 100644 --- a/src/features/SystemSettings/hooks.tsx +++ b/src/features/SystemSettings/hooks.tsx @@ -38,7 +38,6 @@ export const useSystemSettings = () => { setSelectedApi(api.value) removeToken() removeCookie('access_token') - removeCookie('refresh_token') window.location.reload() } diff --git a/src/helpers/cookie/index.tsx b/src/helpers/cookie/index.tsx index 87b22f22..cbad2d33 100644 --- a/src/helpers/cookie/index.tsx +++ b/src/helpers/cookie/index.tsx @@ -29,7 +29,7 @@ export const checkCookie = (name: string) => { return token[0] } -export const getDomain = () => ( +const getDomain = () => ( process.env.NODE_ENV === 'development' ? 'localhost' : '.insports.tv' diff --git a/src/requests/getCredentials.tsx b/src/requests/getCredentials.tsx deleted file mode 100644 index dce5eb7e..00000000 --- a/src/requests/getCredentials.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { AUTH_SERVICE } from 'config' -import { ClientIds } from 'config/clients/types' - -export type TokenFailedResponse = { - error?: { - code: number, - message: string, - }, - ok: false, -} - -type TokenResponse = { - access_token: string, - id_token: string, - refresh_token: string, -} - -type TokenProps = { - client_id: ClientIds, - email?: 'string', - grant_type?: 'password' | 'refresh_token', - id_token?: 'string', - password?: 'string', - refresh_token: string, -} - -export const getCredentials = async ({ - client_id, - grant_type = 'refresh_token', - refresh_token, -}: TokenProps): Promise => { - const url = new URL(`${AUTH_SERVICE}/token`) - - const credetials = await fetch(url, { - body: JSON.stringify({ - client_id, - grant_type, - refresh_token, - }), - headers: { - 'Content-Type': 'application/json', - }, - method: 'POST', - }) - - const body: TokenResponse | TokenFailedResponse = await credetials.json() - - if ('ok' in body) return Promise.reject(body.error) - - return Promise.resolve(body) -} -- 2.30.2 From 7a2423568aba3cebd4f5a8ff7001deba135c80d7 Mon Sep 17 00:00:00 2001 From: Rakov Date: Thu, 5 Oct 2023 10:42:32 +0300 Subject: [PATCH 4/4] fix(refresh): save refresh lff facr --- public/silent-refresh.html | 23 ++++++++++---- src/features/AuthStore/hooks/useAuth.tsx | 38 +++++++++++++++++++----- src/features/SystemSettings/hooks.tsx | 5 ++-- src/helpers/token/index.tsx | 13 ++++++++ 4 files changed, 65 insertions(+), 14 deletions(-) diff --git a/public/silent-refresh.html b/public/silent-refresh.html index 852cc138..840a0cce 100644 --- a/public/silent-refresh.html +++ b/public/silent-refresh.html @@ -1,15 +1,28 @@ + + - + - + + \ No newline at end of file diff --git a/src/features/AuthStore/hooks/useAuth.tsx b/src/features/AuthStore/hooks/useAuth.tsx index 115a0a28..965206b9 100644 --- a/src/features/AuthStore/hooks/useAuth.tsx +++ b/src/features/AuthStore/hooks/useAuth.tsx @@ -14,7 +14,11 @@ import isString from 'lodash/isString' import isBoolean from 'lodash/isBoolean' import includes from 'lodash/includes' -import { PAGES } from 'config' +import { + PAGES, + isFacrClient, + isLffClient, +} from 'config' import { addLanguageUrlParam, @@ -24,6 +28,10 @@ import { setCookie, removeCookie, isMatchPage, + REFRESH_TOKEN_KEY, + removeRefreshToken, + writeRefreshToken, + readRefreshToken, } from 'helpers' import { @@ -77,6 +85,7 @@ export const useAuth = () => { userManager.signoutRedirect({ post_logout_redirect_uri: urlWithLang }) }) removeToken() + removeRefreshToken() if (key !== 'saveToken') { removeCookie('access_token') } @@ -158,12 +167,18 @@ export const useAuth = () => { } } - const signinRedirectCallback = useCallback(() => { + const signinRedirectCallback = useCallback(async (refreshToken: string | null) => { setPage(history.location.pathname) userManager.signinRedirectCallback() .then((loadedUser) => { storeUser(loadedUser) + + if ( + refreshToken + && (isLffClient || isFacrClient) + ) writeRefreshToken(refreshToken) + queryParamStorage.clear() if (page.includes(PAGES.useraccount)) { history.push(PAGES.home) @@ -175,7 +190,7 @@ export const useAuth = () => { setPage('') setSearch('') }).catch(login) - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ login, storeUser, @@ -187,11 +202,14 @@ export const useAuth = () => { const searchToken = urlSearch.get('access_token') const searchRefToken = urlSearch.get('id_token') const searchExp = urlSearch.get('expires_in') + const refreshToken = urlSearch.get(REFRESH_TOKEN_KEY) const isRedirectedBackFromAuthProvider = Boolean(searchToken && searchRefToken && searchExp) - isRedirectedBackFromAuthProvider ? signinRedirectCallback() : checkUser() - // eslint-disable-next-line react-hooks/exhaustive-deps + isRedirectedBackFromAuthProvider + ? signinRedirectCallback(refreshToken) + : checkUser() + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ checkUser, signinRedirectCallback, @@ -221,7 +239,7 @@ export const useAuth = () => { }, [reChekNewDevice]) useEffect(() => { - if (!needCheckNewDeviсe && !user) return undefined + if (!needCheckNewDeviсe || !user) return undefined const startCheckDevice = setInterval(checkNewDevice, 20000) isNewDeviceLogin && clearInterval(startCheckDevice) return () => clearInterval(startCheckDevice) @@ -240,7 +258,13 @@ export const useAuth = () => { // библиотека oidc-client не поддерживает обновление токена только на 1 вкладке // @ts-ignore if (window.isMaster()) { - userManager.signinSilent().catch(logout) + // safari ограничивает доступ к куке через крос доменные запросы + // передаем рефреш токен через квери параметры + userManager.signinSilent({ + extraQueryParams: (isLffClient || isFacrClient) && { + refresh_token: readRefreshToken(), + }, + }).catch(logout) } } // если запросы вернули 401 | 403 diff --git a/src/features/SystemSettings/hooks.tsx b/src/features/SystemSettings/hooks.tsx index 8ab7df2e..575d7168 100644 --- a/src/features/SystemSettings/hooks.tsx +++ b/src/features/SystemSettings/hooks.tsx @@ -9,8 +9,8 @@ import { SELECTED_API_KEY } from 'helpers/selectedApi' import { useToggle } from 'hooks/useToggle' import { useLocalStore } from 'hooks/useStorage' -import { removeToken } from '../../helpers' -import { removeCookie } from '../../helpers/cookie' +import { removeRefreshToken, removeToken } from 'helpers' +import { removeCookie } from 'helpers/cookie' type FormElement = HTMLFormElement & { api: HTMLInputElement & { @@ -37,6 +37,7 @@ export const useSystemSettings = () => { const { api } = e.currentTarget setSelectedApi(api.value) removeToken() + removeRefreshToken() removeCookie('access_token') window.location.reload() } diff --git a/src/helpers/token/index.tsx b/src/helpers/token/index.tsx index 0c4e59f8..6665e79e 100644 --- a/src/helpers/token/index.tsx +++ b/src/helpers/token/index.tsx @@ -1,4 +1,5 @@ export const TOKEN_KEY = 'token' +export const REFRESH_TOKEN_KEY = 'refresh_token' export const readToken = () => ( localStorage.getItem(TOKEN_KEY) @@ -11,3 +12,15 @@ export const writeToken = (token: string) => ( export const removeToken = () => ( localStorage.removeItem(TOKEN_KEY) ) + +export const removeRefreshToken = () => { + localStorage.removeItem(REFRESH_TOKEN_KEY) +} + +export const writeRefreshToken = (token: string) => ( + localStorage.setItem(REFRESH_TOKEN_KEY, token) +) + +export const readRefreshToken = () => ( + localStorage.getItem(REFRESH_TOKEN_KEY) +) -- 2.30.2