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

[LD-163] Add access token encryption. #210

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
4 changes: 3 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ android {
}
debug {
enableUnitTestCoverage true
testCoverageEnabled true
}
}
compileOptions {
Expand Down Expand Up @@ -161,6 +160,9 @@ dependencies {
// Firebase
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.analytics)

// Security
implementation(libs.androidx.security)
}

tasks.withType(Test) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
package com.appunite.loudius.domain.store

import android.content.Context
import android.content.SharedPreferences
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import com.appunite.loudius.network.model.AccessToken

interface UserLocalDataSource {
Expand All @@ -32,8 +33,19 @@ class UserLocalDataSourceImpl(context: Context) : UserLocalDataSource {
private const val KEY_ACCESS_TOKEN = "access_token"
}

private val sharedPreferences: SharedPreferences =
context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
private val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()

private val sharedPreferences by lazy {
EncryptedSharedPreferences.create(
context,
FILE_NAME,
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
)
}

override fun saveAccessToken(accessToken: AccessToken) {
sharedPreferences.edit().putString(KEY_ACCESS_TOKEN, accessToken).apply()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@
package com.appunite.loudius.di

import android.content.Context
import android.content.SharedPreferences
import com.appunite.loudius.appModule
import com.appunite.loudius.util.MainDispatcherExtension
import com.google.firebase.analytics.FirebaseAnalytics
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkClass
import io.mockk.mockkStatic
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
Expand All @@ -36,9 +34,7 @@ class CheckModulesTest : KoinTest {

@Test
fun verifyKoinApp() {
val mockContext = mockkClass(Context::class)
val mockSharedPref = mockkClass(SharedPreferences::class)
every { mockContext.getSharedPreferences(any(), any()) } returns mockSharedPref
val mockContext = mockk<Context>(relaxed = true)

val mockFirebaseAnalytics = mockk<FirebaseAnalytics>()
mockkStatic(FirebaseAnalytics::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@

package com.appunite.loudius.domain

import android.content.Context
import com.appunite.loudius.domain.store.UserLocalDataSourceImpl
import com.appunite.loudius.fakes.FakeSharedPreferences
import com.appunite.loudius.domain.store.UserLocalDataSource
import io.mockk.every
import io.mockk.mockk
import org.junit.jupiter.api.Test
Expand All @@ -27,11 +25,11 @@ import strikt.assertions.isEmpty
import strikt.assertions.isEqualTo

class UserLocalDataSourceTest {
private val sharedPreferences = FakeSharedPreferences()
private val context = mockk<Context> {
every { getSharedPreferences(any(), any()) } returns sharedPreferences

private val userLocalDataSource = mockk<UserLocalDataSource> {
every { saveAccessToken(any()) } returns Unit
every { getAccessToken() } returns ""
}
private val userLocalDataSource = UserLocalDataSourceImpl(context)

@Test
fun `GIVEN the app is started first time WHEN getting access token THEN token is empty`() {
Expand All @@ -42,6 +40,8 @@ class UserLocalDataSourceTest {

@Test
fun `WHEN token is set THEN token can be retrieved`() {
every { userLocalDataSource.getAccessToken() } returns "someToken"

userLocalDataSource.saveAccessToken("someToken")

val result = userLocalDataSource.getAccessToken()
Expand Down
105 changes: 0 additions & 105 deletions app/src/test/java/com/appunite/loudius/fakes/FakeSharedPreferences.kt

This file was deleted.

2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ mockwebserver = "4.11.0"
mockkAndroid = "1.13.5"
okhttp3 = "4.12.0"
robolectric = "4.10.3"
securityCrypto = "1.1.0-alpha06"
slf4jApi = "2.0.11"
striktCore = "0.34.1"
striktMockk = "0.34.1"
Expand Down Expand Up @@ -71,6 +72,7 @@ androidx-junit = { module = "androidx.test.ext:junit", version.ref = "junitVersi
androidx-junit-ktx = { module = "androidx.test.ext:junit-ktx", version.ref = "junitVersion" }
androidx-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "ktx" }
androidx-lifecycle = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleKtx" }
androidx-security = { group = "androidx.security", name = "security-crypto", version.ref = "securityCrypto" }
androidx-test-orchestartor = { group = "androidx.test", name = "orchestrator", version.ref = "testOrchestrator" }
androidx-test-runner = { group = "androidx.test", name = "runner", version.ref = "testRunner" }
androidx-test-uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version.ref = "testUiAutomator" }
Expand Down
4 changes: 4 additions & 0 deletions module-jacoco.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
apply plugin: 'jacoco'

jacoco {
toolVersion '0.8.8'
}

tasks.register('codeCoverage', JacocoReport) {

reports {
Expand Down
Loading