如何扩展AdonisJS Ally?求指导添加Tumblr提供者
Hey there! I’ve worked with AdonisJS Ally before, so let’s break down how to add a Tumblr provider to your repository step by step.
Creating a custom Ally provider for Tumblr involves a few key steps—let’s walk through each one clearly:
1. Create the Tumblr Provider Class
First, create a new provider file (e.g., TumblrProvider.ts) in your Ally providers directory. This class extends Ally’s base OAuth2 provider and implements all required methods for auth flow and user data fetching.
Here’s a starter template you can adapt:
import type { AllyUserContract, ApiRequestContract } from '@ioc:Adonis/Addons/Ally' import { Oauth2Provider } from '@ioc:Adonis/Addons/Ally' export class TumblrProvider extends Oauth2Provider<TumblrAccessToken, TumblrUser> { protected accessTokenUrl = 'https://api.tumblr.com/v2/oauth2/token' protected authorizeUrl = 'https://www.tumblr.com/oauth2/authorize' protected userInfoUrl = 'https://api.tumblr.com/v2/user/info' // Tumblr's default required scope for basic user data protected defaultScopes = ['basic'] /** * Generate the redirect URL for Tumblr's OAuth authorization page */ public async redirectUrl(): Promise<string> { return this.getRedirectUrl([ 'response_type=code', `client_id=${this.clientId}`, `redirect_uri=${this.redirectUri}`, `scope=${this.scopes.join(' ')}`, ]) } /** * Exchange the authorization code for an access token */ public async getAccessToken(code: string): Promise<TumblrAccessToken> { const response = await this.httpClient.post(this.accessTokenUrl, { grant_type: 'authorization_code', client_id: this.clientId, client_secret: this.clientSecret, redirect_uri: this.redirectUri, code, }) return response.body() } /** * Fetch the authenticated user's profile data from Tumblr's API */ public async getUser(token: TumblrAccessToken): Promise<TumblrUser> { const response = await this.httpClient.get(this.userInfoUrl, { headers: { Authorization: `Bearer ${token.access_token}`, }, }) const userData = response.body().response.user return { id: userData.name, name: userData.name, nickName: userData.name, email: userData.email || null, // Tumblr doesn't always return an email avatarUrl: userData.avatar_url || null, emailVerificationState: 'unsupported' as const, original: userData, } } /** * Create an authenticated API request instance for Tumblr */ public getAuthenticatedRequest(token: TumblrAccessToken): ApiRequestContract { const request = this.httpClient request.header('Authorization', `Bearer ${token.access_token}`) return request } } // Type definitions for Tumblr's access token and user data export type TumblrAccessToken = { access_token: string token_type: string expires_in: number } export type TumblrUser = AllyUserContract<{ name: string avatar_url?: string }>
2. Register the Provider in Ally Config
Open your config/ally.ts file and add Tumblr to the list of providers. Make sure to point to your new provider class:
import { TumblrProvider } from 'Providers/Ally/TumblrProvider' // Adjust the path to match your project structure export default allyConfig({ // ... keep your existing providers here tumblr: { driver: 'custom', implementation: TumblrProvider, clientId: Env.get('TUMBLR_CLIENT_ID'), clientSecret: Env.get('TUMBLR_CLIENT_SECRET'), callbackUrl: Env.get('TUMBLR_CALLBACK_URL'), }, })
3. Set Up Tumblr OAuth Credentials
- Head over to Tumblr’s developer dashboard to create a new application
- Configure your app’s callback URL to match the value in your
.envfile - Add these credentials to your
.envfile:TUMBLR_CLIENT_ID=your_tumblr_client_id TUMBLR_CLIENT_SECRET=your_tumblr_client_secret TUMBLR_CALLBACK_URL=http://localhost:3333/tumblr/callback
4. Test the Provider
You can now use the Tumblr provider in your controllers just like any other Ally provider:
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' export default class AuthController { public async redirectToTumblr({ ally }: HttpContextContract) { return ally.use('tumblr').redirect() } public async handleTumblrCallback({ ally, response }: HttpContextContract) { const tumblrUser = await ally.use('tumblr').user() // Add your logic here (e.g., create a user session, save to database) return response.redirect('/dashboard') } }
Common Pitfalls to Watch For
- Scopes: Tumblr’s OAuth scopes are limited—stick to
basicfor core user data unless you need specific additional permissions - Email Availability: Tumblr doesn’t guarantee access to a user’s email, so make sure your code handles cases where
emailisnull - Rate Limits: Tumblr’s API has rate limits, so add error handling for 429 responses if you’re making frequent requests
If you hit specific issues (like OAuth flow errors or unexpected API responses), share the error messages or problematic code snippets, and I’ll help you troubleshoot further!
内容的提问来源于stack exchange,提问作者pirmax

