nuxt-csurf
Advanced tools
Comparing version 1.6.3 to 1.6.4
@@ -26,3 +26,3 @@ import * as _nuxt_schema from '@nuxt/schema'; | ||
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>; | ||
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>; | ||
@@ -29,0 +29,0 @@ declare module '@nuxt/schema' { |
{ | ||
"name": "nuxt-csurf", | ||
"configKey": "csurf", | ||
"version": "1.6.3", | ||
"version": "1.6.4", | ||
"builder": { | ||
"@nuxt/module-builder": "0.8.3", | ||
"@nuxt/module-builder": "0.8.4", | ||
"unbuild": "2.0.0" | ||
} | ||
} |
@@ -1,11 +0,19 @@ | ||
import type { Ref } from 'vue'; | ||
import type { FetchError } from 'ofetch'; | ||
import type { NitroFetchRequest, AvailableRouterMethod as _AvailableRouterMethod } from 'nitropack'; | ||
import type { AsyncData, KeysOf, PickFrom } from 'nuxt/dist/app/composables/asyncData'; | ||
import { type FetchResult, type UseFetchOptions } from '#app'; | ||
type AvailableRouterMethod<R extends NitroFetchRequest> = _AvailableRouterMethod<R> | Uppercase<_AvailableRouterMethod<R>>; | ||
export declare function useCsrfFetch<ResT = void, ErrorT = FetchError, ReqT extends NitroFetchRequest = NitroFetchRequest, Method extends AvailableRouterMethod<ReqT> = ResT extends void ? 'get' extends AvailableRouterMethod<ReqT> ? 'get' : AvailableRouterMethod<ReqT> : AvailableRouterMethod<ReqT>, _ResT = ResT extends void ? FetchResult<ReqT, Method> : ResT, DataT = _ResT, PickKeys extends KeysOf<DataT> = KeysOf<DataT>, DefaultT = undefined>(request: Ref<ReqT> | ReqT | (() => ReqT), opts?: UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, ReqT, Method>): AsyncData<PickFrom<DataT, PickKeys> | DefaultT, ErrorT | undefined>; | ||
export declare function useCsrfFetch<ResT = void, ErrorT = FetchError, ReqT extends NitroFetchRequest = NitroFetchRequest, Method extends AvailableRouterMethod<ReqT> = ResT extends void ? 'get' extends AvailableRouterMethod<ReqT> ? 'get' : AvailableRouterMethod<ReqT> : AvailableRouterMethod<ReqT>, _ResT = ResT extends void ? FetchResult<ReqT, Method> : ResT, DataT = _ResT, PickKeys extends KeysOf<DataT> = KeysOf<DataT>, DefaultT = DataT>(request: Ref<ReqT> | ReqT | (() => ReqT), opts?: UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, ReqT, Method>): AsyncData<PickFrom<DataT, PickKeys> | DefaultT, ErrorT | undefined>; | ||
export declare function useLazyCsrfFetch<ResT = void, ErrorT = FetchError, ReqT extends NitroFetchRequest = NitroFetchRequest, Method extends AvailableRouterMethod<ReqT> = ResT extends void ? 'get' extends AvailableRouterMethod<ReqT> ? 'get' : AvailableRouterMethod<ReqT> : AvailableRouterMethod<ReqT>, _ResT = ResT extends void ? FetchResult<ReqT, Method> : ResT, DataT = _ResT, PickKeys extends KeysOf<DataT> = KeysOf<DataT>, DefaultT = undefined>(request: Ref<ReqT> | ReqT | (() => ReqT), opts?: Omit<UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, ReqT, Method>, 'lazy'>): AsyncData<PickFrom<DataT, PickKeys> | DefaultT, ErrorT | null>; | ||
export declare function useLazyCsrfFetch<ResT = void, ErrorT = FetchError, ReqT extends NitroFetchRequest = NitroFetchRequest, Method extends AvailableRouterMethod<ReqT> = ResT extends void ? 'get' extends AvailableRouterMethod<ReqT> ? 'get' : AvailableRouterMethod<ReqT> : AvailableRouterMethod<ReqT>, _ResT = ResT extends void ? FetchResult<ReqT, Method> : ResT, DataT = _ResT, PickKeys extends KeysOf<DataT> = KeysOf<DataT>, DefaultT = DataT>(request: Ref<ReqT> | ReqT | (() => ReqT), opts?: UseFetchOptions<_ResT, DataT, PickKeys, DefaultT, ReqT, Method>): AsyncData<PickFrom<DataT, PickKeys> | DefaultT, ErrorT | undefined>; | ||
import { useFetch, type useLazyFetch } from 'nuxt/app'; | ||
type UseCsrfFetch = typeof useFetch; | ||
type UseLazyCsrfFetch = typeof useLazyFetch; | ||
/** | ||
* Fetch data from an API endpoint protected by a CSRF token. SSR-friendly composable. | ||
* See {@link https://nuxt.com/docs/api/composables/use-fetch} | ||
* @param url The URL to fetch | ||
* @param options extends $fetch options and useAsyncData options | ||
*/ | ||
export declare const useCsrfFetch: UseCsrfFetch; | ||
export declare const useLazyCsrfFetch: UseLazyCsrfFetch; | ||
/** | ||
* Retrieves the CSRF token from either the server or the client-side context. | ||
* See {@link https://github.com/Morgbn/nuxt-csurf#usecsrf} | ||
* @returns | ||
* - `csrf`: The CSRF token, either retrieved from the server or from the meta tag in the client. | ||
* - `headerName`: The name of the CSRF header, as configured in the public runtime configuration. Defaults to an empty string if not set. | ||
*/ | ||
export declare function useCsrf(): { | ||
@@ -12,0 +20,0 @@ csrf: any; |
@@ -1,26 +0,15 @@ | ||
import { useFetch, useNuxtApp, useRuntimeConfig } from "#app"; | ||
export function useCsrfFetch(request, arg1, arg2) { | ||
const [opts = {}, autoKey] = typeof arg1 === "string" ? [{}, arg1] : [arg1, arg2]; | ||
const { csrf, headerName } = useCsrf(); | ||
opts.headers = opts.headers || {}; | ||
opts.headers[headerName] = csrf; | ||
return useFetch( | ||
request, | ||
opts, | ||
// @ts-expect-error we pass an extra argument with the resolved auto-key to prevent another from being injected | ||
autoKey | ||
); | ||
} | ||
export function useLazyCsrfFetch(request, arg1, arg2) { | ||
const [opts, autoKey] = typeof arg1 === "string" ? [{}, arg1] : [arg1, arg2]; | ||
return useCsrfFetch( | ||
request, | ||
{ | ||
...opts, | ||
lazy: true | ||
}, | ||
// @ts-expect-error we pass an extra argument with the resolved auto-key to prevent another from being injected | ||
autoKey | ||
); | ||
} | ||
import { useFetch, useNuxtApp, useRuntimeConfig } from "nuxt/app"; | ||
export const useCsrfFetch = (url, options) => { | ||
return useFetch(url, { | ||
...options, | ||
$fetch: useNuxtApp().$csrfFetch | ||
}); | ||
}; | ||
export const useLazyCsrfFetch = (url, options) => { | ||
return useFetch(url, { | ||
...options, | ||
lazy: true, | ||
$fetch: useNuxtApp().$csrfFetch | ||
}); | ||
}; | ||
export function useCsrf() { | ||
@@ -27,0 +16,0 @@ const headerName = useRuntimeConfig().public.csurf.headerName ?? ""; |
@@ -1,11 +0,2 @@ | ||
import type { FetchOptions, FetchRequest, $Fetch } from 'ofetch'; | ||
interface ResponseMap { | ||
blob: Blob; | ||
text: string; | ||
arrayBuffer: ArrayBuffer; | ||
stream: ReadableStream<Uint8Array>; | ||
} | ||
type ResponseType = keyof ResponseMap | 'json'; | ||
type MappedType<R extends ResponseType, JsonType = any> = R extends keyof ResponseMap ? ResponseMap[R] : JsonType; | ||
type $CsrfFetch = <T = any, R extends ResponseType = 'json'>(request: FetchRequest, options?: FetchOptions<R>, fetch?: $Fetch) => Promise<MappedType<R, T>>; | ||
import { type $Fetch } from 'ofetch'; | ||
declare const _default: any; | ||
@@ -15,3 +6,3 @@ export default _default; | ||
interface NuxtApp { | ||
$csrfFetch: $CsrfFetch; | ||
$csrfFetch: $Fetch; | ||
} | ||
@@ -21,4 +12,4 @@ } | ||
interface ComponentCustomProperties { | ||
$csrfFetch: $CsrfFetch; | ||
$csrfFetch: $Fetch; | ||
} | ||
} |
import { $fetch } from "ofetch"; | ||
import { defineNuxtPlugin, useCsrf } from "#imports"; | ||
import { useCsrf } from "./composables.js"; | ||
import { defineNuxtPlugin } from "#app"; | ||
export default defineNuxtPlugin(() => { | ||
const { csrf, headerName } = useCsrf(); | ||
const csrfFetch = (request, options, fetch = $fetch) => { | ||
if (!options) | ||
options = {}; | ||
options.headers = options.headers || {}; | ||
options.headers[headerName] = csrf; | ||
return fetch(request, options); | ||
}; | ||
const csrfFetch = $fetch.create({ | ||
onRequest({ options }) { | ||
const { csrf, headerName } = useCsrf(); | ||
options.headers = options.headers || {}; | ||
options.headers[headerName] = csrf; | ||
} | ||
}); | ||
return { | ||
@@ -13,0 +13,0 @@ provide: { csrfFetch } |
import type { ModuleOptions } from '../../types.js'; | ||
export declare const useSecretKey: (options: ModuleOptions) => Promise<JsonWebKey>; | ||
export declare const useSecretKey: (options: ModuleOptions) => Promise<CryptoKey>; |
import * as csrf from "uncsrf"; | ||
import { getCookie, setCookie } from "h3"; | ||
import { useSecretKey } from "../helpers.js"; | ||
import { useRuntimeConfig } from "#imports"; | ||
import { useRuntimeConfig, getRouteRules } from "#imports"; | ||
const defineNitroPlugin = (def) => def; | ||
@@ -11,6 +11,10 @@ export default defineNitroPlugin((nitroApp) => { | ||
nitroApp.hooks.hook("request", async (event) => { | ||
const { csurf } = getRouteRules(event); | ||
const needCookie = !(csurf === false || csurf?.enabled === false); | ||
let secret = getCookie(event, cookieKey); | ||
if (!secret) { | ||
secret = csrf.randomSecret(); | ||
setCookie(event, cookieKey, secret, csrfConfig.cookie); | ||
if (needCookie) { | ||
setCookie(event, cookieKey, secret, csrfConfig.cookie); | ||
} | ||
} | ||
@@ -17,0 +21,0 @@ event.context.csrfToken = await csrf.create(secret, await useSecretKey(csrfConfig), csrfConfig.encryptAlgorithm); |
{ | ||
"name": "nuxt-csurf", | ||
"version": "1.6.3", | ||
"version": "1.6.4", | ||
"description": "Nuxt Cross-Site Request Forgery (CSRF) Prevention", | ||
@@ -34,15 +34,15 @@ "keywords": [ | ||
"dependencies": { | ||
"@nuxt/kit": "^3.12.4", | ||
"@nuxt/kit": "^3.13.2", | ||
"defu": "^6.1.4", | ||
"uncsrf": "^1.1.1" | ||
"uncsrf": "^1.2.0" | ||
}, | ||
"devDependencies": { | ||
"@nuxt/devtools": "^1.3.9", | ||
"@nuxt/eslint-config": "^0.3.13", | ||
"@nuxt/module-builder": "^0.8.3", | ||
"@nuxt/schema": "^3.12.4", | ||
"@types/node": "^20.16.1", | ||
"eslint": "^9.9.0", | ||
"nuxt": "^3.12.4", | ||
"typescript": "^5.5.4" | ||
"@nuxt/devtools": "^1.6.0", | ||
"@nuxt/eslint-config": "^0.6.1", | ||
"@nuxt/module-builder": "^0.8.4", | ||
"@nuxt/schema": "^3.13.2", | ||
"@types/node": "^22.8.2", | ||
"eslint": "^9.13.0", | ||
"nuxt": "^3.13.2", | ||
"typescript": "^5.6.3" | ||
}, | ||
@@ -49,0 +49,0 @@ "repository": { |
@@ -15,3 +15,4 @@ ![nuxt-oa-social-card](https://github.com/Morgbn/nuxt-csurf/assets/25689856/7f49b654-c682-4f15-9e40-6ba9644e28ac) | ||
✅ Per-route configuration \ | ||
✅ TypeScript | ||
✅ TypeScript \ | ||
❌ Don't support static hosting and [nitro prerender](https://nitro.unjs.io/config#prerender) due to certain limitations [*](#limitations) | ||
@@ -39,3 +40,3 @@ ## Installation | ||
methodsToProtect: ['POST', 'PUT', 'PATCH'], // the request methods we want CSRF protection for | ||
encryptSecret: /** a 32 bits secret */, // only for non serverless runtime, random bytes by default | ||
encryptSecret: /** a 32 bits secret */, // for stateless server (like serverless runtime), random bytes by default | ||
encryptAlgorithm: 'aes-256-cbc', // by default 'aes-256-cbc' (node), 'AES-CBC' (serverless) | ||
@@ -88,2 +89,11 @@ addCsrfTokenToEventCtx: true, // default false, to run useCsrfFetch on server set it to true | ||
### Try production on localhost (`yarn preview`): | ||
```.env | ||
NITRO_CSURF_HTTPS=false | ||
NITRO_CSURF_COOKIE_KEY=csrf | ||
``` | ||
## Limitations | ||
The CSRF Token value is stored in the DOM as described [in Owasp's CSRF cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#storing-the-csrf-token-value-in-the-dom). So the DOM has to be generated for each new page request, which is not the case with a static site (or prerendered routes). See error #42 | ||
## Credits | ||
@@ -90,0 +100,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
113
0
17599
267
Updated@nuxt/kit@^3.13.2
Updateduncsrf@^1.2.0