Skip to content
Back to skills

629 Oauth Providers 5201dc27

ASecurity

Better Auth provides built-in OAuth 2.0 support for social authentication. No plugins required.

  • 9 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added October 11, 2026
developmentrustgobashreactazuregitapidatabasefrontendbackend

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 629-oauth-providers_5201dc27 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 629 Oauth Providers 5201dc27?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 629 Oauth Providers 5201dc27
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-629-oauth-providers-5201dc27/badge)](https://www.skillsdirectory.com/skills/tools-only-629-oauth-providers-5201dc27)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# OAuth Providers

Better Auth provides built-in OAuth 2.0 support for social authentication. No plugins required.

## Supported Providers

GitHub, Google, Apple, Discord, Facebook, Microsoft, Twitter/X, Spotify, Twitch, LinkedIn, Dropbox, GitLab, and more.

## Basic OAuth Setup

### Server Configuration

```ts
import { betterAuth } from "better-auth";

export const auth = betterAuth({
  socialProviders: {
    github: {
      clientId: process.env.GITHUB_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!,
      // Optional: custom scopes
      scope: ["user:email", "read:user"]
    },
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
      scope: ["openid", "email", "profile"]
    },
    discord: {
      clientId: process.env.DISCORD_CLIENT_ID!,
      clientSecret: process.env.DISCORD_CLIENT_SECRET!,
    }
  }
});
```

### Client Usage

```ts
import { authClient } from "@/lib/auth-client";

// Basic sign in
await authClient.signIn.social({
  provider: "github",
  callbackURL: "/dashboard"
});

// With callbacks
await authClient.signIn.social({
  provider: "google",
  callbackURL: "/dashboard",
  errorCallbackURL: "/error",
  newUserCallbackURL: "/welcome", // For first-time users
});
```

## Provider Configuration

### GitHub OAuth

1. Create OAuth App at https://github.com/settings/developers
2. Set Authorization callback URL: `http://localhost:3000/api/auth/callback/github`
3. Add credentials to `.env`:

```env
GITHUB_CLIENT_ID=your_client_id
GITHUB_CLIENT_SECRET=your_client_secret
```

### Google OAuth

1. Create project at https://console.cloud.google.com
2. Enable Google+ API
3. Create OAuth 2.0 credentials
4. Add authorized redirect URI: `http://localhost:3000/api/auth/callback/google`
5. Add credentials to `.env`:

```env
GOOGLE_CLIENT_ID=your_client_id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your_client_secret
```

### Discord OAuth

1. Create application at https://discord.com/developers/applications
2. Add OAuth2 redirect: `http://localhost:3000/api/auth/callback/discord`
3. Add credentials:

```env
DISCORD_CLIENT_ID=your_client_id
DISCORD_CLIENT_SECRET=your_client_secret
```

### Apple Sign In

```ts
export const auth = betterAuth({
  socialProviders: {
    apple: {
      clientId: process.env.APPLE_CLIENT_ID!,
      clientSecret: process.env.APPLE_CLIENT_SECRET!,
      teamId: process.env.APPLE_TEAM_ID!,
      keyId: process.env.APPLE_KEY_ID!,
      privateKey: process.env.APPLE_PRIVATE_KEY!
    }
  }
});
```

### Microsoft/Azure AD

```ts
export const auth = betterAuth({
  socialProviders: {
    microsoft: {
      clientId: process.env.MICROSOFT_CLIENT_ID!,
      clientSecret: process.env.MICROSOFT_CLIENT_SECRET!,
      tenantId: process.env.MICROSOFT_TENANT_ID, // Optional: for specific tenant
    }
  }
});
```

### Twitter/X OAuth

```ts
export const auth = betterAuth({
  socialProviders: {
    twitter: {
      clientId: process.env.TWITTER_CLIENT_ID!,
      clientSecret: process.env.TWITTER_CLIENT_SECRET!,
    }
  }
});
```

## Custom OAuth Provider

Add custom OAuth 2.0 provider:

```ts
import { betterAuth } from "better-auth";

export const auth = betterAuth({
  socialProviders: {
    customProvider: {
      clientId: process.env.CUSTOM_CLIENT_ID!,
      clientSecret: process.env.CUSTOM_CLIENT_SECRET!,
      authorizationUrl: "https://provider.com/oauth/authorize",
      tokenUrl: "https://provider.com/oauth/token",
      userInfoUrl: "https://provider.com/oauth/userinfo",
      scope: ["email", "profile"],
      // Map provider user data to Better Auth user
      mapProfile: (profile) => ({
        id: profile.id,
        email: profile.email,
        name: profile.name,
        image: profile.avatar_url
      })
    }
  }
});
```

## Account Linking

Link multiple OAuth providers to same user account.

### Server Setup

```ts
export const auth = betterAuth({
  account: {
    accountLinking: {
      enabled: true,
      trustedProviders: ["google", "github"] // Auto-link these providers
    }
  }
});
```

### Client Usage

```ts
// Link new provider to existing account
await authClient.linkSocial({
  provider: "google",
  callbackURL: "/profile"
});

// List linked accounts
const { data: session } = await authClient.getSession();
const accounts = session.user.accounts;

// Unlink account
await authClient.unlinkAccount({
  accountId: "account-id"
});
```

## Token Management

### Access OAuth Tokens

```ts
// Server-side
const session = await auth.api.getSession({
  headers: request.headers
});

const accounts = await auth.api.listAccounts({
  userId: session.user.id
});

// Get specific provider token
const githubAccount = accounts.find(a => a.providerId === "github");
const accessToken = githubAccount.accessToken;
const refreshToken = githubAccount.refreshToken;
```

### Refresh Tokens

```ts
// Manually refresh OAuth token
const newToken = await auth.api.refreshToken({
  accountId: "account-id"
});
```

### Use Provider API

```ts
// Example: Use GitHub token to fetch repos
const githubAccount = accounts.find(a => a.providerId === "github");

const response = await fetch("https://api.github.com/user/repos", {
  headers: {
    Authorization: `Bearer ${githubAccount.accessToken}`
  }
});

const repos = await response.json();
```

## Advanced OAuth Configuration

### Custom Scopes

```ts
export const auth = betterAuth({
  socialProviders: {
    github: {
      clientId: process.env.GITHUB_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!,
      scope: [
        "user:email",
        "read:user",
        "repo", // Access repositories
        "gist" // Access gists
      ]
    }
  }
});
```

### State Parameter

Better Auth automatically handles OAuth state parameter for CSRF protection.

```ts
// Custom state validation
export const auth = betterAuth({
  advanced: {
    generateState: async () => {
      // Custom state generation
      return crypto.randomUUID();
    },
    validateState: async (state: string) => {
      // Custom state validation
      return true;
    }
  }
});
```

### PKCE Support

Better Auth automatically uses PKCE (Proof Key for Code Exchange) for supported providers.

```ts
export const auth = betterAuth({
  socialProviders: {
    customProvider: {
      pkce: true, // Enable PKCE
      // ... other config
    }
  }
});
```

## Error Handling

### Client-Side

```ts
await authClient.signIn.social({
  provider: "github",
  errorCallbackURL: "/auth/error"
}, {
  onError: (ctx) => {
    console.error("OAuth error:", ctx.error);
    // Handle specific errors
    if (ctx.error.code === "OAUTH_ACCOUNT_ALREADY_LINKED") {
      alert("This account is already linked to another user");
    }
  }
});
```

### Server-Side

```ts
export const auth = betterAuth({
  callbacks: {
    async onOAuthError({ error, provider }) {
      console.error(`OAuth error with ${provider}:`, error);
      // Log to monitoring service
      await logError(error);
    }
  }
});
```

## Callback URLs

### Development

```
http://localhost:3000/api/auth/callback/{provider}
```

### Production

```
https://yourdomain.com/api/auth/callback/{provider}
```

**Important:** Add all callback URLs to OAuth provider settings.

## UI Components

### Sign In Button (React)

```tsx
import { authClient } from "@/lib/auth-client";

export function SocialSignIn() {
  const handleOAuth = async (provider: string) => {
    await authClient.signIn.social({
      provider,
      callbackURL: "/dashboard"
    });
  };

  return (
    <div className="space-y-2">
      <button onClick={() => handleOAuth("github")}>
        Sign in with GitHub
      </button>
      <button onClick={() => handleOAuth("google")}>
        Sign in with Google
      </button>
      <button onClick={() => handleOAuth("discord")}>
        Sign in with Discord
      </button>
    </div>
  );
}
```

## Best Practices

1. **Callback URLs**: Add all environments (dev, staging, prod) to OAuth app
2. **Scopes**: Request minimum scopes needed
3. **Token Storage**: Better Auth stores tokens securely in database
4. **Token Refresh**: Implement automatic token refresh for long-lived sessions
5. **Account Linking**: Enable for better UX when user signs in with different providers
6. **Error Handling**: Provide clear error messages for OAuth failures
7. **Provider Icons**: Use official brand assets for OAuth buttons
8. **Mobile Deep Links**: Configure deep links for mobile OAuth flows
9. **Email Matching**: Consider auto-linking accounts with same email
10. **Privacy**: Inform users what data you access from OAuth providers

## Common Issues

### Redirect URI Mismatch

Ensure callback URL in OAuth app matches exactly:
```
http://localhost:3000/api/auth/callback/github
```

### Missing Scopes

Add required scopes for email access:
```ts
scope: ["user:email"] // GitHub
scope: ["email"] // Google
```

### HTTPS Required

Some providers (Apple, Microsoft) require HTTPS callbacks. Use ngrok for local development:
```bash
ngrok http 3000
```

### CORS Errors

Configure CORS if frontend/backend on different domains:
```ts
export const auth = betterAuth({
  advanced: {
    corsOptions: {
      origin: ["https://yourdomain.com"],
      credentials: true
    }
  }
});
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.