Skip to content

Commit

Permalink
Applied appauth libs for OAuth.| #716
Browse files Browse the repository at this point in the history
  • Loading branch information
DenBond7 committed Aug 7, 2020
1 parent d4f7fae commit 02611bf
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 131 deletions.
1 change: 1 addition & 0 deletions FlowCrypt/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -425,4 +425,5 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
implementation 'ja.burhanrashid52:photoeditor:1.0.0'
implementation "org.jetbrains.kotlin:kotlin-reflect:1.3.72"
implementation 'net.openid:appauth:0.7.1'
}
13 changes: 9 additions & 4 deletions FlowCrypt/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,21 @@
<activity
android:name=".ui.activity.SignInActivity"
android:launchMode="singleTask"
android:screenOrientation="portrait">
<intent-filter android:autoVerify="true">
android:screenOrientation="portrait" />

<activity
android:name="net.openid.appauth.RedirectUriReceiverActivity"
tools:node="replace">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<!-- support Microsoft OAuth2.0 -->
<data android:scheme="msauth" />
<data android:host="${applicationId}" />
<data
android:host="${applicationId}"
android:scheme="msauth" />
</intent-filter>
</activity>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@

package com.flowcrypt.email.api.oauth

import android.content.Intent
import android.net.Uri
import okhttp3.HttpUrl.Companion.toHttpUrl
import net.openid.appauth.AuthorizationRequest
import net.openid.appauth.AuthorizationServiceConfiguration
import net.openid.appauth.ResponseTypeValues

