๐ Solving Vimeo API Authentication: Building a Secure Video Gallery with OAuth 2.0

Table of contents
- ๐๏ธ Project Architecture
- Key Components
- ๐ The OAuth 2.0 Solution
- The Complete OAuth Flow
- My Solution: SimpleVimeoTest Component
- Features of the Token Generator
- ๐ง API Implementation
- ๐จ Video Gallery Implementation
- ๐จ Solving Common Authentication Issues
- ๐ Security Features
- ๐ฑ User Experience Features
- ๐ Deployment and Production
- ๐ Results and Impact
- ๐ฎ Future Enhancements
- ๐ Lessons Learned
- ๐ฏ Conclusion
- ๐ Resources and Links

๐จ The Problem: Vimeo API Authentication Nightmare
The Error That Started It All
Vimeo API Error: Can't upload video - "No user credentials were provided." or "No user credentials were provided" when you try to Retrieve Videos from your account!
When I tried to integrate Vimeo's API into my project, I hit a wall. The official documentation was confusing, and I kept getting authentication errors despite following their guides. The problem? There was no clear solution for OAuth 2.0 implementation in the Vimeo documentation.
What I Discovered
Client Credentials Grant doesn't work for user-specific data
OAuth 2.0 flow was poorly documented
Token generation required manual API calls
Error handling was vague and unhelpful
No working examples for web applications
๐ก The Solution: Built-In OAuth 2.0 with Token Generator
Instead of struggling with unclear documentation, I built a complete solution that includes:
OAuth 2.0 Authentication Flow - Proper implementation
Built-in Token Generator - No more manual API calls
Secure Video Gallery - Display videos without exposing credentials
Comprehensive Error Handling - Clear solutions for common issues.
๐๏ธ Project Architecture
Technology Stack
Frontend: Next.js 14 + React 18 + TypeScript
Styling: Tailwind CSS for responsive design
Authentication: OAuth 2.0 (Authorization Code Grant)
API: Vimeo REST API v3.4
HTTP Client: Axios for API requests.
Key Components
src/
โโโ app/
โ โโโ api/vimeo/
โ โ โโโ videos/ # Fetch user videos
โ โ โโโ token/ # OAuth token exchange
โ โโโ components/
โ โ โโโ VimeoGallery.tsx # Video display
โ โ โโโ SimpleVimeoTest.tsx # Token generator
โ โโโ lib/
โ โ โโโ vimeo.ts # Vimeo API service
โ โโโ types/
โ โโโ vimeo.ts # TypeScript definitions
๐ The OAuth 2.0 Solution
Why OAuth 2.0 Instead of API Keys?
โ API Keys (Client Credentials)
Only work for app-level data
Can't access user-specific content
Limited scope and permissions
Security risks if exposed
โ OAuth 2.0 (Authorization Code Grant)
User-specific access tokens
Secure, industry-standard protocol
Users can revoke access anytime
Proper scope control
The Complete OAuth Flow
Step 1: App Registration
Create Vimeo app with "User Authentication" type
Set redirect URI:
http://localhost:3000/api/auth/vimeo/callback
Configure scopes:
public
,private
(avoidvideo_files
for free accounts).
Step 2: Authorization Request
const authUrl = `https://api.vimeo.com/oauth/authorize
?response_type=code
&client_id=${CLIENT_ID}
&redirect_uri=${REDIRECT_URI}
&scope=public private`;
Step 3: Token Exchange
// Exchange authorization code for access token
const response = await fetch('https://api.vimeo.com/oauth/access_token', {
method: 'POST',
headers: {
'Authorization': `Basic ${btoa(CLIENT_ID + ':' + CLIENT_SECRET)}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
grant_type: 'authorization_code',
code: authorizationCode,
redirect_uri: REDIRECT_URI
})
});
๐ ๏ธ Built-in Token Generator: The Game Changer
The Problem with Manual Token Generation
Complex API calls required
Authorization codes expire in 5-10 minutes
No visual feedback during the process
Error handling was difficult.
My Solution: SimpleVimeoTest Component
I built a user-friendly interface that handles the entire OAuth flow:
export default function SimpleVimeoTest() {
const [authCode, setAuthCode] = useState('');
const [accessToken, setAccessToken] = useState('');
const [userInfo, setUserInfo] = useState<any>(null);
const handleGetToken = async () => {
// Exchange authorization code for access token
const response = await fetch('/api/vimeo/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code: authCode.trim() })
});
const data = await response.json();
if (data.success) {
setAccessToken(data.access_token);
setUserInfo(data.user);
}
};
// ... rest of component with UI
}
Features of the Token Generator
Step-by-step guidance for OAuth flow
Authorization code input with validation
Automatic token exchange via API
Connection testing to verify tokens work
User info display for verification
Clear error messages and solutions.
๐ง API Implementation
Token Exchange Endpoint
// /api/vimeo/token/route.ts
export async function POST(request: NextRequest) {
try {
const { code } = await request.json();
const tokenResponse = await fetch('https://api.vimeo.com/oauth/access_token', {
method: 'POST',
headers: {
'Authorization': `Basic ${Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64')}`,
'Content-Type': 'application/json',
'Accept': 'application/vnd.vimeo.*+json;version=3.4'
},
body: JSON.stringify({
grant_type: 'authorization_code',
code: code,
redirect_uri: REDIRECT_URI
})
});
const tokenData = await tokenResponse.json();
return NextResponse.json({
success: true,
access_token: tokenData.access_token,
user: tokenData.user
});
} catch (error) {
return NextResponse.json({ error: 'Token exchange failed' }, { status: 500 });
}
}
Video Fetching Service
// /lib/vimeo.ts
export default class VimeoService {
private accessToken: string;
constructor(accessToken?: string) {
this.accessToken = accessToken || process.env.VIMEO_ACCESS_TOKEN || '';
}
async getUserVideos(page = 1, per_page = 25) {
const response = await axios.get('https://api.vimeo.com/me/videos', {
headers: this.getHeaders(),
params: { page, per_page }
});
return response.data;
}
private getHeaders() {
return {
'Authorization': `Bearer ${this.accessToken}`,
'Accept': 'application/vnd.vimeo.*+json;version=3.4'
};
}
}
๐จ Video Gallery Implementation
Responsive Grid Layout
export default function VimeoGallery() {
const [videos, setVideos] = useState<VimeoVideo[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchVideos();
}, []);
const fetchVideos = async () => {
const response = await fetch('/api/vimeo/videos');
const data = await response.json();
if (data.success) {
setVideos(data.videos || []);
}
};
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{videos.map((video) => (
<VideoCard key={video.uri} video={video} />
))}
</div>
);
}
Video Player Modal
const VideoModal = ({ video, onClose }) => (
<div className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center">
<div className="bg-white rounded-lg max-w-4xl w-full">
<iframe
src={`https://player.vimeo.com/video/${video.uri.split('/').pop()}`}
width="100%"
height="400"
allow="autoplay; fullscreen"
allowFullScreen
/>
{/* Video details and metadata */}
</div>
</div>
);
๐จ Solving Common Authentication Issues
Issue 1: "Invalid authorization code"
Problem: Authorization codes expire quickly and can only be used once Solution: Get fresh codes and use immediately via the built-in token generator
Issue 2: "App didn't receive user credentials"
Problem: Using wrong authentication method Solution: Ensure app type is "User Authentication" and use OAuth flow
Issue 3: "Video files scope requires paid plan"
Problem: Requesting premium scopes on free accounts Solution: Use only public
and private
scopes
Issue 4: "401 Unauthorized"
Problem: Expired or invalid access tokens Solution: Generate new OAuth tokens using the token generator
๐ Security Features
OAuth 2.0 Security
State parameter prevents CSRF attacks
HTTPS required for production
Scope limitation requests minimal permissions
Token expiration handled gracefully
Development Security
Environment variables for sensitive data
Never commit tokens to version control
Separate tokens for different environments
Access control limits token exposure
๐ฑ User Experience Features
Built-in Token Generator
Visual workflow with color-coded sections
Real-time feedback during token generation
Error handling with clear solutions
Connection testing before committing tokens
Video Gallery
Responsive design works on all devices
Modal player for seamless video viewing
Video metadata display (duration, date, plays)
Loading states and error handling
๐ Deployment and Production
Environment Configuration
# Development
VIMEO_CLIENT_ID=your_dev_client_id
VIMEO_CLIENT_SECRET=your_dev_client_secret
VIMEO_REDIRECT_URI=http://localhost:3000/api/auth/vimeo/callback
VIMEO_ACCESS_TOKEN=your_dev_token
# Production
VIMEO_CLIENT_ID=your_prod_client_id
VIMEO_CLIENT_SECRET=your_prod_client_secret
VIMEO_REDIRECT_URI=https://yourdomain.com/api/auth/vimeo/callback
VIMEO_ACCESS_TOKEN=your_prod_token
Production Considerations
HTTPS required for OAuth 2.0
Environment variables in hosting platform
Token monitoring for expiration
Error tracking for debugging
๐ Results and Impact
What This Project Achieved
Solved the authentication problem that wasn't documented
Created a user-friendly OAuth flow with visual guidance
Built a secure video gallery without exposing credentials
Provided comprehensive documentation for future developers
Technical Benefits
Secure authentication using industry standards
Built-in token management eliminates manual work
Responsive design works on all devices
Error handling provides clear solutions
Developer Experience
No more authentication headaches with Vimeo API
Clear documentation for OAuth implementation
Working examples for common use cases
Reusable components for other projects
๐ฎ Future Enhancements
Planned Features
Search and filtering for videos
Advanced pagination with infinite scroll
Custom video player with analytics
Video categories and organization
User management for multiple accounts
Potential Applications
Portfolio websites for video creators
Educational platforms with video content
Corporate video libraries for internal use
E-commerce with product videos
Social platforms with video sharing
๐ Lessons Learned
OAuth 2.0 Implementation
Authorization Code Grant is the right choice for web apps
State parameters are essential for security
Token expiration must be handled gracefully
Scope limitation improves security
API Integration
Clear error messages are crucial for debugging
Built-in tools improve developer experience
Comprehensive documentation saves time
Working examples are invaluable
Project Development
Solve real problems that others face
Build tools that make development easier
Document everything for future reference
Focus on user experience from the start
๐ฏ Conclusion
This project started as a solution to a frustrating Vimeo API authentication problem and evolved into a comprehensive video gallery application. By implementing OAuth 2.0 properly and building a user-friendly token generator, I created a solution that:
Solves the authentication problem that wasn't clearly documented
Provides a secure way to display Vimeo videos
Offers a better developer experience with built-in tools
Demonstrates best practices for OAuth 2.0 implementation
The key insight was that instead of struggling with unclear documentation, I could build a complete solution that handles the entire OAuth flow seamlessly. The built-in token generator eliminates the need for manual API calls and provides clear guidance for users.
This approach not only solved my immediate problem but also created a reusable solution that others can benefit from. The project demonstrates that sometimes the best solution is to build the tools you need rather than waiting for better documentation.
๐ Resources and Links
Project Repository: Vimeo API Code
Vimeo API Documentation: https://developer.vimeo.com/api
OAuth 2.0 Specification: RFC 6749
This project demonstrates that with the right approach, even complex authentication problems can be solved elegantly. By building tools that make OAuth 2.0 accessible and user-friendly, we can create better developer experiences and more secure applications.
Subscribe to my newsletter
Read articles from saqib directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

saqib
saqib
As a Web3 Software Engineer and the founder of Orbimatrix, I empowers businesses to thrive in the decentralized future. He's an expert in crafting innovative blockchain and AI solutions that don't just innovate, but deliver tangible value: think streamlined operations and boosted ROI. Discover how Web3 and AI can revolutionize your business. Orbimatrix provides strategic guidance, custom software development, and complete solution integration, all designed to meet your unique needs and ensure your success.