@ley0x/better-auth-lastfm
Version:
Last.fm authentication plugin for BetterAuth
247 lines (184 loc) • 5.89 kB
Markdown
# BetterAuth Last.fm Plugin
A clean, modern Last.fm authentication plugin for [BetterAuth](https://better-auth.com).
## Features
- 🔐 Complete Last.fm authentication flow implementation
- 🎵 Session key storage for Last.fm API calls
- 🌟 TypeScript support with full type safety
- 🛠️ Modern architecture following BetterAuth patterns
- 🚀 Zero additional dependencies (except peer dependencies)
## Installation
```bash
npm install @ley0x/better-auth-lastfm
# or
pnpm add @ley0x/better-auth-lastfm
# or
yarn add @ley0x/better-auth-lastfm
```
## Setup
### 1. Get Last.fm API Credentials
1. Visit [Last.fm API Account Creation](https://www.last.fm/api/account/create)
2. Create an application to get your API Key and Shared Secret
### 2. Server Configuration
```typescript
import { betterAuth } from 'better-auth'
import { lastfmPlugin } from '@ley0x/better-auth-lastfm'
export const auth = betterAuth({
// ... your other config
plugins: [
lastfmPlugin({
apiKey: process.env.LASTFM_API_KEY!,
sharedSecret: process.env.LASTFM_SHARED_SECRET!,
// Optional: customize redirect URL after successful auth
redirectTo: '/dashboard', // default: '/dashboard'
// Optional: set base URL (usually auto-detected)
baseUrl: process.env.BETTER_AUTH_URL,
}),
],
// Optional: customize session expiration (default: 7 days)
session: {
expiresIn: 60 * 60 * 24 * 30, // 30 days
updateAge: 60 * 60 * 24, // Update session every day
},
})
```
### 3. Client Configuration
```typescript
import { createAuthClient } from 'better-auth/react'
import { lastfmClientPlugin } from '@ley0x/better-auth-lastfm/client'
export const authClient = createAuthClient({
plugins: [lastfmClientPlugin()],
})
export const { useSession, signOut, signIn, signUp } = authClient
```
## Usage
### Basic Sign-In
```typescript
import { authClient } from './auth-client'
// Redirect to Last.fm authentication
await authClient.signInWithLastfm()
```
### React Component Example
```typescript
import { authClient } from './auth-client'
function LoginButton() {
const handleSignIn = async () => {
await authClient.signInWithLastfm()
}
return (
<button onClick={handleSignIn}>
Sign in with Last.fm
</button>
)
}
```
### Getting Last.fm Session Key
After authentication, you can retrieve the Last.fm session key to make API calls:
```typescript
import { authClient } from './auth-client'
// Get the Last.fm session key for API calls
const sessionKey = await authClient.getLastfmSessionKey()
if (sessionKey) {
// Use session key to call Last.fm API
// Example: get user's recent tracks, scrobble, etc.
}
```
### Making Last.fm API Calls
```typescript
import { createLastfmApiSignature } from '@ley0x/better-auth-lastfm'
async function getRecentTracks(username: string, sessionKey: string) {
const params = {
method: 'user.getRecentTracks',
user: username,
api_key: process.env.LASTFM_API_KEY!,
sk: sessionKey,
format: 'json',
}
const signature = createLastfmApiSignature(params, process.env.LASTFM_SHARED_SECRET!)
const url = new URL('https://ws.audioscrobbler.com/2.0/')
Object.entries({ ...params, api_sig: signature }).forEach(([key, value]) => {
url.searchParams.set(key, value)
})
const response = await fetch(url)
return response.json()
}
```
## Environment Variables
Add these to your `.env` file:
```env
LASTFM_API_KEY=your_api_key_here
LASTFM_SHARED_SECRET=your_shared_secret_here
BETTER_AUTH_URL=http://localhost:3000 # Your app's base URL
BETTER_AUTH_SECRET=your_secret_here # BetterAuth secret
```
## Database Schema
The plugin uses BetterAuth's standard user and account tables. Last.fm session keys are stored in the `accessToken` field of the account record.
## Session Configuration
By default, BetterAuth sessions expire after 7 days. You can customize the session expiration by adding a `session` configuration object to your `betterAuth` configuration:
```typescript
export const auth = betterAuth({
plugins: [
lastfmPlugin({
/* ... */
}),
],
session: {
expiresIn: 60 * 60 * 24 * 30, // 30 days (default: 7 days)
updateAge: 60 * 60 * 24, // Update session every day (default: 1 day)
},
})
```
### Important: Session Persistence Fix
**Note**: A recent fix ensures sessions persist across browser restarts. The plugin now properly respects cookie `maxAge` settings. See [SESSION_PERSISTENCE_SOLUTION.md](SESSION_PERSISTENCE_SOLUTION.md) for details.
### Recommended Configuration for Persistence
```typescript
export const auth = betterAuth({
plugins: [
lastfmPlugin({
/* ... */
}),
],
session: {
expiresIn: 60 * 60 * 24 * 30, // 30 days
updateAge: 60 * 60 * 24,
cookieCache: {
enabled: true,
maxAge: 60 * 60 * 24,
strategy: 'compact',
},
},
cookies: {
sessionToken: {
attributes: {
maxAge: 60 * 60 * 24 * 30, // Persistent cookie
},
},
},
})
```
## API Reference
### `lastfmPlugin(options)`
Server-side plugin configuration.
#### Options
- `apiKey` (required): Your Last.fm API key
- `sharedSecret` (required): Your Last.fm shared secret
- `baseUrl` (optional): Your app's base URL for callbacks
- `redirectTo` (optional): Path to redirect after successful auth
### `lastfmClientPlugin()`
Client-side plugin for browser environments.
### Client Methods
- `signInWithLastfm()`: Initiates Last.fm authentication flow
- `getLastfmSessionKey()`: Returns the user's Last.fm session key
## TypeScript Support
Full TypeScript support with exported types:
```typescript
import type {
LastfmPluginOptions,
LastfmSession,
LastfmAuthResponse,
LastfmUserProfile,
} from '@ley0x/better-auth-lastfm'
```
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## License
MIT