Android: GitHub Authorization in Sign Up/In Feature

17 Views Asked by At

I'm currently working on implementing a feature in my Android application that allows users to sign up and sign in using their GitHub accounts. However, I'm facing some challenges with the flow of navigating to the GitHub authorization page in a browser window and then back to my application after authorization. The app is navigating to the browser but am getting an error that the endpoint is not reachable or server is down.

Here's a summary of what I've implemented so far:

I have defined endpoints for GitHub sign up and sign in in my Endpoint.kt file. I've set up API methods in MyApi to handle GitHub sign up and sign in requests. My AuthRepositoryImpl class contains functions for signing up and signing in with GitHub. I have a GitHubModel class that handles user interactions and initiates the GitHub authentication process. Here's a snippet of the relevant code:

// Endpoint.kt
sealed class Endpoint(val route: String, private val customBaseUrl: String? = null) {
    private val baseUrl = "https://development.mentorlst.com/"

    val url: String
        get() =
            buildString {
                append(baseUrl)
                append(route)
            }
object Auth {

        object GithubSignIn : Endpoint(route = "auth/login/github")

        object GithubSignUp : Endpoint(route = "auth/register/github")
    }

my api 
class MyApi
    @Inject
    constructor(val client: HttpClient) {
        suspend fun githubSignUp(
            request: GithubSignUpRequestDTO,
//            ClientID: String,
//            ClientSecret: String,
        ): NetworkResult<GithubSignUpResponseDTO> =
            safeApiCall {
                client.post(urlString = Endpoint.Auth.GithubSignUp.url)
            }

        suspend fun githubSignIn(request: GithubSignInRequestDTO): NetworkResult<GithubSignInResponseDTO> =
            safeApiCall {
                client.post(urlString = Endpoint.Auth.GithubSignIn.url) {
                    setBody(request)
                }
            }
    }

Myrepository
class AuthRepositoryImpl(
    val api: MytApi,
    val remotePreference: RemotePreference,
    val localPreference: LocalPreference
) : AuthRepository {

    override suspend fun signUpWithGithub(code: String): DataResult<String> {
        return when (val response = api.githubSignUp(request = GithubSignUpRequestDTO(code))){
            is NetworkResult.Error -> {
                DataResult.Error(message = response.message)
            }

            is NetworkResult.Success -> {
                val data = response.data
                handleResponse(
                    access = data.accessToken,
                    refresh = data.refreshToken,
                    entity = data.toEntity()
                )
                DataResult.Success(data = "Welcome ${data.fullName}")
            }
        }
    } 

    override suspend fun signInWithGithub(code: String): DataResult<String> {
        return when (val response = api.githubSignIn(request = GithubSignInRequestDTO(code))) {
            is NetworkResult.Error -> {
                DataResult.Error(message = response.message)
            }

            is NetworkResult.Success -> {
                val data = response.data
                handleResponse(
                    access = data.accessToken,
                    refresh = data.refreshToken,
                    entity = data.toEntity()
                )
                DataResult.Success(data = "You have successfully signed up")
            }
        }
    }
@Serializable
data class GithubSignUpRequestDTO(
    @Serializable
    val code: String,
)

@Serializable
data class GithubSignUpResponseDTO(
    val accessToken: String,
    val authProviderType: String,
    val fullName: String,
    val menteeProfile: String,
    val mentorProfile: String,
    val profilePicture: String,
    val refreshToken: String,
    val timeZone: String,
) {
    companion object {
        val RESPONSE =
            """
{
    "accessToken": "string",
    "refreshToken": "string",
    "authProviderType": "string",
    "mentorProfile": "string",
    "menteeProfile": "string",
    "profilePicture": "string",
    "fullName": "string"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "timeZone": "string"
}
            """.trimIndent()

 
class GitHubModel
    @Inject
    constructor(
        val repository: AuthRepository,
    ) : MutableScreenModel<GithubState>(GithubState()) {
        private fun showLoading() {
            updateState { copy(isLoading = true) }
        }

        private fun hideLoading() {
            updateState { copy(isLoading = false) }
        }

        fun onGithubClicked(context: Context) {
            coroutineScope.launch {
                showLoading()
                val code = state.value.code ?: ""
                val response = repository.signInWithGithub(code)
                val authUrl = Endpoint.Auth.GithubSignIn.url
                val clientId = "aa84d7f6e47ad98754a1"
                val clientSecret = "6101c1c5a4803e9f68e5a31ca4b5743f22e7acdd"
                val authUrlWithParams = "$authUrl?client_id=$clientId&client_secret=$clientSecret&code=$code"
                openBrowser(context, authUrl)
                hideLoading()
                when (response) {
                    is DataResult.Error -> {
                        updateState { copy(authenticationError = response.message) }
                    }

                    is DataResult.Success -> {
                        updateState { copy(navigateToProfile = true) }
                    }

                    else -> {}
                }
            }
        }

        fun clearError() {
            updateState { copy(authenticationError = null) }
        }

        private fun openBrowser(
            context: Context,
            authUrl: String,
        ) {
            val intent = Intent(Intent.ACTION_VIEW, Uri.parse(authUrl))
            context.startActivity(intent)
        }
    }

The issue I'm facing is with the navigation flow when the user clicks the GitHub sign up or sign in button. Ideally, I want the user to be redirected to a browser window where they can sign in to their GitHub account and authorize my application to access their credentials. After authorization, I want to navigate the user back to my application.

However, I'm unsure about how to properly handle this navigation flow. Currently, when the GitHub button is clicked, I'm opening a browser window using an intent, but I'm not sure how to handle the redirection back to my application after authorization.

Can someone provide guidance on how to properly implement this navigation flow for signing up and signing in with GitHub in an Android application?

0

There are 0 best solutions below