Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(e2ei): use refresh token for IDP authorisation (WPB-5880) #2327

Merged
merged 3 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,7 @@ class E2EIClientImpl : E2EIClient {
TODO("Not yet implemented")
}

override suspend fun getOAuthRefreshToken(): String? {
TODO("Not yet implemented")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ class E2EIClientImpl(
override suspend fun certificateRequest(previousNonce: String) =
wireE2eIdentity.certificateRequest(previousNonce)

@Suppress("TooGenericExceptionCaught")
override suspend fun getOAuthRefreshToken() = try {
wireE2eIdentity.getRefreshToken()
} catch (e: Exception) {
null
}

companion object {
fun toAcmeDirectory(value: com.wire.crypto.AcmeDirectory) = AcmeDirectory(
value.newNonce, value.newAccount, value.newOrder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,5 @@ interface E2EIClient {
suspend fun finalizeRequest(previousNonce: String): JsonRawData
suspend fun finalizeResponse(finalize: JsonRawData): String
suspend fun certificateRequest(previousNonce: String): JsonRawData
suspend fun getOAuthRefreshToken(): String?
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,8 @@ class E2EIClientImpl : E2EIClient {
override suspend fun certificateRequest(previousNonce: String): JsonRawData {
TODO("Not yet implemented")
}

override suspend fun getOAuthRefreshToken(): String? {
TODO("Not yet implemented")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import kotlinx.coroutines.withContext

interface E2EIClientProvider {
suspend fun getE2EIClient(clientId: ClientId? = null): Either<CoreFailure, E2EIClient>
suspend fun nuke()
}

internal class EI2EIClientProviderImpl(
Expand Down Expand Up @@ -86,6 +87,10 @@ internal class EI2EIClientProviderImpl(
else Either.Right(selfUser)
}

override suspend fun nuke() {
e2EIClient = null
}

companion object {
const val ERROR_NAME_AND_HANDLE_MUST_NOT_BE_NULL = "name and handle must have a value"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,30 @@ interface E2EIRepository {
suspend fun loadACMEDirectories(): Either<CoreFailure, AcmeDirectory>
suspend fun getACMENonce(endpoint: String): Either<CoreFailure, String>
suspend fun createNewAccount(prevNonce: String, createAccountEndpoint: String): Either<CoreFailure, String>
suspend fun createNewOrder(prevNonce: String, createOrderEndpoint: String):
Either<CoreFailure, Triple<NewAcmeOrder, String, String>>
suspend fun createAuthz(prevNonce: String, authzEndpoint: String):
Either<CoreFailure, Triple<NewAcmeAuthz, String, String>>
suspend fun createNewOrder(prevNonce: String, createOrderEndpoint: String): Either<CoreFailure, Triple<NewAcmeOrder, String, String>>
suspend fun createAuthz(prevNonce: String, authzEndpoint: String): Either<CoreFailure, Triple<NewAcmeAuthz, String, String>>
suspend fun getWireNonce(): Either<CoreFailure, String>
suspend fun getWireAccessToken(wireNonce: String): Either<CoreFailure, AccessTokenResponse>
suspend fun getDPoPToken(wireNonce: String): Either<CoreFailure, String>
suspend fun validateDPoPChallenge(accessToken: String, prevNonce: String, acmeChallenge: AcmeChallenge):
Either<CoreFailure, ChallengeResponse>
suspend fun validateOIDCChallenge(idToken: String, refreshToken: String, prevNonce: String, acmeChallenge: AcmeChallenge):
Either<CoreFailure, ChallengeResponse>
suspend fun validateDPoPChallenge(
accessToken: String,
prevNonce: String,
acmeChallenge: AcmeChallenge
): Either<CoreFailure, ChallengeResponse>
suspend fun validateOIDCChallenge(
idToken: String,
refreshToken: String,
prevNonce: String,
acmeChallenge: AcmeChallenge
): Either<CoreFailure, ChallengeResponse>
suspend fun setDPoPChallengeResponse(challengeResponse: ChallengeResponse): Either<CoreFailure, Unit>
suspend fun setOIDCChallengeResponse(challengeResponse: ChallengeResponse): Either<CoreFailure, Unit>
suspend fun finalize(location: String, prevNonce: String): Either<CoreFailure, Pair<ACMEResponse, String>>
suspend fun checkOrderRequest(location: String, prevNonce: String): Either<CoreFailure, Pair<ACMEResponse, String>>
suspend fun certificateRequest(location: String, prevNonce: String): Either<CoreFailure, ACMEResponse>
suspend fun rotateKeysAndMigrateConversations(certificateChain: String): Either<CoreFailure, Unit>
suspend fun getOAuthRefreshToken(): Either<CoreFailure, String?>
suspend fun nukeE2EIClient()
}

@Suppress("LongParameterList")
Expand Down Expand Up @@ -214,6 +221,14 @@ class E2EIRepositoryImpl(
}
}

override suspend fun getOAuthRefreshToken() = e2EIClientProvider.getE2EIClient().flatMap { e2EIClient ->
Either.Right(e2EIClient.getOAuthRefreshToken())
}

override suspend fun nukeE2EIClient() {
e2EIClientProvider.nuke()
}

companion object {
// todo: remove after testing e2ei
const val TEMP_ACME_DISCOVER_URL = "https://acme.elna.wire.link/acme/defaultteams"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.wire.kalium.logic.E2EIFailure
import com.wire.kalium.logic.data.e2ei.E2EIRepository
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.getOrFail
import com.wire.kalium.logic.functional.getOrNull
import com.wire.kalium.logic.functional.onFailure
import com.wire.kalium.logic.kaliumLogger

Expand All @@ -33,7 +34,7 @@ interface EnrollE2EIUseCase {
suspend fun initialEnrollment(): Either<CoreFailure, E2EIEnrollmentResult>
suspend fun finalizeEnrollment(
idToken: String,
refreshToken: String?,
oAuthState: String,
initializationResult: E2EIEnrollmentResult.Initialized
): Either<E2EIFailure, E2EIEnrollmentResult>
}
Expand Down Expand Up @@ -71,9 +72,17 @@ class EnrollE2EIUseCaseImpl internal constructor(
val authzResponse = e2EIRepository.createAuthz(prevNonce, newOrderResponse.first.authorizations[0]).getOrFail {
return E2EIEnrollmentResult.Failed(E2EIEnrollmentResult.E2EIStep.AcmeNewAuthz, it).toEitherLeft()
}
kaliumLogger.i("getoAuth")

val oAuthState = e2EIRepository.getOAuthRefreshToken().getOrNull()
kaliumLogger.i("oAuthStAte: $oAuthState")

val initializationResult = E2EIEnrollmentResult.Initialized(
authzResponse.first.wireOidcChallenge!!.target, authzResponse.first, authzResponse.second, newOrderResponse.third
target = authzResponse.first.wireOidcChallenge!!.target,
oAuthState = oAuthState,
authz = authzResponse.first,
lastNonce = authzResponse.second,
orderLocation = newOrderResponse.third
)

kaliumLogger.i("E2EI Enrollment Initialization Result: $initializationResult")
Expand All @@ -91,7 +100,7 @@ class EnrollE2EIUseCaseImpl internal constructor(
*/
override suspend fun finalizeEnrollment(
idToken: String,
refreshToken: String?,
oAuthState: String,
initializationResult: E2EIEnrollmentResult.Initialized
): Either<E2EIFailure, E2EIEnrollmentResult> {

Expand Down Expand Up @@ -120,7 +129,7 @@ class EnrollE2EIUseCaseImpl internal constructor(
prevNonce = dpopChallengeResponse.nonce

val oidcChallengeResponse = e2EIRepository.validateOIDCChallenge(
idToken, refreshToken ?: "", prevNonce, authz.wireOidcChallenge!!
idToken, oAuthState, prevNonce, authz.wireOidcChallenge!!
).getOrFail {
return E2EIEnrollmentResult.Failed(E2EIEnrollmentResult.E2EIStep.OIDCChallenge, it).toEitherLeft()
}
Expand All @@ -147,6 +156,8 @@ class EnrollE2EIUseCaseImpl internal constructor(
return E2EIEnrollmentResult.Failed(E2EIEnrollmentResult.E2EIStep.ConversationMigration, it).toEitherLeft()
}

e2EIRepository.nukeE2EIClient()

return Either.Right(E2EIEnrollmentResult.Finalized(certificateRequest.response.decodeToString()))
}

Expand All @@ -171,7 +182,13 @@ sealed interface E2EIEnrollmentResult {
Certificate
}

class Initialized(val target: String, val authz: NewAcmeAuthz, val lastNonce: String, val orderLocation: String) : E2EIEnrollmentResult
class Initialized(
val target: String,
val oAuthState: String?,
val authz: NewAcmeAuthz,
val lastNonce: String,
val orderLocation: String
) : E2EIEnrollmentResult

class Finalized(val certificate: String) : E2EIEnrollmentResult

Expand Down
Loading
Loading