1
0
mirror of synced 2026-02-03 18:01:02 -05:00

Compare commits

...

8 Commits

Author SHA1 Message Date
Dillon Raphael
11fdad3acf Merge branch 'main' into feature/onAuth 2022-10-12 12:58:06 -04:00
Fran Zekan
ba309d9cdd Merge branch 'main' into feature/onAuth 2022-10-03 14:02:16 +02:00
Fran Zekan
7e6ccd0359 Fix pnpm-lock 2022-10-02 01:17:47 +02:00
Fran Zekan
602d461b8e Fix onAuthorize client side 2022-10-02 01:07:45 +02:00
Fran Zekan
f383d10406 Merge branch 'main' into feature/onAuth 2022-10-02 00:28:48 +02:00
Fran Zekan
392440b39e Merge branch 'main' into feature/onAuth 2022-07-22 23:53:32 +02:00
Fran Zekan
9d5e0f5804 Wip testing onAuthorize in client 2022-07-17 23:10:02 +02:00
Fran Zekan
178956a76b Add serverSide onAuthMiddleware hook 2022-07-17 19:03:02 +02:00
9 changed files with 85 additions and 65 deletions

View File

@@ -10,4 +10,4 @@
Bump react, react-dom, @types/react and next versions
This fixes a console warning: `Warning: Received `true` for a non-boolean attribute `global`.` when using `styled-jsx`. Versions bump also fixes React Hydration error that happens on and off when using `redirectAuthenticatedTo`.
This fixes a console warning: `Warning: Received `true`for a non-boolean attribute`global`.` when using `styled-jsx`. Versions bump also fixes React Hydration error that happens on and off when using `redirectAuthenticatedTo`.

View File

@@ -1,5 +1,5 @@
---
"@blitzjs/codemod": patch
---
Add DocumentProps & DocumentContext to the codemod import map
Add DocumentProps & DocumentContext to the codemod import map

View File

@@ -5,4 +5,5 @@
"blitz": patch
"@blitzjs/generator": patch
---
Fixes the supports-color warning for pnpm

View File

@@ -1,2 +1 @@
# toolkit-app-passportjs

View File

@@ -4,7 +4,7 @@ TODO
This is a [Blitz.js](https://github.com/blitz-js/blitz) app.
# ****name****
# \***\*name\*\***
## Getting Started

View File

@@ -6,4 +6,3 @@ export default defineConfig({
hookTimeout: 100000,
},
})

View File

