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?