# MIXERA OAuth Callback Template

This is a ready-to-use callback page template for developers integrating MIXERA OAuth into their local applications.

## 🎯 What is this?

When users authorize your app through MIXERA OAuth, they need to be redirected back to your application with an authorization code. This template provides a beautiful, professional-looking success page that matches MIXERA's design language.

## 🚀 Quick Start

### 1. Download the Template

Download `callback-template.html` and place it in your project.

### 2. Serve it Locally

The template needs to be served on the redirect URI you registered with MIXERA.

**Example: Using Python**
```bash
# Serve on http://localhost:8080
python -m http.server 8080
```

**Example: Using Node.js**
```bash
# Install http-server globally
npm install -g http-server

# Serve on http://localhost:8080
http-server -p 8080
```

**Example: Using PHP**
```bash
php -S localhost:8080
```

### 3. Register Your Redirect URI

In your MIXERA OAuth client settings, set your redirect URI to:
```
http://localhost:8080/callback-template.html
```

## 💻 Integration Options

The template includes several commented-out integration options. Choose the one that fits your architecture:

### Option 1: Post Message (Popup Flow)

If you open the OAuth flow in a popup window:

```javascript
// Uncomment in callback-template.html
if (window.opener) {
    window.opener.postMessage({
        type: 'oauth_callback',
        code: code,
        state: state
    }, 'http://localhost:YOUR_PORT'); // Replace with your app's origin
}
```

In your main app:
```javascript
window.addEventListener('message', (event) => {
    if (event.data.type === 'oauth_callback') {
        const { code, state } = event.data;
        // Exchange code for tokens
    }
});
```

### Option 2: LocalStorage

Store the code in localStorage for your app to retrieve:

```javascript
// Uncomment in callback-template.html
localStorage.setItem('mixera_oauth_code', code);
localStorage.setItem('mixera_oauth_state', state);
```

Then poll for it in your app:
```javascript
const checkForCode = setInterval(() => {
    const code = localStorage.getItem('mixera_oauth_code');
    if (code) {
        clearInterval(checkForCode);
        localStorage.removeItem('mixera_oauth_code');
        // Exchange code for tokens
    }
}, 1000);
```

### Option 3: Custom URL Scheme (Desktop Apps)

For Electron, Tauri, or native desktop apps:

```javascript
// Uncomment in callback-template.html
window.location.href = `yourapp://oauth/callback?code=${code}&state=${state}`;
```

Register your custom protocol handler in your app.

### Option 4: Local Backend

Send the code directly to your local backend:

```javascript
// Uncomment in callback-template.html
fetch('http://localhost:YOUR_PORT/oauth/callback', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ code, state })
});
```

## 🔐 Complete OAuth Flow Example

Here's a complete example using a local Express.js backend:

**1. Server (server.js)**
```javascript
const express = require('express');
const axios = require('axios');
const app = express();

app.use(express.json());
app.use(express.static('public')); // Serve callback-template.html from public/

let pendingAuth = null;

// Step 1: Start OAuth flow
app.get('/login', (req, res) => {
    const clientId = 'your_client_id';
    const redirectUri = 'http://localhost:8080/callback-template.html';
    const state = Math.random().toString(36).substring(7);
    
    pendingAuth = { state };
    
    const authUrl = `https://mixera.app/oauth/authorize?` +
        `client_id=${clientId}&` +
        `redirect_uri=${encodeURIComponent(redirectUri)}&` +
        `response_type=code&` +
        `scope=profile&` +
        `state=${state}`;
    
    res.redirect(authUrl);
});

// Step 2: Handle callback
app.post('/oauth/callback', async (req, res) => {
    const { code, state } = req.body;
    
    // Verify state
    if (!pendingAuth || pendingAuth.state !== state) {
        return res.status(400).json({ error: 'Invalid state' });
    }
    
    // Exchange code for tokens
    try {
        const tokenResponse = await axios.post('https://mixera.app/api/oauth/token', {
            grant_type: 'authorization_code',
            code: code,
            redirect_uri: 'http://localhost:8080/callback-template.html',
            client_id: 'your_client_id',
            client_secret: 'your_client_secret'
        });
        
        const { access_token, refresh_token } = tokenResponse.data;
        
        // Get user info
        const userResponse = await axios.get('https://mixera.app/api/oauth/userinfo', {
            headers: { 'Authorization': `Bearer ${access_token}` }
        });
        
        // Store tokens securely
        // ... your storage logic ...
        
        res.json({ success: true, user: userResponse.data });
    } catch (error) {
        res.status(500).json({ error: 'Token exchange failed' });
    }
});

app.listen(8080, () => {
    console.log('Server running on http://localhost:8080');
});
```

**2. Update callback-template.html**

Uncomment Option 4 in the template:
```javascript
if (code) {
    fetch('http://localhost:8080/oauth/callback', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ code, state })
    }).then(response => response.json())
      .then(data => {
          if (data.success) {
              // Show success and close window
              setTimeout(() => closeWindow(), 2000);
          }
      });
}
```

## 🎨 Customization

### Change Colors

Edit the CSS variables at the top of the template:
```css
:root {
    --primary: #A259FF;          /* Your brand color */
    --primary-dark: #8B3FE1;     /* Darker shade */
    --success: #26a641;          /* Success color */
    /* ... */
}
```

### Custom Branding

Replace the MIXERA branding at the bottom:
```html
<div class="mixera-branding">
    <div class="your-logo">Your App Name</div>
    <p class="powered-by">Powered by Your Company</p>
</div>
```

### Auto-Close Window

Uncomment the auto-close code at the end of the script:
```javascript
// Auto-close after 3 seconds
setTimeout(() => {
    closeWindow();
}, 3000);
```

## 🐛 Debug Mode

To see the authorization code for debugging, uncomment the developer info section:

```javascript
if (code) {
    document.getElementById('dev-info').style.display = 'block';
    document.getElementById('auth-code').textContent = code;
}
```

**⚠️ Important: Remove this in production!**

## 📝 Security Best Practices

1. **Always validate the `state` parameter** to prevent CSRF attacks
2. **Never expose your client secret** in the frontend
3. **Exchange the authorization code for tokens** on your backend
4. **Use HTTPS in production** (required by MIXERA)
5. **Store tokens securely** (never in localStorage for production apps)
6. **Validate the redirect URI** matches what you registered

## 🌐 Production Deployment

For production apps, you'll need:

1. A registered domain (e.g., `https://yourdomain.com`)
2. HTTPS certificate
3. Update redirect URI to your production URL
4. Update CORS origins if using fetch to your backend

## 📚 Additional Resources

- [MIXERA OAuth Documentation](https://mixera.app/api/OAUTH_DOCUMENTATION.md)
- [OAuth 2.0 RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749)
- [PKCE for Public Clients](https://oauth.net/2/pkce/)

## ⚡ Troubleshooting

### "Authorization Failed" appears

- Check your `client_id` is correct
- Verify your `redirect_uri` exactly matches what's registered
- Ensure the user is logged into MIXERA

### Window won't close automatically

- `window.close()` only works for windows opened by `window.open()`
- For normal browser tabs, users must close manually
- Consider using a popup window for the OAuth flow

### CORS errors

- Ensure your backend has proper CORS headers
- In development, you can use a proxy or disable CORS (not for production!)

## 💬 Support

For issues or questions about MIXERA OAuth:
- Documentation: https://mixera.app/api/OAUTH_DOCUMENTATION.md
- Support: contact@mixera.app

---

**Made with ❤️ for MIXERA developers**

