Updated on 2026-08-14
This commit is contained in:
parent
0b3914cf6a
commit
7581e22ee7
19 changed files with 784 additions and 74 deletions
|
|
@ -89,19 +89,19 @@ dependencies {
|
|||
/** Coroutines */
|
||||
implementation(deps.kotlin.coroutines)
|
||||
implementation(deps.kotlin.coroutines.rx2)
|
||||
implementation(deps.kotlin.datetime)
|
||||
implementation(deps.kotlin.serialization)
|
||||
api(deps.kotlin.datetime)
|
||||
api(deps.kotlin.serialization)
|
||||
|
||||
/** Logging */
|
||||
|
||||
/** Network */
|
||||
implementation(deps.moshi)
|
||||
api(deps.moshi)
|
||||
implementation(deps.moshi.kotlin)
|
||||
implementation(deps.moshi.adapters)
|
||||
implementation(deps.moshi.adapters.ext)
|
||||
implementation(deps.okHttp)
|
||||
api(deps.okHttp)
|
||||
implementation(deps.okHttp.prettyLogging)
|
||||
implementation(deps.retrofit)
|
||||
api(deps.retrofit)
|
||||
implementation(deps.retrofit.moshi)
|
||||
ksp(deps.moshi.kotlin.codegen)
|
||||
kaptForObfuscatingVariants(deps.retrofit.response.type.keeper)
|
||||
|
|
@ -120,7 +120,7 @@ dependencies {
|
|||
releaseImplementation(deps.chuckerStub)
|
||||
|
||||
/** Local storages */
|
||||
implementation(deps.androidx.datastore)
|
||||
api(deps.androidx.datastore)
|
||||
implementation(deps.room.runtime)
|
||||
implementation(deps.room.ktx)
|
||||
ksp(deps.room.compiler)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.datasource.api.auth
|
|||
import com.tangem.datasource.api.auth.models.request.AuthApiRequest
|
||||
import com.tangem.datasource.api.auth.models.request.NonceApiRequest
|
||||
import com.tangem.datasource.api.auth.models.request.RefreshApiRequest
|
||||
import com.tangem.datasource.api.auth.models.request.RegisterApiRequest
|
||||
import com.tangem.datasource.api.auth.models.response.NonceApiResponse
|
||||
import com.tangem.datasource.api.auth.models.response.TokenApiResponse
|
||||
import com.tangem.datasource.api.common.response.ApiResponse
|
||||
|
|
@ -14,6 +15,24 @@ import retrofit2.http.POST
|
|||
*/
|
||||
interface AuthApi {
|
||||
|
||||
/**
|
||||
* Request device registration nonce.
|
||||
*
|
||||
* Generates a nonce bound to the device public key for the device registration flow.
|
||||
*/
|
||||
@POST("api/v1/auth/nonce/device")
|
||||
suspend fun requestDeviceNonce(@Body request: NonceApiRequest): ApiResponse<NonceApiResponse>
|
||||
|
||||
/**
|
||||
* Register device.
|
||||
*
|
||||
* Registers a new device using its hardware-backed public key and issues the initial
|
||||
* session token pair. Called once per app install.
|
||||
*/
|
||||
@POST("api/v1/auth/register")
|
||||
@RequiresDpopProof
|
||||
suspend fun register(@Body request: RegisterApiRequest): ApiResponse<TokenApiResponse>
|
||||
|
||||
/**
|
||||
* Request authentication nonce.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -23,24 +23,4 @@ data class AuthenticationPayload(
|
|||
@Json(name = "attestationToken") val attestationToken: String?,
|
||||
/** Client-reported device metadata. */
|
||||
@Json(name = "metadata") val metadata: DeviceMetadata,
|
||||
) {
|
||||
|
||||
/** Device metadata collection. */
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DeviceMetadata(
|
||||
/** Device hardware model (e.g. `iPhone 15 Pro`). */
|
||||
@Json(name = "deviceModel") val deviceModel: String?,
|
||||
/** Operating system (`android` / `ios`). */
|
||||
@Json(name = "os") val os: String,
|
||||
/** OS version string (e.g. `17.4.1`). */
|
||||
@Json(name = "osVersion") val osVersion: String?,
|
||||
/** Application version (e.g. `5.8.0`). */
|
||||
@Json(name = "appVersion") val appVersion: String?,
|
||||
/** User-Agent header (e.g. `Tangem/5.8.0 (iPhone; iOS 17.4.1; Scale/3.00)`). */
|
||||
@Json(name = "userAgent") val userAgent: String?,
|
||||
/** Client locale (e.g. `en-US`). */
|
||||
@Json(name = "locale") val locale: String?,
|
||||
/** Client timezone (e.g. `Europe/Moscow`). */
|
||||
@Json(name = "timezone") val timezone: String?,
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package com.tangem.datasource.api.auth.models.request
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Client-reported device metadata, included in both [AuthenticationPayload] and [RegisterPayload].
|
||||
* Mirrors the `DeviceMetadata` schema in the backend OpenAPI contract.
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DeviceMetadata(
|
||||
/** Device hardware model (e.g. `iPhone 15 Pro`). */
|
||||
@Json(name = "deviceModel") val deviceModel: String?,
|
||||
/** Operating system (`android` / `ios`). */
|
||||
@Json(name = "os") val os: String,
|
||||
/** OS version string (e.g. `17.4.1`). */
|
||||
@Json(name = "osVersion") val osVersion: String?,
|
||||
/** Application version (e.g. `5.8.0`). */
|
||||
@Json(name = "appVersion") val appVersion: String?,
|
||||
/** User-Agent header (e.g. `Tangem/5.8.0 (iPhone; iOS 17.4.1; Scale/3.00)`). */
|
||||
@Json(name = "userAgent") val userAgent: String?,
|
||||
/** Client locale (e.g. `en-US`). */
|
||||
@Json(name = "locale") val locale: String?,
|
||||
/** Client timezone (e.g. `Europe/Moscow`). */
|
||||
@Json(name = "timezone") val timezone: String?,
|
||||
)
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.tangem.datasource.api.auth.models.request
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* Registration request — registers a new device and establishes initial trust.
|
||||
*
|
||||
* Posted to `POST /api/v1/auth/register`; on success the server returns
|
||||
* [com.tangem.datasource.api.auth.models.response.TokenApiResponse] (the initial session token pair).
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RegisterApiRequest(
|
||||
/** Signed registration payload. */
|
||||
@Json(name = "payload") val payload: RegisterPayload,
|
||||
/** EC signature over the registration payload, signed by the device private key (Base64). */
|
||||
@Json(name = "signature") val signature: String,
|
||||
)
|
||||
|
||||
/** Signed registration payload — the data that is signed by the device private key. */
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RegisterPayload(
|
||||
/** Base64-encoded EC public key of the device. */
|
||||
@Json(name = "devicePublicKey") val devicePublicKey: String,
|
||||
/** Deciphered nonce value from the `/api/v1/auth/nonce/device` endpoint. */
|
||||
@Json(name = "nonce") val nonce: String,
|
||||
/** Platform attestation token (Play Integrity / App Attest). Optional; backend accepts `null`. */
|
||||
@Json(name = "attestationToken") val attestationToken: String?,
|
||||
/** Client-reported device metadata. */
|
||||
@Json(name = "metadata") val metadata: DeviceMetadata,
|
||||
)
|
||||
|
|
@ -103,6 +103,8 @@ object PreferencesKeys {
|
|||
|
||||
val IS_GOOGLE_PAY_AVAILABLE_KEY by lazy { booleanPreferencesKey(name = "isGooglePayAvailable") }
|
||||
|
||||
val IS_DEVICE_REGISTERED_KEY by lazy { booleanPreferencesKey(name = "isDeviceRegistered") }
|
||||
|
||||
val WAS_LOG_FILE_CLEARED by lazy { booleanPreferencesKey(name = "wasLogFileCleared") }
|
||||
|
||||
val SEED_FIRST_NOTIFICATION_SHOW_TIME by lazy { longPreferencesKey("seedFirstNotificationTime") }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue