Skip to content
Merged
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: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ The MIRACL Trust Android SDK provides the following functionalities:

```kotlin
dependencies {
implementation("com.miracl:trust-sdk-android:1.13.0")
implementation("com.miracl:trust-sdk-android:1.14.0")
}
```

Groovy:

```groovy
dependencies {
implementation "com.miracl:trust-sdk-android:1.13.0"
implementation "com.miracl:trust-sdk-android:1.14.0"
}
```

Expand Down
2 changes: 1 addition & 1 deletion miracl-sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ plugins {
alias libs.plugins.jreleaser
}

version = '1.13.0'
version = '1.14.0'

android {
namespace 'com.miracl.trust'
Expand Down
8 changes: 7 additions & 1 deletion miracl-sdk/src/main/java/com/miracl/trust/MIRACLTrust.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.miracl.trust.authentication.AuthenticatorScopes
import com.miracl.trust.configuration.*
import com.miracl.trust.configuration.factory.ConfigurationFactory
import com.miracl.trust.configuration.factory.DefaultConfigurationFactory
import com.miracl.trust.core.DeviceTagProvider
import com.miracl.trust.delegate.PinProvider
import com.miracl.trust.delegate.ResultHandler
import com.miracl.trust.factory.ComponentFactory
Expand Down Expand Up @@ -187,7 +188,12 @@ public class MIRACLTrust private constructor(
configuration.applicationInfo
)

val componentFactory = configuration.componentFactory ?: ComponentFactory(context, logger)
var componentFactory = configuration.componentFactory
if (componentFactory == null) {
val deviceTagProvider = DeviceTagProvider.create(context)
componentFactory = ComponentFactory(context, logger, deviceTagProvider)
}

apiSettings = ApiSettings(projectUrl)

miraclTrustCoroutineContext = configuration.miraclCoroutineContext
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.miracl.trust.core

import android.content.Context
import com.miracl.trust.util.toHexString
import java.io.File
import java.security.SecureRandom

internal class DeviceTagProvider(private val file: File) {

fun get(): String {
cachedTag?.let { return it }
Comment thread
Foriger marked this conversation as resolved.
Comment thread
Foriger marked this conversation as resolved.

synchronized(LOCK) {
cachedTag?.let { return it }

val tag = try {
if (file.exists()) {
val stored = file.readText(Charsets.UTF_8).trim()

if (isValidTag(stored)) {
stored
} else {
createAndPersist(file)
}
} else {
createAndPersist(file)
}
} catch (_: Exception) {
createAndPersist(file)
}

cachedTag = tag
return tag
}
}

private fun createAndPersist(file: File): String {
val tag = generateTag()

try {
file.writeText(tag, Charsets.UTF_8)
} catch (_: Exception) {
// Ignore persistence failure.
}

return tag
}

private fun isValidTag(value: String): Boolean {
Comment thread
Foriger marked this conversation as resolved.
return value.length == ID_LENGTH &&
value.all { it in '0'..'9' || it in 'a'..'f' }
}

private fun generateTag(): String {
val data = ByteArray(16)
SecureRandom().nextBytes(data)

return data.toHexString()
}

internal companion object {
private const val FILE_NAME = "miracl_device_tag"
private const val ID_LENGTH = 32

private val LOCK = Any()

@Volatile
private var cachedTag: String? = null

fun create(context: Context): DeviceTagProvider {
val file = File(context.applicationContext.noBackupFilesDir, FILE_NAME)
return DeviceTagProvider(file)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.content.Context
import com.miracl.trust.authentication.AuthenticationApi
import com.miracl.trust.authentication.Authenticator
import com.miracl.trust.authentication.AuthenticatorContract
import com.miracl.trust.core.DeviceTagProvider
import com.miracl.trust.crypto.Crypto
import com.miracl.trust.registration.*
import com.miracl.trust.session.*
Expand All @@ -14,7 +15,8 @@ import com.miracl.trust.util.log.Logger

internal class ComponentFactory(
private val context: Context,
private val logger: Logger
private val logger: Logger,
private val deviceTagProvider: DeviceTagProvider
) {
private val crypto: Crypto = Crypto(logger)

Expand All @@ -25,7 +27,8 @@ internal class ComponentFactory(
authenticator: AuthenticatorContract,
verificationApi: VerificationApi,
userStorage: UserStorage
): Verificator = Verificator(authenticator, verificationApi, userStorage, logger)
): Verificator =
Verificator(authenticator, verificationApi, userStorage, logger, deviceTagProvider)

fun createRegistrator(
registrationApi: RegistrationApi,
Expand All @@ -35,7 +38,8 @@ internal class ComponentFactory(
registrationApi,
crypto,
userStorage,
logger
logger,
deviceTagProvider
)

fun createAuthenticator(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.annotation.VisibleForTesting
import com.miracl.trust.MIRACLError
import com.miracl.trust.MIRACLResult
import com.miracl.trust.MIRACLSuccess
import com.miracl.trust.core.DeviceTagProvider
import com.miracl.trust.crypto.Crypto
import com.miracl.trust.crypto.CryptoException
import com.miracl.trust.crypto.SigningKeyPair
Expand Down Expand Up @@ -35,7 +36,8 @@ internal class Registrator(
private val registrationApi: RegistrationApi,
private val crypto: Crypto,
private val userStorage: UserStorage,
private val logger: Logger
private val logger: Logger,
private val deviceTagProvider: DeviceTagProvider
) : RegistratorContract {
companion object {
internal const val MIN_PIN_LENGTH = 4
Expand Down Expand Up @@ -74,7 +76,8 @@ internal class Registrator(
deviceName = deviceName.trim(),
activationToken = activationToken.trim(),
pushToken = pushNotificationsToken,
publicKey = signingKeyPair.publicKey.toHexString()
publicKey = signingKeyPair.publicKey.toHexString(),
deviceTag = deviceTagProvider.get()
)

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ internal data class RegisterRequestBody(
@SerialName("deviceName") val deviceName: String,
@SerialName("activationToken") val activationToken: String,
@SerialName("pushToken") val pushToken: String? = null,
@SerialName("publicKey") val publicKey: String
@SerialName("publicKey") val publicKey: String,
@SerialName("deviceTag") val deviceTag: String
)

@Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ internal data class QuickCodeVerificationResponse(
@Serializable
internal data class ConfirmationRequestBody(
val userId: String,
val code: String
val code: String,
val deviceTag: String
)

@Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.miracl.trust.MIRACLSuccess
import com.miracl.trust.authentication.AuthenticationException
import com.miracl.trust.authentication.AuthenticatorContract
import com.miracl.trust.authentication.AuthenticatorScopes
import com.miracl.trust.core.DeviceTagProvider
import com.miracl.trust.delegate.PinProvider
import com.miracl.trust.model.QuickCode
import com.miracl.trust.model.User
Expand All @@ -21,7 +22,8 @@ internal class Verificator(
private val authenticator: AuthenticatorContract,
private val verificationApi: VerificationApi,
private val userStorage: UserStorage,
private val logger: Logger
private val logger: Logger,
private val deviceTagProvider: DeviceTagProvider
) {
suspend fun sendVerificationEmail(
userId: String,
Expand Down Expand Up @@ -133,8 +135,9 @@ internal class Verificator(
}

val confirmationRequestBody = ConfirmationRequestBody(
userId,
code
userId = userId,
code = code,
deviceTag = deviceTagProvider.get()
)

logOperation(LoggerConstants.VerificatorOperations.ACTIVATION_TOKEN_REQUEST)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class MIRACLTrustUnitTest {
// Arrange
val userStorageMock = mockk<UserStorage>()
val config = Configuration.Builder(projectId, projectUrl)
.componentFactory(componentFactoryMock)
.deviceName(deviceName)
.userStorage(userStorageMock)
.build()
Expand Down Expand Up @@ -173,7 +174,11 @@ class MIRACLTrustUnitTest {
@Test
fun `createInstance creates configuration when there isn't any`() = runTest {
// Arrange
val configuration = Configuration.Builder().deviceName(deviceName).build()
val configuration = Configuration.Builder()
.componentFactory(componentFactoryMock)
.deviceName(deviceName)
.build()

val configurationFactory = mockk<ConfigurationFactory>()
every { configurationFactory.create() } returns configuration

Expand Down Expand Up @@ -333,6 +338,7 @@ class MIRACLTrustUnitTest {
val userStorageMock = mockk<UserStorage>()
val config = Configuration.Builder(projectId, projectUrl)
.deviceName(deviceName)
.componentFactory(componentFactoryMock)
.userStorage(userStorageMock)
.build()

Expand All @@ -358,6 +364,7 @@ class MIRACLTrustUnitTest {
every { userStorageMock.all() } returns listOf()

val config = Configuration.Builder(projectId, projectUrl)
.componentFactory(componentFactoryMock)
.deviceName(deviceName)
.build()

Expand Down
Loading
Loading