You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android Firebase UI中实现GitHub登录授权

Great question! Let's break down exactly how to add a GitHub login button to your Android app that integrates with Firebase—you've already checked off the big prerequisites (GitHub app created, Firebase Console configured with Client ID/Secret), so we'll focus on the UI, click handling, and auth flow.

Adding GitHub Login to Your Firebase-Integrated Android App

1. Add the GitHub Login Button to Your XML Layout

First, add a polished GitHub login button to your login screen layout. Use a MaterialButton with GitHub's branding for consistency:

<!-- Inside your login layout file -->
<com.google.android.material.button.MaterialButton
    android:id="@+id/btn_github_login"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Sign in with GitHub"
    android:drawableStart="@drawable/ic_github" <!-- Add GitHub's vector icon here -->
    android:drawablePadding="8dp"
    android:layout_marginHorizontal="16dp"
    android:layout_marginTop="8dp"
    android:backgroundTint="#24292F" <!-- GitHub's dark gray brand color -->
    android:textColor="@android:color/white"/>

You can grab GitHub's official vector icon from Material Icons or GitHub's branding resources if you don't already have it.

2. Handle Button Click & Launch GitHub Authorization Flow

When the user taps the button, we'll redirect them to GitHub's OAuth 2.0 authorization page using Chrome Custom Tabs (for a smoother in-app experience vs. opening a separate browser).

First, add the Custom Tabs dependency to your app-level build.gradle:

implementation("androidx.browser:browser:1.6.0")

Then, set up the button click listener in your LoginActivity/Fragment:

class LoginActivity : AppCompatActivity() {
    private val GITHUB_CLIENT_ID = "your_github_client_id_here"
    private val GITHUB_REDIRECT_URI = "your_app_scheme://github-auth" // Match what you set in GitHub app settings
    private val AUTH_PREFS = "AuthPrefs"
    private val KEY_GITHUB_STATE = "github_state"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        val btnGithubLogin = findViewById<MaterialButton>(R.id.btn_github_login)
        btnGithubLogin.setOnClickListener {
            // Generate a random state string to prevent CSRF attacks
            val authState = UUID.randomUUID().toString()
            // Save the state to validate later
            getSharedPreferences(AUTH_PREFS, MODE_PRIVATE)
                .edit()
                .putString(KEY_GITHUB_STATE, authState)
                .apply()

            // Build GitHub's authorization URL
            val githubAuthUrl = Uri.parse("https://github.com/login/oauth/authorize")
                .buildUpon()
                .appendQueryParameter("client_id", GITHUB_CLIENT_ID)
                .appendQueryParameter("redirect_uri", GITHUB_REDIRECT_URI)
                .appendQueryParameter("scope", "user:email") // Request user email (optional but useful)
                .appendQueryParameter("state", authState)
                .build()

            // Launch the authorization page with Custom Tabs
            val customTabsIntent = CustomTabsIntent.Builder().build()
            customTabsIntent.launchUrl(this, githubAuthUrl)
        }
    }
}

3. Set Up a Callback Activity to Handle GitHub's Response

GitHub will redirect back to your app using the redirect_uri you specified. Create a new activity (GithubAuthCallbackActivity) to capture this response, then register it in your AndroidManifest.xml:

Manifest Entry

<activity
    android:name=".GithubAuthCallbackActivity"
    android:exported="true"
    android:noHistory="true"> <!-- Prevents this activity from staying in the back stack -->
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- Match the scheme from your redirect URI -->
        <data android:scheme="your_app_scheme" />
    </intent-filter>
</activity>

Callback Activity Code

This activity will validate the state, exchange the authorization code for a GitHub access token, then use that token to sign in to Firebase. First, add OkHttp (for network requests) to your build.gradle:

implementation("com.squareup.okhttp3:okhttp:4.11.0")

Then, the activity code:

