Skip to content

Expose Guardian.getAPIClient() function to make it available for updating device push notification token #132

@ronintran

Description

@ronintran

Describe the problem you'd like to have solved

To update the device's push token, we need to use the GuardianAPIClient.device().update() function. But unfortunately, the Guardian.getAPIClient() is not exposed. So we can't update the device's push token. While iOS SDk does expose the same thing at Guardian.api(...).
As a result, after the user enrolled into 2FA push notification, It worked until their device's push notification token had been expired/invalid, then it got refreshed. The user got blocked at 2FA challenge screen because of failed to send 2FA Push Notification to Android devices.

Describe the ideal solution

Add the public modifier at the function Guardian.getAPIClient()

public GuardianAPIClient getAPIClient() {
   return guardianAPIClient;
}

Alternatives and current work-arounds

Build the GuardianAPIClient by ourself manually instead of getting it from Guardian class, but it is not ideal solution and it's not safe in the future when the Guardian Android SDK has newer versions, It doesn't guarantee that ourself built GuardianAPIClient still works

    private val guardianApiClient: GuardianAPIClient by lazy {
        val clientInfo = ClientInfo()
        val okHttpClient = provideOkHttpClient(clientInfo)
        val requestFactory = provideRequestFactory(okHttpClient)

        GuardianAPIClient.Builder()
            .url("your-url")
            .setClientInfo(clientInfo)
            .setRequestFactory(requestFactory)
            .build()
    }

    private fun provideOkHttpClient(clientInfo: ClientInfo): OkHttpClient {
        val builder = OkHttpClient.Builder()
        val encodedClientInfo: String = clientInfo.toBase64()

        builder.addInterceptor(object : Interceptor {
            @Throws(IOException::class)
            override fun intercept(chain: Interceptor.Chain): Response {
                val originalRequest = chain.request()
                val requestWithUserAgent = originalRequest.newBuilder()
                    .header("Accept-Language", Locale.getDefault().toString())
                    .header(
                        "User-Agent",
                        String.format(
                            "GuardianSDK/%s Android %s",
                            BuildConfig.VERSION_NAME,
                            Build.VERSION.RELEASE,
                        ),
                    )
                    .header("Auth0-Client", encodedClientInfo)
                    .build()
                return chain.proceed(requestWithUserAgent)
            }
        })

        return builder.build()
    }

    private fun provideRequestFactory(okHttpClient: OkHttpClient): RequestFactory {
        val gson = GsonBuilder().create()
        return RequestFactory(gson, okHttpClient)
    }

    fun ClientInfo.toJson(): String {
        val gson = GsonBuilder().create()
        return gson.toJson(this)
    }

    fun ClientInfo.toBase64(): String {
        val bytes: ByteArray = this.toJson().toByteArray()
        return Base64.encodeToString(
            bytes,
            Base64.URL_SAFE or Base64.NO_WRAP or Base64.NO_PADDING,
        )
    }

Additional context

It is causing ~20% failed of sending 2FA push notification from Auth0's logs and keep increasing.

{
  "type": "gd_send_pn_failure",
  "description": "Guardian - There was an error sending the push notification",
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions