
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
local-first-auth
Advanced tools
Easily add auth to your web app with this library. This library implements the Local First Auth specification client side, allowing you to skip building email-based auth systems.
This library provides an easy way to add auth to your web app - no servers, no passwords, no third-party auth providers.
Show the Onboarding component to let users pick a name (and optionally an avatar) — behind the scenes, the user gets a public and private key pair that is stored on their device. When your app needs to authenticate a request, call getProfileDetails() to get a signed JWT containing the user's profile. Pass the JWT with any request so your backend can verify the signature, confirm who made the request, and extract the profile data.
This is a great fit for apps where people are physically present together in the same place, such as:
Drawbacks of using this library:
npm install local-first-auth
import { Onboarding } from 'local-first-auth/react'
function App() {
const hasLocalFirstAuth = typeof window !== 'undefined' && window.localFirstAuth
const [showOnboarding, setShowOnboarding] = useState(!hasLocalFirstAuth)
if (showOnboarding) {
return (
<Onboarding
onComplete={(profile) => {
console.log('Profile created:', profile)
setShowOnboarding(false)
}}
customStyles={{ primaryColor: '#403B51' }}
/>
)
}
return <YourApp />
}
import { createOnboarding } from 'local-first-auth'
const onboarding = createOnboarding({
container: '#onboarding-root',
onComplete: (profile) => {
console.log('Profile created:', profile)
// window.localFirstAuth is now available
}
})
<Onboarding
skipSocialStep={true} // Skip social links step
skipAvatarStep={true} // Skip avatar upload step
/>
<Onboarding
customStyles={{
primaryColor: '#403B51',
backgroundColor: '#ffffff',
textColor: '#333333',
borderRadius: '12px',
fontFamily: 'Inter, sans-serif',
inputRadius: '8px',
buttonRadius: '12px'
}}
/>
When a user creates an account:
window.localFirstAuth objectThe generated profile is compatible with the Local First Auth specification. Your backend can verify JWTs the same way it would for a profile from any Local First Auth compatible app.
<Onboarding />Main wrapper component.
interface OnboardingProps {
skipSocialStep?: boolean
skipAvatarStep?: boolean
customStyles?: CustomStyles
onComplete?: (profile: Profile) => void
}
<CreateAccountFlow />The 3-step account creation flow.
interface CreateAccountFlowProps {
skipSocialStep?: boolean
skipAvatarStep?: boolean
onComplete?: (profile: Profile) => void
customStyles?: CustomStyles
}
useOnboarding()Hook for detecting Local First Auth status and determining whether to show onboarding.
import { useOnboarding } from 'local-first-auth/react'
const { shouldShowOnboarding, profile, isLoading } = useOnboarding()
// Returns:
// - shouldShowOnboarding: boolean (true if no API available)
// - profile: Profile | null (user's profile if web account exists)
// - isLoading: boolean (initial loading state)
// Derived values you can compute:
// - hasApi = !shouldShowOnboarding
// - isNativeApp = !shouldShowOnboarding && profile === null
// - hasWebAccount = profile !== null
useProfile()Hook for accessing the current user profile.
import { useProfile } from 'local-first-auth/react'
const profile = useProfile()
// Returns Profile | null
// Profile management
import {
createProfile,
getCurrentProfile,
updateProfile,
hasProfile,
clearProfile
} from 'local-first-auth'
// Device detection
import {
isLocalFirstAuth
} from 'local-first-auth'
// Social validation
import {
validateHandle,
normalizeHandle,
createSocialLink
} from 'local-first-auth'
Profile data is stored in LocalStorage:
{
'local-first-auth:profile': {
did: 'did:key:z6Mk...',
name: 'Alice Anderson',
socials: [{platform: 'INSTAGRAM', handle: 'alice'}],
avatar: 'data:image/jpeg;base64,...'
},
'local-first-auth:privateKey': 'base64-encoded-64-byte-key'
}
After profile creation, window.localFirstAuth is injected with these methods:
interface LocalFirstAuth {
getProfileDetails(): Promise<string> // Returns signed JWT
getAvatar(): Promise<string | null> // Returns signed JWT with avatar
getAppDetails(): AppDetails
requestPermission(permission: string): Promise<boolean>
close(): void
}
All methods are compatible with the Local First Auth Specification. Users can generate an account and your backend can verify JWTs that are generated by this package the same way it would for a profile from any Local First Auth compatible app.
This package includes a comprehensive example app in /example that demonstrates all features. The example app is excluded from the npm package (via "files": ["dist"] in package.json).
Run the example:
npm run dev:example
# Opens http://localhost:5173
What it tests:
useOnboarding() and useProfile() hooks, state detection, native API simulationcustomStyles propBuild example:
cd example
npm install
npm run build
The example app uses Vite for fast development with hot module replacement and demonstrates both React components and vanilla JS core functionality.
Full TypeScript support with comprehensive type definitions:
import type {
Profile,
SocialLink,
SocialPlatform,
LocalFirstAuth,
CustomStyles
} from 'local-first-auth'
This library was inspired by a recent trip to China. ie) One really innovative user experience in China is the idea that you don’t always need to download an app, sometimes the better experience is to just scan a QR code. Here is an example: When I enter a cafe, I don't have to download the cafe's app, I just scan a QR code and it allows me to pay for my coffee and track my loyalty points - no signup or app download required.
This works because of WeChat's prominence in China. When I entered the cafe, I opened up WeChat and scanned the QR code. The cafe has built a WeChat mini app that uses my WeChat Id and WeChat Pay to authenticate me to allow me to pay for my coffee and track my loyalty points.
It's cool and really convenient UX for users, BUT it would be cooler if we could build something like this but use open standards (so we don't need to have a super app like WeChat). This library uses the Local First Auth specification to make it easy to build in simple auth into your web app.
However, Antler is a demo app that showcases how any native mobile app can integrate this spec into their app. When you download Antler, you do the same onboarding process as you would with this library (enter your name and optionally an avatar). It generates a public and private key pair that is stored locally on your device. Whenever you scan a QR code using Antler, your profile details are shared with the web app. This means users don't have to go through account creation for every web app you use, and you don't have to worry about losing your keys if you clear your browsing data.
My dream would be that if other messaging or event apps like Telegram, Signal, Meetup.com, etc. would build this spec into their app. It would give users the same great UX you get with WeChat but use open standards instead of requiring a super app like WeChat.
FAQs
Easily add auth to your web app with this library. This library implements the Local First Auth specification client side, allowing you to skip building email-based auth systems.
The npm package local-first-auth receives a total of 6 weekly downloads. As such, local-first-auth popularity was classified as not popular.
We found that local-first-auth demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.