class GithubAuthCallbackActivity : AppCompatActivity() {
    private val GITHUB_CLIENT_ID = "your_github_client_id_here"
    private val GITHUB_CLIENT_SECRET = "your_github_client_secret_here"
    private val GITHUB_REDIRECT_URI = "your_app_scheme://github-auth"
    private val AUTH_PREFS = "AuthPrefs"
    private val KEY_GITHUB_STATE = "github_state"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_github_auth_callback) // Can be a blank layout

        intent.data?.let { uri ->
            val authCode = uri.getQueryParameter("code")
            val returnedState = uri.getQueryParameter("state")
            val savedState = getSharedPreferences(AUTH_PREFS, MODE_PRIVATE).getString(KEY_GITHUB_STATE, null)

            // Validate state to prevent CSRF attacks
            if (returnedState == savedState && authCode != null) {
                exchangeCodeForAccessToken(authCode)
            } else {
                Toast.makeText(this, "Authentication failed: Invalid state", Toast.LENGTH_SHORT).show()
                finish()
            }
        } ?: run {
            Toast.makeText(this, "No authentication data received", Toast.LENGTH_SHORT).show()
            finish()
        }
    }

    private fun exchangeCodeForAccessToken(code: String) {
        val okHttpClient = OkHttpClient()
        val requestBody = FormBody.Builder()
            .add("client_id", GITHUB_CLIENT_ID)
            .add("client_secret", GITHUB_CLIENT_SECRET)
            .add("code", code)
            .add("redirect_uri", GITHUB_REDIRECT_URI)
            .build()

        val request = Request.Builder()
            .url("https://github.com/login/oauth/access_token")
            .post(requestBody)
            .header("Accept", "application/json") // Get JSON response for easier parsing
            .build()

        okHttpClient.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                runOnUiThread {
                    Toast.makeText(this@GithubAuthCallbackActivity, "Failed to connect to GitHub", Toast.LENGTH_SHORT).show()
                    finish()
                }
            }

            override fun onResponse(call: Call, response: Response) {
                response.body?.string()?.let { responseString ->
                    try {
                        val jsonObject = JSONObject(responseString)
                        val accessToken = jsonObject.getString("access_token")
                        signInToFirebase(accessToken)
                    } catch (e: JSONException) {
                        runOnUiThread {
                            Toast.makeText(this@GithubAuthCallbackActivity, "Invalid response from GitHub", Toast.LENGTH_SHORT).show()
                            finish()
                        }
                    }
                } ?: run {
                    runOnUiThread {
                        Toast.makeText(this@GithubAuthCallbackActivity, "Empty response from GitHub", Toast.LENGTH_SHORT).show()
                        finish()
                    }
                }
            }
        })
    }

    private fun signInToFirebase(accessToken: String) {
        val credential = GithubAuthProvider.getCredential(accessToken)
        FirebaseAuth.getInstance().signInWithCredential(credential)
            .addOnCompleteListener(this) { task ->
                if (task.isSuccessful) {
                    // Login successful! Redirect to main activity
                    val intent = Intent(this, MainActivity::class.java)
                    intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
                    startActivity(intent)
                } else {
                    runOnUiThread {
                        Toast.makeText(this, "Firebase login failed: ${task.exception?.message}", Toast.LENGTH_SHORT).show()
                    }
                }
                finish()
            }
    }
}

4. Key Notes to Avoid Issues

  • Redirect URI Match: Ensure the redirect_uri in your code exactly matches what you set in your GitHub app's "Authorization callback URL" field.
  • State Validation: Never skip validating the state parameter—it's critical for preventing CSRF attacks.
  • Dependencies: Use the latest versions of Firebase Auth, OkHttp, and Custom Tabs in your build.gradle.
  • Internet Permission: Add <uses-permission android:name="android.permission.INTERNET" /> to your AndroidManifest.xml (required for network requests).

内容的提问来源于stack exchange,提问作者Jean-Pascal MEWENEMESSE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 02:33:23