Skip to content

Commit

Permalink
fix: Make refreshToken work in worker and node env
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The `data-cozy-token` injection is no longer supported
for refreshToken.

We used to rely on DOMParser to extract the new token during a
refreshToken procedure. However, DOMParser is a web API, which is not
available in web workers, nor in node env.
Therefore, we implement or own HTML parsing, relying on the `data-cozy`
attribute in HTML. We tried using external libraries such as JSDom,
fauxdom or linkedom, but got build issues with all those libs. It was
somehow manageable, but required some additional config in consuimng
apps. As the HTML parsing is quite basic, we decided that it is not
worth the effort, and we now do the parsing ourselves, making it
available in web, workers, and node envs.

As a consequence, we do not support the `data-cozy-token` existence
anymore, as it would require extra work and is seen as deprecated for
several years now. If your app still somehow require it, you need to
migrate the app template to rely on `data-cozy` like this:
https://github.com/cozy/cozy-drive/blob/master/src/targets/browser/index.ejs#L37
  • Loading branch information
paultranvan committed Feb 11, 2025
1 parent be98992 commit 753cad4
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 23 deletions.
34 changes: 13 additions & 21 deletions packages/cozy-stack-client/src/CozyStackClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,44 +191,36 @@ class CozyStackClient {
credentials: 'include'
}

if (!global.document) {
throw new Error('Not in a web context, cannot refresh token')
}

const response = await fetch('/?refreshToken', options)

if (!response.ok) {
throw new Error(
"couldn't fetch a new token - response " + response.statusCode
"Couldn't fetch a new token - response " + response.statusCode
)
}
const html = await response.text()
const parser = new DOMParser()
const doc = parser.parseFromString(html, 'text/html')
if (!doc) {
throw Error("couldn't fetch a new token - doc is not html")
}
const appNode = doc.querySelector('div[role="application"]')
if (!appNode) {
throw Error("couldn't fetch a new token - no div[role=application]")
const match = html.match(/data-cozy="([^"]+)"/)
if (!match || match.length < 2) {
throw new Error(
"Couldn't fetch a new token - no data-cozy element found in HTML"
)
}
const data = appNode.dataset.cozy
? JSON.parse(appNode.dataset.cozy)
: { ...appNode.dataset }
const htmlCozyData = match[1].replace(/&#34;/g, '"')
const cozyData = JSON.parse(htmlCozyData)

let { token } = data
let { token } = cozyData
if (token) {
token = token || data.cozyToken
token = token || cozyData.cozyToken
}

if (!token) {
throw Error(
"couldn't fetch a new token -- missing data-cozy or data-cozy-token attribute"
)
throw Error("Couldn't fetch a new token - missing in data-cozy attribute")
}
const newToken = new AppToken(token)
this.setToken(newToken)
this.onTokenRefresh(newToken)
logger.info('Token successfully refreshed')

return newToken
}

Expand Down
5 changes: 3 additions & 2 deletions packages/cozy-stack-client/src/CozyStackClient.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const FAKE_INIT_OPTIONS = {
const FAKE_APP_TOKEN =
'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhcHAiLCJpYXQiOjE1NTYxMTIwOTQsImlzcyI6ImVkYXMubXljb3p5LmNsb3VkIiwic3ViIjoiaG9tZSIsInNlc3Npb25faWQiOiI4YjI1ZTgzNTkwYTg5MDg0MDUzNDIxZGE0ZmZlOTMwNiJ9.gA3Xnoliu43gwpuO88O6G59rVP_HClZ_vBp96pEjVNnZDpxU4ZnQoWmICoLXih4PvFZRj2eHjnG-eqnJx6XM2A'

const FAKE_DATA_COZY = JSON.stringify({
const FAKE_DATA_COZY_STR = JSON.stringify({
app: {
editor: 'Cozy',
icon: 'icon.svg',
Expand All @@ -36,6 +36,7 @@ const FAKE_DATA_COZY = JSON.stringify({
token: `${FAKE_APP_TOKEN}`,
tracking: false
})
const FAKE_DATA_COZY = FAKE_DATA_COZY_STR.replace(/"/g, '&#34;')

const FAKE_APP_HTML = `<!DOCTYPE html><html lang="fr"><head><meta charset="utf-8"><title>Cozy Home</title>
<link rel="icon" href="//test.mycozy.cloud/assets/favicon.f56cf1d03b.ico">
Expand All @@ -45,7 +46,7 @@ const FAKE_APP_HTML = `<!DOCTYPE html><html lang="fr"><head><meta charset="utf-8
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials"><meta name="msapplication-TileColor" content="#2b5797"><meta name="theme-color" content="#ffffff"><meta name="viewport" content="width=device-width,height=device-height,initial-scale=1,viewport-fit=cover"><link rel="stylesheet" href="vendors/home.c451e5ac76c8377b20c5.0.min.css"><link rel="stylesheet" href="app/home.cbb1b1050b936df11fbd.min.css"><link rel="stylesheet" type="text/css" href="//test.mycozy.cloud/assets/styles/theme.faa4e12bdc.css"> <script src="//test.mycozy.cloud/assets/js/cozy-client.605c649bc3.min.js"></script>
<link rel="stylesheet" type="text/css" href="//test.mycozy.cloud/assets/fonts/fonts.33109548ca.css">
<link rel="stylesheet" type="text/css" href="//test.mycozy.cloud/assets/css/cozy-bar.6effa2d88c.min.css">
<script src="//test.mycozy.cloud/assets/js/cozy-bar.f99c08ee53.min.js"></script></head><body><div role="application" data-cozy='${FAKE_DATA_COZY}'><script src="vendors/home.a664629f1a5622ccb459.js"></script><script src="app/home.455bbc269323b2c64382.js"></script><script src="//test.mycozy.cloud/assets/js/piwik.js" async></script></div></body></html>
<script src="//test.mycozy.cloud/assets/js/cozy-bar.f99c08ee53.min.js"></script></head><body><div role="application" data-cozy="${FAKE_DATA_COZY}"><script src="vendors/home.a664629f1a5622ccb459.js"></script><script src="app/home.455bbc269323b2c64382.js"></script><script src="//test.mycozy.cloud/assets/js/piwik.js" async></script></div></body></html>
`

describe('CozyStackClient', () => {
Expand Down

0 comments on commit 753cad4

Please sign in to comment.