@netlify/identity 0.1.1-alpha.21 → 0.1.1-alpha.22
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.
- package/README.md +41 -15
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -620,32 +620,58 @@ export function load() {
|
|
|
620
620
|
|
|
621
621
|
### Handling OAuth callbacks in SPAs
|
|
622
622
|
|
|
623
|
-
All SPA frameworks need a callback handler that runs on page load to process OAuth redirects, email confirmations, and password recovery tokens.
|
|
623
|
+
All SPA frameworks need a callback handler that runs on page load to process OAuth redirects, email confirmations, and password recovery tokens. Use a **wrapper component** that blocks page content while processing tokens. This prevents a flash of unauthenticated content that occurs when the page renders before the callback completes.
|
|
624
624
|
|
|
625
625
|
```tsx
|
|
626
626
|
// React component (works with Next.js, Remix, TanStack Start)
|
|
627
|
-
import { useEffect } from 'react'
|
|
627
|
+
import { useEffect, useState } from 'react'
|
|
628
628
|
import { handleAuthCallback } from '@netlify/identity'
|
|
629
629
|
|
|
630
|
-
|
|
630
|
+
const AUTH_HASH_PATTERN = /^#(confirmation_token|recovery_token|invite_token|email_change_token|access_token)=/
|
|
631
|
+
|
|
632
|
+
export function CallbackHandler({ children }: { children: React.ReactNode }) {
|
|
633
|
+
const [processing, setProcessing] = useState(
|
|
634
|
+
() => typeof window !== 'undefined' && AUTH_HASH_PATTERN.test(window.location.hash),
|
|
635
|
+
)
|
|
636
|
+
const [error, setError] = useState<string | null>(null)
|
|
637
|
+
|
|
631
638
|
useEffect(() => {
|
|
632
|
-
if (!window.location.hash) return
|
|
633
|
-
|
|
634
|
-
handleAuthCallback()
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
639
|
+
if (!window.location.hash || !AUTH_HASH_PATTERN.test(window.location.hash)) return
|
|
640
|
+
|
|
641
|
+
handleAuthCallback()
|
|
642
|
+
.then((result) => {
|
|
643
|
+
if (!result) {
|
|
644
|
+
setProcessing(false)
|
|
645
|
+
return
|
|
646
|
+
}
|
|
647
|
+
if (result.type === 'invite') {
|
|
648
|
+
window.location.href = `/accept-invite?token=${result.token}`
|
|
649
|
+
} else {
|
|
650
|
+
window.location.href = '/dashboard'
|
|
651
|
+
}
|
|
652
|
+
})
|
|
653
|
+
.catch((err) => {
|
|
654
|
+
setError(err instanceof Error ? err.message : 'Callback failed')
|
|
655
|
+
setProcessing(false)
|
|
656
|
+
})
|
|
642
657
|
}, [])
|
|
643
658
|
|
|
644
|
-
return
|
|
659
|
+
if (error) return <div>Auth error: {error}</div>
|
|
660
|
+
if (processing) return <div>Confirming your account...</div>
|
|
661
|
+
return <>{children}</>
|
|
645
662
|
}
|
|
646
663
|
```
|
|
647
664
|
|
|
648
|
-
|
|
665
|
+
Wrap your page content with this component in your **root layout** so it runs on every page:
|
|
666
|
+
|
|
667
|
+
```tsx
|
|
668
|
+
// Root layout
|
|
669
|
+
<CallbackHandler>
|
|
670
|
+
<Outlet /> {/* or {children} in Next.js */}
|
|
671
|
+
</CallbackHandler>
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
If you only mount it on a `/callback` route, OAuth redirects and email confirmation links that land on other pages will not be processed.
|
|
649
675
|
|
|
650
676
|
## Guides
|
|
651
677
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/identity",
|
|
3
|
-
"version": "0.1.1-alpha.
|
|
3
|
+
"version": "0.1.1-alpha.22",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Add authentication to your Netlify site with a few lines of code",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
},
|
|
64
64
|
"author": "Netlify Inc.",
|
|
65
65
|
"devDependencies": {
|
|
66
|
+
"@types/node": "^25.3.3",
|
|
66
67
|
"eslint": "^9.0.0",
|
|
67
68
|
"husky": "^9.1.7",
|
|
68
69
|
"jsdom": "^28.1.0",
|