/**
* @author Denis Bondarenko
Expand All @@ -17,10 +18,6 @@ import okhttp3.HttpUrl.Companion.toHttpUrl
*/
class OAuth2Helper {
companion object {
const val QUERY_PARAMETER_STATE = "state"
const val QUERY_PARAMETER_CODE = "code"
const val QUERY_PARAMETER_ERROR = "error"
const val QUERY_PARAMETER_ERROR_DESCRIPTION = "error_description"
const val OAUTH2_GRANT_TYPE = "authorization_code"
const val OAUTH2_GRANT_TYPE_REFRESH_TOKEN = "refresh_token"

Expand All @@ -41,19 +38,20 @@ class OAuth2Helper {
const val MICROSOFT_OAUTH2_TOKEN_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
const val MICROSOFT_REDIRECT_URI = "msauth://com.flowcrypt.email.denys/04gM%2BEAfhnq4ALbhOX8jG5oRuow%3D"
const val MICROSOFT_AZURE_APP_ID = "3be51534-5f76-4970-9a34-40ef197aa018"
const val MICROSOFT_OAUTH2_SCHEMA = "msauth"

fun getMicrosoftOAuth2Intent(state: String): Intent {
val authorizeUrl = MICROSOFT_OAUTH2_AUTHORIZE_URL.toHttpUrl()
.newBuilder()
.addQueryParameter("client_id", MICROSOFT_AZURE_APP_ID)
.addQueryParameter("response_type", "code")
.addQueryParameter("redirect_uri", MICROSOFT_REDIRECT_URI)
.addQueryParameter("response_mode", "query")
.addQueryParameter("scope", "$SCOPE_MICROSOFT_OAUTH2_FOR_PROFILE $SCOPE_MICROSOFT_OAUTH2_FOR_MAIL")
.addQueryParameter(QUERY_PARAMETER_STATE, state)
.build()
fun getMicrosoftAuthorizationRequest(): AuthorizationRequest {
val configuration = AuthorizationServiceConfiguration(Uri.parse(MICROSOFT_OAUTH2_AUTHORIZE_URL), Uri.parse(MICROSOFT_OAUTH2_TOKEN_URL))

return Intent(Intent.ACTION_VIEW).apply { data = Uri.parse(authorizeUrl.toUrl().toString()) }
return AuthorizationRequest.Builder(
configuration,
MICROSOFT_AZURE_APP_ID,
ResponseTypeValues.CODE,
Uri.parse(MICROSOFT_REDIRECT_URI))
.setScope("$SCOPE_MICROSOFT_OAUTH2_FOR_PROFILE $SCOPE_MICROSOFT_OAUTH2_FOR_MAIL")
.build()
}

val SUPPORTED_SCHEMAS = listOf(MICROSOFT_OAUTH2_SCHEMA)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import com.flowcrypt.email.api.retrofit.response.attester.LookUpEmailsResponse
import com.flowcrypt.email.api.retrofit.response.attester.PubResponse
import com.flowcrypt.email.api.retrofit.response.attester.TestWelcomeResponse
import com.flowcrypt.email.api.retrofit.response.base.Result
import com.flowcrypt.email.api.retrofit.response.oauth2.MicrosoftAccountResponse
import com.flowcrypt.email.api.retrofit.response.oauth2.MicrosoftOAuth2TokenResponse

/**
Expand Down Expand Up @@ -86,7 +85,5 @@ interface ApiRepository : BaseApiRepository {
* @param context Interface to global information about an application environment.
* @param authorizeCode A code which will be used to retrieve an access token.
*/
suspend fun getMicrosoftOAuth2Token(requestCode: Long = 0L, context: Context, authorizeCode: String, scopes: String): Result<MicrosoftOAuth2TokenResponse>

suspend fun getMicrosoftAccountInfo(requestCode: Long = 0L, context: Context, bearerToken: String): Result<MicrosoftAccountResponse>
suspend fun getMicrosoftOAuth2Token(requestCode: Long = 0L, context: Context, authorizeCode: String, scopes: String, codeVerifier: String): Result<MicrosoftOAuth2TokenResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import com.flowcrypt.email.api.retrofit.response.attester.InitialLegacySubmitRes
import com.flowcrypt.email.api.retrofit.response.attester.LookUpEmailResponse
import com.flowcrypt.email.api.retrofit.response.attester.LookUpEmailsResponse
import com.flowcrypt.email.api.retrofit.response.attester.TestWelcomeResponse
import com.flowcrypt.email.api.retrofit.response.oauth2.MicrosoftAccountResponse
import com.flowcrypt.email.api.retrofit.response.oauth2.MicrosoftOAuth2TokenResponse
import retrofit2.Call
import retrofit2.Response
Expand Down Expand Up @@ -144,6 +143,7 @@ interface ApiService {
suspend fun getMicrosoftOAuth2Token(
@Field("code") code: String,
@Field("scope") scope: String,
@Field("code_verifier") codeVerifier: String,
@Field("client_id") clientId: String = OAuth2Helper.MICROSOFT_AZURE_APP_ID,
@Field("redirect_uri") redirect_uri: String = OAuth2Helper.MICROSOFT_REDIRECT_URI,
@Field("grant_type") grant_type: String = OAuth2Helper.OAUTH2_GRANT_TYPE): Response<MicrosoftOAuth2TokenResponse>
Expand All @@ -155,8 +155,4 @@ interface ApiService {
@Field("scope") scope: String,
@Field("client_id") clientId: String = OAuth2Helper.MICROSOFT_AZURE_APP_ID,
@Field("grant_type") grant_type: String = OAuth2Helper.OAUTH2_GRANT_TYPE_REFRESH_TOKEN): Response<MicrosoftOAuth2TokenResponse>


@GET("https://graph.microsoft.com/v1.0/me/")
suspend fun getMicrosoftAccountInfo(@Header("Authorization") bearerToken: String): Response<MicrosoftAccountResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import com.flowcrypt.email.api.retrofit.response.attester.LookUpEmailsResponse
import com.flowcrypt.email.api.retrofit.response.attester.PubResponse
import com.flowcrypt.email.api.retrofit.response.attester.TestWelcomeResponse
import com.flowcrypt.email.api.retrofit.response.base.Result
import com.flowcrypt.email.api.retrofit.response.oauth2.MicrosoftAccountResponse
import com.flowcrypt.email.api.retrofit.response.oauth2.MicrosoftOAuth2TokenResponse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
Expand Down Expand Up @@ -95,16 +94,10 @@ class FlowcryptApiRepository : ApiRepository {
}

override suspend fun getMicrosoftOAuth2Token(requestCode: Long, context: Context,
authorizeCode: String, scopes: String):
authorizeCode: String, scopes: String, codeVerifier: String):
Result<MicrosoftOAuth2TokenResponse> =
withContext(Dispatchers.IO) {
val apiService = ApiHelper.getInstance(context).retrofit.create(ApiService::class.java)
getResult { apiService.getMicrosoftOAuth2Token(authorizeCode, scopes) }
}

override suspend fun getMicrosoftAccountInfo(requestCode: Long, context: Context, bearerToken: String): Result<MicrosoftAccountResponse> =
withContext(Dispatchers.IO) {
val apiService = ApiHelper.getInstance(context).retrofit.create(ApiService::class.java)
getResult { apiService.getMicrosoftAccountInfo("Bearer $bearerToken") }
getResult { apiService.getMicrosoftOAuth2Token(authorizeCode, scopes, codeVerifier) }
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.flowcrypt.email.api.retrofit.ApiRepository
import com.flowcrypt.email.api.retrofit.FlowcryptApiRepository
import com.flowcrypt.email.api.retrofit.response.base.Result
import kotlinx.coroutines.launch
import net.openid.appauth.AuthorizationRequest


/**
Expand All @@ -27,14 +28,15 @@ class OAuth2AuthCredentialsViewModel(application: Application) : BaseAndroidView
private val apiRepository: ApiRepository = FlowcryptApiRepository()
val microsoftOAuth2TokenLiveData = MutableLiveData<Result<AuthCredentials>>()

fun getMicrosoftOAuth2Token(requestCode: Long = 0L, authorizeCode: String) {
fun getMicrosoftOAuth2Token(requestCode: Long = 0L, authorizeCode: String, authRequest: AuthorizationRequest) {
viewModelScope.launch {
microsoftOAuth2TokenLiveData.postValue(Result.loading())
val microsoftOAuth2TokenResponseResultForProfile = apiRepository.getMicrosoftOAuth2Token(
requestCode = requestCode,
context = getApplication(),
authorizeCode = authorizeCode,
scopes = OAuth2Helper.SCOPE_MICROSOFT_OAUTH2_FOR_PROFILE
scopes = OAuth2Helper.SCOPE_MICROSOFT_OAUTH2_FOR_PROFILE,
codeVerifier = authRequest.codeVerifier ?: ""
)

if (microsoftOAuth2TokenResponseResultForProfile.status != Result.Status.SUCCESS) {
Expand All @@ -54,19 +56,17 @@ class OAuth2AuthCredentialsViewModel(application: Application) : BaseAndroidView
return@launch
}

//validate id_token


val tokenForProfile = microsoftOAuth2TokenResponseResultForProfile.data?.accessToken
if (tokenForProfile == null) {
microsoftOAuth2TokenLiveData.postValue(Result.exception(NullPointerException("token is null")))
return@launch
}

val microsoftAccount = apiRepository.getMicrosoftAccountInfo(
requestCode = requestCode,
context = getApplication(),
bearerToken = tokenForProfile
)

val userEmailAddress = microsoftAccount.data?.userPrincipalName
val userEmailAddress = "[email protected]"//microsoftAccount.data?.userPrincipalName
if (userEmailAddress == null) {
microsoftOAuth2TokenLiveData.postValue(Result.exception(NullPointerException("User email is null")))
return@launch
Expand All @@ -76,7 +76,8 @@ class OAuth2AuthCredentialsViewModel(application: Application) : BaseAndroidView
requestCode = requestCode,
context = getApplication(),
authorizeCode = authorizeCode,
scopes = OAuth2Helper.SCOPE_MICROSOFT_OAUTH2_FOR_MAIL
scopes = OAuth2Helper.SCOPE_MICROSOFT_OAUTH2_FOR_MAIL,
codeVerifier = authRequest.codeVerifier ?: ""
)

if (microsoftOAuth2TokenResponseResultForEmail.status != Result.Status.SUCCESS) {
Expand Down Expand Up @@ -104,7 +105,7 @@ class OAuth2AuthCredentialsViewModel(application: Application) : BaseAndroidView
}

val recommendAuthCredentials = EmailProviderSettingsHelper.getBaseSettings(
microsoftAccount.data.userPrincipalName, tokenForEmail)?.copy(useOAuth2 = true)
"microsoftAccount.data.userPrincipalName", tokenForEmail)?.copy(useOAuth2 = true)

microsoftOAuth2TokenLiveData.postValue(Result.success(recommendAuthCredentials!!))
}
Expand Down
Loading

0 comments on commit 02611bf

Please sign in to comment.