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
10 changes: 10 additions & 0 deletions universal_components/consumer-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,14 @@
-keep public enum com.auth0.universalcomponents.domain.model.AuthenticatorType {
**[] $VALUES;
public *;
}

# --- Strip verbose SDK logging from minified consumer builds -----------------
# Errors (e) and warnings (w) are intentionally kept so field failures stay
# diagnosable in release builds. These three have no default args, so a single
# void d(...) matches every overload — no $default synthetic to worry about.
-assumenosideeffects class com.auth0.universalcomponents.utils.logging.Logger {
void d(...);
void i(...);
void v(...);
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.auth0.universalcomponents

import android.content.Context
import android.util.Log
import androidx.credentials.CredentialManager
import com.auth0.android.Auth0
import com.auth0.universalcomponents.token.TokenProvider
import com.auth0.universalcomponents.utils.logging.Logger
import java.util.concurrent.atomic.AtomicBoolean

/**
Expand All @@ -24,6 +24,8 @@ data class PasskeyConfiguration(

public object Auth0UniversalComponents {

private const val TAG = "Auth0UniversalComponents"

private var initialized = AtomicBoolean(false)
private lateinit var _context: Context
private lateinit var _account: Auth0
Expand Down Expand Up @@ -69,7 +71,7 @@ public object Auth0UniversalComponents {
passkeyConfiguration: PasskeyConfiguration = PasskeyConfiguration()
) {
if (initialized.get()) {
Log.d("Auth0UniversalComponents", "Auth0UniversalComponents is already initialized.")
Logger.d(TAG, "Auth0UniversalComponents is already initialized.")
return
}
_context = context.applicationContext
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.auth0.universalcomponents.data

import android.util.Log
import androidx.annotation.VisibleForTesting
import com.auth0.android.result.APICredentials
import com.auth0.universalcomponents.Auth0UniversalComponents
import com.auth0.universalcomponents.utils.logging.Logger
import java.util.concurrent.ConcurrentHashMap

/**
Expand Down Expand Up @@ -51,12 +51,12 @@ class TokenManager private constructor() {
val cachedCredentials = tokenMap[cacheKey(audience, scope)]
if (cachedCredentials != null) {
if (!willTokenExpire(cachedCredentials.expiresAt.time)) {
Log.d(TAG, "Returning cached token for audience: $audience, scope: $scope")
Logger.d(TAG, "Returning cached token for audience: $audience, scope: $scope")
return cachedCredentials.accessToken
}
}

Log.d(TAG, "Fetching new token from provider for audience: $audience, scope: $scope")
Logger.d(TAG, "Fetching new token from provider for audience: $audience, scope: $scope")
val credentials = tokenProvider.fetchApiCredentials(audience, scope)

// Saving the same token for scenario where we request multiple scopes together
Expand All @@ -79,7 +79,7 @@ class TokenManager private constructor() {
val splitScope = scope.split(" ")
if (splitScope.size > 1) {
splitScope.forEach {
Log.d(TAG, "token:$it ")
Logger.d(TAG, "Caching token for scope: $it")
tokenMap[cacheKey(audience, it)] = credentials
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.auth0.universalcomponents.presentation.ui.mfa

import android.util.Log
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
Expand Down Expand Up @@ -44,6 +43,7 @@ import com.auth0.universalcomponents.presentation.viewmodel.EnrollmentUiState
import com.auth0.universalcomponents.presentation.viewmodel.EnrollmentViewModel
import com.auth0.universalcomponents.theme.Auth0Theme
import com.auth0.universalcomponents.utils.ValidationUtil
import com.auth0.universalcomponents.utils.logging.Logger

@OptIn(ExperimentalMaterial3Api::class)
@Composable
Expand Down Expand Up @@ -80,7 +80,7 @@ internal fun EmailEnrollmentScreen(
}

is EnrollmentEvent.VerificationSuccess -> {
Log.d("EmailEnrollmentScreen", "$event not handled ")
Logger.d("EmailEnrollmentScreen", "${event::class.simpleName} not handled")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.auth0.universalcomponents.presentation.ui.mfa

import android.util.Log
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
Expand Down Expand Up @@ -57,6 +56,7 @@ import com.auth0.universalcomponents.presentation.viewmodel.EnrollmentEvent
import com.auth0.universalcomponents.presentation.viewmodel.EnrollmentUiState
import com.auth0.universalcomponents.presentation.viewmodel.EnrollmentViewModel
import com.auth0.universalcomponents.theme.Auth0Theme
import com.auth0.universalcomponents.utils.logging.Logger

@OptIn(ExperimentalMaterial3Api::class)
@Composable
Expand Down Expand Up @@ -94,7 +94,7 @@ internal fun OTPVerificationScreen(
ObserveAsEvents(viewModel.events) { event ->
when (event) {
is EnrollmentEvent.EnrollmentChallengeSuccess -> {
Log.d("OTPVerificationScreen", "EnrollmentChallengeSuccess not handled ")
Logger.d("OTPVerificationScreen", "EnrollmentChallengeSuccess not handled ")
}

is EnrollmentEvent.VerificationSuccess -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.auth0.universalcomponents.presentation.ui.mfa

import android.graphics.Bitmap
import android.util.Log
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
Expand Down Expand Up @@ -70,10 +69,13 @@ import com.auth0.universalcomponents.presentation.viewmodel.EnrollmentEvent
import com.auth0.universalcomponents.presentation.viewmodel.EnrollmentUiState
import com.auth0.universalcomponents.presentation.viewmodel.EnrollmentViewModel
import com.auth0.universalcomponents.theme.Auth0Theme
import com.auth0.universalcomponents.utils.logging.Logger
import com.google.zxing.BarcodeFormat
import com.google.zxing.WriterException
import com.google.zxing.qrcode.QRCodeWriter

private const val TAG = "QREnrollmentScreen"

@Composable
internal fun QREnrollmentScreen(
authenticatorType: AuthenticatorType,
Expand Down Expand Up @@ -533,7 +535,7 @@ private fun generateQRCode(
val bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, size, size)
createQRBitmap(bitMatrix, qrCodeColor, qrBackgroundColor)
} catch (e: WriterException) {
Log.e("TAG", "Failed to generate QR code", e)
Logger.e(TAG, "Failed to generate QR code", e)
null
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.auth0.universalcomponents.presentation.ui.mfa

import android.util.Log
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
Expand Down Expand Up @@ -51,6 +50,7 @@ import com.auth0.universalcomponents.presentation.viewmodel.EnrollmentEvent
import com.auth0.universalcomponents.presentation.viewmodel.EnrollmentUiState
import com.auth0.universalcomponents.presentation.viewmodel.EnrollmentViewModel
import com.auth0.universalcomponents.theme.Auth0Theme
import com.auth0.universalcomponents.utils.logging.Logger
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch

Expand Down Expand Up @@ -88,7 +88,7 @@ internal fun RecoveryCodeEnrollmentScreen(
event.authenticationMethod.id,
event.authenticationMethod.type
)
Log.d("EmailEnrollmentScreen", "$event not handled ")
Logger.d("RecoveryCodeEnrollmentScreen", "${event::class.simpleName} not handled")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.auth0.universalcomponents.presentation.ui.mfa.phone

import android.util.Log
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
Expand Down Expand Up @@ -58,6 +57,7 @@ import com.auth0.universalcomponents.presentation.viewmodel.EnrollmentUiState
import com.auth0.universalcomponents.presentation.viewmodel.EnrollmentViewModel
import com.auth0.universalcomponents.theme.Auth0Theme
import com.auth0.universalcomponents.utils.ValidationUtil
import com.auth0.universalcomponents.utils.logging.Logger

@OptIn(ExperimentalMaterial3Api::class)
@Composable
Expand Down Expand Up @@ -90,7 +90,7 @@ internal fun PhoneEnrollmentScreen(
}

is EnrollmentEvent.VerificationSuccess -> {
Log.d("PhoneEnrollmentScreen", "$event not handled ")
Logger.d("PhoneEnrollmentScreen", "${event::class.simpleName} not handled")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.auth0.universalcomponents.presentation.ui.passkeys

import android.util.Log
import androidx.credentials.exceptions.CreateCredentialCancellationException
import androidx.credentials.exceptions.CreateCredentialException
import androidx.credentials.exceptions.CreateCredentialInterruptedException
Expand All @@ -12,6 +11,7 @@ import com.auth0.universalcomponents.domain.error.Auth0Error
import com.auth0.universalcomponents.domain.model.PublicKeyCredentials
import com.auth0.universalcomponents.domain.repository.MyAccountRepository
import com.auth0.universalcomponents.presentation.ui.UiError
import com.auth0.universalcomponents.utils.logging.Logger
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
Expand Down Expand Up @@ -161,7 +161,7 @@ class PasskeyViewModel(
}

else -> {
Log.w(TAG, "Unexpected exception type ${exception::class.java.name}")
Logger.w(TAG, "Unexpected exception type ${exception::class.java.name}")
Auth0Error.PasskeyError(
"An error occurred when creating a passkey: ${exception.message ?: "Unknown error"}",
exception,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.auth0.universalcomponents.presentation.viewmodel

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.auth0.android.result.AuthenticationMethod
Expand All @@ -15,6 +14,7 @@ import com.auth0.universalcomponents.domain.usecase.EnrollAuthenticatorUseCase
import com.auth0.universalcomponents.domain.usecase.GetUserInfoUseCase
import com.auth0.universalcomponents.domain.usecase.VerifyAuthenticatorUseCase
import com.auth0.universalcomponents.presentation.ui.UiError
import com.auth0.universalcomponents.utils.logging.Logger
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
Expand Down Expand Up @@ -84,7 +84,7 @@ class EnrollmentViewModel(
}

else -> {
Log.d(TAG, "No need to fetch the data during initialization")
Logger.d(TAG, "No need to fetch the data during initialization")
}
}
}
Expand All @@ -99,7 +99,7 @@ class EnrollmentViewModel(
}
enrollAuthenticatorUseCase(authenticatorType, input)
.onSuccess { enrollmentResult ->
Log.d(TAG, "Enrollment initiated successfully")
Logger.d(TAG, "Enrollment initiated successfully")

val (authMethodId, authSession) = when (enrollmentResult) {
is EnrollmentResult.RecoveryCodeEnrollment ->
Expand Down Expand Up @@ -146,7 +146,7 @@ class EnrollmentViewModel(
_uiState.update {
it.copy(verifyingAuthenticator = true)
}
Log.d(TAG, "Verifying with OTP")
Logger.d(TAG, "Verifying with OTP")

val input = VerificationInput.WithOtp(
authenticationMethodId = authenticationMethodId,
Expand All @@ -156,15 +156,15 @@ class EnrollmentViewModel(

verifyAuthenticatorUseCase(input)
.onSuccess { authenticationMethod ->
Log.d(TAG, "Verification successful")
Logger.d(TAG, "Verification successful")

_uiState.update {
EnrollmentUiState()
}
eventChannel.send(EnrollmentEvent.VerificationSuccess(authenticationMethod))
}
.onError { error ->
Log.e(TAG, "Verification failed", error.cause)
Logger.e(TAG, "Verification failed : ${error.message}")
when (error) {
is Auth0Error.InvalidOTP -> {
_uiState.update {
Expand Down Expand Up @@ -206,7 +206,7 @@ class EnrollmentViewModel(
_uiState.update {
EnrollmentUiState(verifyingAuthenticator = true)
}
Log.d(TAG, "Verifying without OTP")
Logger.d(TAG, "Verifying without OTP")

val input = VerificationInput.WithoutOtp(
authenticationMethodId = authenticationMethodId,
Expand All @@ -215,14 +215,14 @@ class EnrollmentViewModel(

verifyAuthenticatorUseCase(input)
.onSuccess { authenticationMethod ->
Log.d(TAG, "Verification successful")
Logger.d(TAG, "Verification successful")
_uiState.update {
EnrollmentUiState()
}
eventChannel.send(EnrollmentEvent.VerificationSuccess(authenticationMethod))
}
.onError { error ->
Log.e(TAG, "Verification failed", error.cause)
Logger.e(TAG, "Verification failed : ${error.message}")
_uiState.update {
EnrollmentUiState(
uiError = UiError(
Expand All @@ -239,11 +239,11 @@ class EnrollmentViewModel(
viewModelScope.launch {
getUserInfoUseCase()
.onSuccess { userInfo ->
Log.d(TAG, "Email prefill succeeded")
Logger.d(TAG, "Email prefill succeeded")
_uiState.update { it.copy(prefillEmail = userInfo.email.orEmpty()) }
}
.onError { error ->
Log.w(TAG, "Could not prefill email: ${error.message}")
Logger.w(TAG, "Could not prefill email: ${error.message}")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.auth0.universalcomponents.utils.logging

import android.util.Log

/**
* Lightweight, SDK-internal logging facade.
Comment thread
pacific-ring marked this conversation as resolved.
*
* All diagnostic logging inside the SDK goes through this object instead of calling
* [android.util.Log] directly. Routing every log statement through a single choke point gives us
* one consistent entry point — useful for keeping tags uniform and as the natural place to add
* redaction or gating later should a privacy requirement call for it.
*
* Logged messages must never contain sensitive values (tokens, sessions, PII); callers are
* responsible for logging only non-sensitive, debug-friendly context.
*
* ### Usage
* ```
* Logger.d(TAG, "Fetching new token for audience: $audience")
* Logger.e(TAG, "Verification failed", throwable)
* ```
*/
internal object Logger {

/** Logs a debug message. */
internal fun d(tag: String, message: String) {
Log.d(tag, message)
}

/** Logs an info message. */
internal fun i(tag: String, message: String) {
Log.i(tag, message)
}

/** Logs a verbose message. */
internal fun v(tag: String, message: String) {
Log.v(tag, message)
}

/** Logs a warning, optionally with a [throwable]. */
internal fun w(tag: String, message: String, throwable: Throwable? = null) {
Log.w(tag, message, throwable)
}

/** Logs an error, optionally with a [throwable]. */
internal fun e(tag: String, message: String, throwable: Throwable? = null) {
Log.e(tag, message, throwable)
}
}
Loading
Loading