auth0 / Auth0.Android

Android toolkit for Auth0 API
https://auth0.com
MIT License
208 stars 129 forks source link

Option to pass headerInfo: Map<String, String> as a parameter for getCredentials method of CredentialsManager & addHeader for reneweAuth request #698

Closed AnilKrishna closed 7 months ago

AnilKrishna commented 8 months ago

Checklist

Describe the problem you'd like to have solved

We have specific requirements to set custom user agent in the header. So while login we simply do the following -

    fun login(
        activity: FragmentActivity,
        loginFailureCallback: (Throwable?) -> Unit,
        loginSuccessCallback: (TokenServiceCredentials) -> Unit
    ) {
        WebAuthProvider.login(auth0)
            .withScheme(credentials.scheme)
            .withAudience(credentials.audience)
            .withScope(credentials.scope)
            .withParameters(
                mapOf(
                    "realm" to credentials.realm,
                    "platform" to credentials.platform,
                    "is_app" to "true",
                    "prompt" to "login",
                    "is-android" to "true"
                )
            )
            .withHeaders(
                mapOf(
                    "user-agent" to credentials.userAgent
                )
            )  and so on.....

For token renewals we are using Credentials manager's getCredentials to check token validity and renew accordingly. For renewing we need refreshToken (i.e - apiClient.renewAuth(refresh-token)). So when we look for the refresh token using getCredentials, it internally tries to renew the credentials -

https://github.com/auth0/Auth0.Android/blob/873989cf712e2308a8c4327198a0cd3b7c7454df/auth0/src/main/java/com/auth0/android/authentication/storage/CredentialsManager.kt#L237

This is resulting in Access Denied error from our server due to a default user agent (i.e example - okhttp/4.9.3 ) in the request header. So we need a provision to pass and set custom user agent when we renew the token inside getCredentials method just like addParameter.

Describe the ideal solution

If we can modify the current getCredentials from

    public fun getCredentials(
        scope: String?,
        minTtl: Int,
        parameters: Map<String, String>,
        forceRefresh: Boolean,
        callback: Callback<Credentials, CredentialsManagerException>
    ) {

to

    public fun getCredentials(
        scope: String?,
        minTtl: Int,
        parameters: Map<String, String>,
        header: Map<String, String>,
        forceRefresh: Boolean,
        callback: Callback<Credentials, CredentialsManagerException>
    ) { .....

            // Set custom user agent in the request header 
            val request = authenticationClient.renewAuth(refreshToken)
            request.addParameters(parameters)
            request.addHeader(header)
            if (scope != null) {
                request.addParameter("scope", scope)
            }

           try {
                val fresh = request.execute()
                val expiresAt = fresh.expiresAt.time
                and so on ......

This would enable us to set the custom user agent before executing the request.

Alternatives and current workarounds

Currently we don't have much of an alternative from app side. The restrictions are on the server side. A possible workaround could be whitelisting the user agent okhttp/{version} on the server side. However, we are not entirely sure about the security considerations from our platform team here. I have raised this with them as well internally.

Additional context

No response

poovamraj commented 7 months ago

Hi @AnilKrishna, we have implemented this feature and merged it to master. This will be added in our next release. We will close this issue now but feel free to comment here and we can reopen it if required.

AnilKrishna commented 7 months ago

Thank you very much @poovamraj. You're Legend mate. I will look forward to the changes in the next release. Cheers.