@@ -109,6 +109,7 @@ class PublicDataStore {
}
}
}
export const getPublicDataStore = (): PublicDataStore => {
if (!(window as any).__publicDataStore) {
;(window as any).__publicDataStore = new PublicDataStore()
@@ -257,89 +258,99 @@ export function getAuthValues<TProps = any>(
return {authenticate, redirectAuthenticatedTo}
}
function withBlitzAuthPlugin<TProps = any>(Page: ComponentType<TProps> | BlitzPage<TProps>) {
const AuthRoot = (props: ComponentProps<any>) => {
useSession({suspense: false})
const [mounted, setMounted] = useState(false)
const withBlitzAuthPluginFactory = (hooks: AuthPluginClientOptions["hooks"]) => {
return function withBlitzAuthPlugin<TProps = any>(
Page: ComponentType<TProps> | BlitzPage<TProps>,
) {
const AuthRoot = (props: ComponentProps<any>) => {
useSession({suspense: false})
useEffect(() => {
setMounted(true)
}, [])
const [mounted, setMounted] = useState(false)
mounted && hooks?.onAuthorize?.(getPublicDataStore().getData() as any)
let {authenticate, redirectAuthenticatedTo} = getAuthValues(Page, props)
useEffect(() => {
setMounted(true)
}, [])
useAuthorizeIf(authenticate === true)
let {authenticate, redirectAuthenticatedTo} = getAuthValues(Page, props)
if (typeof window !== "undefined") {
const publicData = getPublicDataStore().getData()
useAuthorizeIf(authenticate === true)
// We read directly from publicData.userId instead of useSession
// so we can access userId on first render. useSession is always empty on first render
if (publicData.userId) {
debug("[BlitzAuthInnerRoot] logged in")
if (typeof window !== "undefined") {
const publicData = getPublicDataStore().getData()
if (typeof redirectAuthenticatedTo === "function") {
redirectAuthenticatedTo = redirectAuthenticatedTo({
session: publicData,
})
}
// We read directly from publicData.userId instead of useSession
// so we can access userId on first render. useSession is always empty on first render
if (publicData.userId) {
debug("[BlitzAuthInnerRoot] logged in")
if (redirectAuthenticatedTo) {
const redirectUrl =
typeof redirectAuthenticatedTo === "string"
? redirectAuthenticatedTo
: formatWithValidation(redirectAuthenticatedTo)
if (mounted) {
debug("[BlitzAuthInnerRoot] redirecting to", redirectUrl)
const error = new RedirectError(redirectUrl)
error.stack = null!
throw error
}
}
} else {
debug("[BlitzAuthInnerRoot] logged out")
if (authenticate && typeof authenticate === "object" && authenticate.redirectTo) {
let {redirectTo} = authenticate
if (typeof redirectTo !== "string") {
redirectTo = formatWithValidation(redirectTo)
if (typeof redirectAuthenticatedTo === "function") {
redirectAuthenticatedTo = redirectAuthenticatedTo({
session: publicData,
})
}
const url = new URL(redirectTo, window.location.href)
url.searchParams.append("next", window.location.pathname)
if (redirectAuthenticatedTo) {
const redirectUrl =
typeof redirectAuthenticatedTo === "string"
? redirectAuthenticatedTo
: formatWithValidation(redirectAuthenticatedTo)
if (mounted) {
debug("[BlitzAuthInnerRoot] redirecting to", url.toString())
const error = new RedirectError(url.toString())
error.stack = null!
throw error
if (mounted) {
debug("[BlitzAuthInnerRoot] redirecting to", redirectUrl)
const error = new RedirectError(redirectUrl)
error.stack = null!
throw error
}
}
} else {
debug("[BlitzAuthInnerRoot] logged out")
if (authenticate && typeof authenticate === "object" && authenticate.redirectTo) {
let {redirectTo} = authenticate
if (typeof redirectTo !== "string") {
redirectTo = formatWithValidation(redirectTo)
}
const url = new URL(redirectTo, window.location.href)
url.searchParams.append("next", window.location.pathname)
if (mounted) {
debug("[BlitzAuthInnerRoot] redirecting to", url.toString())
const error = new RedirectError(url.toString())
error.stack = null!
throw error
}
}
}
}
return <Page {...props} />
}
return <Page {...props} />
}
for (let [key, value] of Object.entries(Page)) {
// @ts-ignore
AuthRoot[key] = value
}
if (process.env.NODE_ENV !== "production") {
AuthRoot.displayName = `BlitzAuthInnerRoot`
}
for (let [key, value] of Object.entries(Page)) {
// @ts-ignore
AuthRoot[key] = value
return AuthRoot
}
if (process.env.NODE_ENV !== "production") {
AuthRoot.displayName = `BlitzAuthInnerRoot`
}
return AuthRoot
}
export interface AuthPluginClientOptions {
cookiePrefix: string
hooks?: {
onAuthorize?: (user: ClientSession) => void
}
}
export const AuthClientPlugin = createClientPlugin((options: AuthPluginClientOptions) => {
globalThis.__BLITZ_SESSION_COOKIE_PREFIX = options.cookiePrefix || "blitz"
return {
withProvider: withBlitzAuthPlugin,
withProvider: withBlitzAuthPluginFactory(options?.hooks),
events: {},
middleware: {},
exports: () => ({

View File

@@ -1,7 +1,7 @@
import type {BlitzServerPlugin, RequestMiddleware, Ctx} from "blitz"
import {assert} from "blitz"
import {IncomingMessage, ServerResponse} from "http"
import {PublicData, SessionModel, SessionConfigMethods} from "../shared/types"
import {PublicData, SessionModel, SessionConfigMethods, SessionContext} from "../shared/types"
import {getSession} from "./auth-sessions"
interface SessionConfigOptions {
@@ -12,6 +12,9 @@ interface SessionConfigOptions {
secureCookies?: boolean
domain?: string
publicDataKeysToSyncAcrossSessions?: string[]
hooks?: {
onAuthMiddleware: (sc: SessionContext["$publicData"]) => void
}
}
interface IsAuthorized {
@@ -108,6 +111,9 @@ export function AuthServerPlugin(options: AuthPluginOptions): BlitzServerPlugin<
if (!res.blitzCtx?.session) {
await getSession(req, res)
}
options.hooks?.onAuthMiddleware(res.blitzCtx.session.$publicData)
return next()
}
@@ -117,6 +123,7 @@ export function AuthServerPlugin(options: AuthPluginOptions): BlitzServerPlugin<
}
return blitzSessionMiddleware
}
return {
requestMiddlewares: [authPluginSessionMiddleware()],
}

View File

@@ -118,8 +118,11 @@ export function passportAuth(config: BlitzPassportConfig): ApiHandler {
const {name, strategy, authenticateOptions} = blitzStrategy
assert(typeof strategy.name !== "undefined", `A passport strategy name was not found for: ${req.query.auth[0]}`)
assert(
typeof strategy.name !== "undefined",
`A passport strategy name was not found for: ${req.query.auth[0]}`,
)
const strategyName = name || strategy.name
passport.use(strategyName, strategy)