@stacksjs/defaults 0.74.55 → 0.74.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -26,12 +26,17 @@ export default new Action({
|
|
|
26
26
|
// rather than trusting the bearer token alone (a stolen/leaked
|
|
27
27
|
// token shouldn't be enough to turn off the second factor it's
|
|
28
28
|
// meant to help guard against).
|
|
29
|
-
|
|
29
|
+
// Bind reconfirmation to the same account and password version while
|
|
30
|
+
// disabling. A concurrent password reset must invalidate this request.
|
|
31
|
+
const confirmed = await Auth.withVerifiedCredentials({ email: user.email, password }, async (verifiedUser) => {
|
|
32
|
+
if (String(verifiedUser.id) !== String(user.id))
|
|
33
|
+
return false
|
|
34
|
+
await disableTwoFactor(user.id as number)
|
|
35
|
+
return true
|
|
36
|
+
})
|
|
30
37
|
if (!confirmed)
|
|
31
38
|
return response.unauthorized('Incorrect password')
|
|
32
39
|
|
|
33
|
-
await disableTwoFactor(user.id as number)
|
|
34
|
-
|
|
35
40
|
return response.json({ enabled: false })
|
|
36
41
|
},
|
|
37
42
|
})
|
package/app/Middleware/Csrf.ts
CHANGED
|
@@ -144,7 +144,34 @@ export function createCsrfCookie(req: Request, minted?: string): string {
|
|
|
144
144
|
return `${CSRF_COOKIE_PREFIX}${token}${suffix}`
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Whether a browser could go on to use a CSRF token from this response.
|
|
149
|
+
*
|
|
150
|
+
* A page carries the forms that submit it, and an API answer is what an SPA
|
|
151
|
+
* reads before its next request. A stylesheet, script, font or image is
|
|
152
|
+
* neither, and a cookie on one is worse than useless: a response that sets a
|
|
153
|
+
* cookie is one no shared cache will store, so seeding every static file kept
|
|
154
|
+
* the site's whole asset set out of the CDN (every file came back
|
|
155
|
+
* `cf-cache-status: BYPASS`). A cacheable file carrying a per-visitor token is
|
|
156
|
+
* also the shape of a leak, should any cache in the path store it anyway.
|
|
157
|
+
*
|
|
158
|
+
* No content type at all (a redirect, an empty answer) keeps the old
|
|
159
|
+
* behaviour: it says nothing about what the browser is looking at.
|
|
160
|
+
*/
|
|
161
|
+
export function responseMayUseCsrfToken(response: Response): boolean {
|
|
162
|
+
const type = (response.headers.get('content-type') || '').split(';')[0].trim().toLowerCase()
|
|
163
|
+
if (!type)
|
|
164
|
+
return true
|
|
165
|
+
return type === 'text/html'
|
|
166
|
+
|| type === 'application/xhtml+xml'
|
|
167
|
+
|| type === 'application/json'
|
|
168
|
+
|| type.endsWith('+json')
|
|
169
|
+
}
|
|
170
|
+
|
|
147
171
|
export function seedCsrfCookieIfMissing(req: Request, response: Response, minted?: string, responseHasNoCookies = false): Response {
|
|
172
|
+
if (!responseMayUseCsrfToken(response))
|
|
173
|
+
return response
|
|
174
|
+
|
|
148
175
|
// A token the router minted before rendering wins over "the header already
|
|
149
176
|
// has one", because it put that value in the header itself - and the page
|
|
150
177
|
// has already embedded it in every form it drew. Generating a second token
|
package/ide/vscode/package.json
CHANGED
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/defaults",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.74.
|
|
5
|
+
"version": "0.74.56",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/stacksjs/stacks.git",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@iconify-json/f7": "^1.2.2",
|
|
57
57
|
"@iconify-json/hugeicons": "^1.2.27",
|
|
58
|
-
"@stacksjs/mobile": "^0.74.
|
|
58
|
+
"@stacksjs/mobile": "^0.74.56",
|
|
59
59
|
"@stacksjs/sanitizer": "^0.2.113",
|
|
60
60
|
"ts-qr-codes": "^0.1.8"
|
|
61
61
|
}
|