@seneris/nextauth-moopy-provider
v1.0.0
Published
Moopy OAuth provider for NextAuth.js
Maintainers
Readme
@seneris/nextauth-moopy-provider
Moopy OAuth provider for NextAuth.js.
Features
- 🔐 OAuth 2.0 authentication with Moopy
- 🔒 PKCE support for enhanced security
- 📦 TypeScript support with full type definitions
- 🎨 Custom Moopy branding
- 🔧 Support for Moopy-specific profile fields (subscription tier, authorized apps, preferences)
- ✅ Type augmentation for Next-Auth session and JWT
Installation
npm install @seneris/nextauth-moopy-provider next-auth
# or
yarn add @seneris/nextauth-moopy-provider next-auth
# or
pnpm add @seneris/nextauth-moopy-provider next-authPrerequisites
- Register your application in the Moopy OAuth system
- Obtain your Client ID and Client Secret
- Configure redirect URIs:
- Development:
http://localhost:3000/api/auth/callback/moopy - Production:
https://yourdomain.com/api/auth/callback/moopy
- Development:
Usage
Basic Setup
import NextAuth, { NextAuthOptions } from "next-auth"
import { PrismaAdapter } from "@next-auth/prisma-adapter"
import MoopyProvider from "@seneris/nextauth-moopy-provider"
import { prisma } from "@/lib/prisma"
export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(prisma),
providers: [
MoopyProvider({
clientId: process.env.MOOPY_CLIENT_ID!,
clientSecret: process.env.MOOPY_CLIENT_SECRET!,
issuer: process.env.MOOPY_ISSUER_URL || 'https://moopy.nl',
}),
],
session: {
strategy: "jwt"
},
callbacks: {
async session({ session, token }) {
if (token && session.user) {
session.user.id = token.sub as string
// Moopy-specific fields are automatically included
session.user.subscription_tier = token.subscription_tier
session.user.subscription_status = token.subscription_status
}
return session
},
async jwt({ token, user, account }) {
if (user && account?.provider === 'moopy') {
token.subscription_tier = user.subscription_tier
token.subscription_status = user.subscription_status
token.authorized_apps = user.authorized_apps
token.preferences = user.preferences
}
return token
},
}
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }Environment Variables
Add to your .env file:
MOOPY_CLIENT_ID=your-client-id-here
MOOPY_CLIENT_SECRET=your-client-secret-here
MOOPY_ISSUER_URL=https://moopy.nl
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=generate-with-openssl-rand-base64-32Custom Configuration
You can customize the OAuth scopes and other settings:
import { createMoopyProvider } from "@seneris/nextauth-moopy-provider"
const provider = createMoopyProvider({
clientId: process.env.MOOPY_CLIENT_ID!,
clientSecret: process.env.MOOPY_CLIENT_SECRET!,
issuer: 'https://moopy.nl',
scope: 'email profile custom-scope'
})Moopy Profile Fields
The provider includes these Moopy-specific profile fields:
interface MoopyProfile {
sub: string // User ID
email?: string // Email address
email_verified?: boolean // Email verification status
name?: string // Full name
given_name?: string // First name
family_name?: string // Last name
picture?: string // Profile picture URL
updated_at?: number // Last update timestamp
subscription_tier?: string // Subscription level (free, pro, enterprise)
subscription_status?: string // Status (active, cancelled, expired)
authorized_apps?: Array<{ // Other apps user has authorized
client_id: string
name: string
}>
preferences?: Record<string, unknown> // User preferences
}TypeScript
The package includes full TypeScript support and automatically augments Next-Auth types to include Moopy-specific fields.
Accessing Moopy Fields
In your components:
import { useSession } from "next-auth/react"
export function MyComponent() {
const { data: session } = useSession()
// TypeScript knows about Moopy fields
const tier = session?.user?.subscription_tier
const status = session?.user?.subscription_status
return (
<div>
<p>Subscription: {tier}</p>
<p>Status: {status}</p>
</div>
)
}In API routes:
import { getServerSession } from "next-auth"
import { authOptions } from "@/lib/auth"
export async function GET() {
const session = await getServerSession(authOptions)
if (!session) {
return new Response("Unauthorized", { status: 401 })
}
// Access Moopy fields
const tier = session.user.subscription_tier
return Response.json({ tier })
}Security
- Uses PKCE (Proof Key for Code Exchange) for enhanced security
- Supports state and nonce checks
- Follows OAuth 2.0 best practices
- Always use HTTPS in production
Examples
Sign In Button
"use client"
import { signIn } from "next-auth/react"
import { Button } from "@/components/ui/button"
export function SignInButton() {
return (
<Button onClick={() => signIn("moopy")}>
Sign in with Moopy
</Button>
)
}Protected API Route
import { NextRequest, NextResponse } from "next/server"
import { getServerSession } from "next-auth"
import { authOptions } from "@/lib/auth"
export async function GET(request: NextRequest) {
const session = await getServerSession(authOptions)
if (!session?.user?.id) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 })
}
return NextResponse.json({
userId: session.user.id,
tier: session.user.subscription_tier
})
}Troubleshooting
Redirect URI Mismatch
Ensure your redirect URI in the Moopy OAuth app exactly matches:
http://localhost:3000/api/auth/callback/moopySession Not Persisting
- Verify
NEXTAUTH_SECRETis set - Check
NEXTAUTH_URLmatches your domain - Ensure cookies are enabled in browser
Custom Fields Not Available
Make sure you include the callbacks in your auth configuration to pass Moopy fields from the JWT to the session (see Usage example above).
License
MIT
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
Support
For issues related to:
- This provider: GitHub Issues
- NextAuth.js: NextAuth.js Documentation
- Moopy OAuth: Contact Moopy support
