Providers

GitHub Provider

Prebuilt GitHub OAuth provider — Authorization Code flow with client secret.

GitHubOAuth2Provider is a prebuilt OAuth2Provider subclass for GitHub OAuth Apps. GitHub does not support PKCE, so a clientSecret is required. For production mobile apps where embedding a secret is a concern, use ProxyOAuthProvider instead.

Package: authyra_flutter


Constructor

GitHubOAuth2Provider({
  required String clientId,
  required String clientSecret,
  String redirectUri = 'authyra://callback',
  List<String> scopes = const ['user', 'user:email'],
})
ParameterDefaultDescription
clientIdrequiredOAuth App client ID from GitHub Developer Settings
clientSecretrequiredOAuth App client secret — GitHub requires this because PKCE is not supported
redirectUri'authyra://callback'Must exactly match the Authorization callback URL in GitHub settings
scopes['user', 'user:email']GitHub OAuth scopes to request

The provider ID is 'github'.

Embedding a client secret in a Flutter app exposes it to extraction from the binary. For production mobile apps, route the OAuth exchange through your backend using ProxyOAuthProvider.

Setup

1. Create a GitHub OAuth App

Go to GitHub Developer Settings → OAuth AppsNew OAuth App:

  • Application name: your app name
  • Homepage URL: your website
  • Authorization callback URL: authyra://callback (or your custom scheme)

Note the Client ID and Client secret.

2. Add the provider

lib/main.dart
import 'package:app_links/app_links.dart';
import 'package:authyra_flutter/authyra_flutter.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final githubProvider = GitHubOAuth2Provider(
    clientId:     'YOUR_GITHUB_CLIENT_ID',
    clientSecret: 'YOUR_GITHUB_CLIENT_SECRET',
    redirectUri:  'authyra://callback',
  );

  // Register before Authyra.initialize
  OAuth2CallbackHandler.registerProvider('authyra', githubProvider);
  AppLinks().uriLinkStream.listen(OAuth2CallbackHandler.handleCallback);

  await Authyra.initialize(
    client: AuthyraClient(
      providers: [githubProvider],
      storage: SecureAuthStorage(),
    ),
  );

  runApp(const MyApp());
}

Androidandroid/app/src/main/AndroidManifest.xml:

<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="authyra" />
</intent-filter>

iOSios/Runner/Info.plist:

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>authyra</string>
    </array>
  </dict>
</array>

Sign in

try {
  final user = await Authyra.instance.signIn('github');
  print('Signed in as ${user.name}');
} on AuthenticationCancelledException {
  // User closed the browser
} on AuthenticationFailedException catch (e) {
  print('GitHub sign-in failed: $e');
}

User fields

AuthUser fieldGitHub fieldNotes
idid (int → String)Stable numeric user ID converted to String
emailemailMay be null if the user's email is private
namename or loginFalls back to username if display name is unset
avatarUrlavatar_url
metadata['login']loginGitHub username
metadata['bio']bio
metadata['company']company
metadata['location']location
metadata['blog']blog
metadata['twitter_username']twitter_username
metadata['public_repos']public_repos
metadata['followers']followers
metadata['following']following

Scopes

Default scopes: ['user', 'user:email']. Add repository or organization access as needed:

GitHubOAuth2Provider(
  clientId:     'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET',
  scopes: ['user', 'user:email', 'repo', 'read:org'],
)

See the full list at GitHub OAuth scopes.


Token refresh

GitHub access tokens are long-lived and do not expire by default. GitHubOAuth2Provider sets supportsRefresh: false.

If you enable expiring tokens in your GitHub App settings, implement a custom AuthProvider that calls GitHub's token refresh endpoint and returns an AuthTokenResult.


Private email

If a user's email is set to private on GitHub, the /user API returns null for email. To reliably get the user's primary email, add the user:email scope (included in defaults) and call the /user/emails endpoint separately.


Troubleshooting

"redirect_uri_mismatch" from GitHub

The redirectUri in GitHubOAuth2Provider must match exactly what is set in GitHub Developer Settings → Authorization callback URL.

email is null after sign-in

The user has set their email to private. Add user:email to scopes (it is included by default) but also call GitHub's /user/emails API to get the verified primary email.

Callback never arrives on iOS

Verify the CFBundleURLSchemes entry in Info.plist matches the scheme in your redirectUri (the part before ://).


See also

Copyright © 2026