It seems that ktor client auth doesn’t work on WAS...
# ktor
m
It seems that ktor client auth doesn’t work on WASM yet (using BearerTokens). I tried using 3.0.1-eap-1121 but doesn’t work either. Are they any plans to support WASM for auth? Or is there some extra setting or something I need to configure specifically to support WASM? It works on android and ios but not on WASM for me.
a
Is it about WASM executed in the browser environment?
👍 1
m
yep.
a
Unfortunately, the Bearer Auth doesn't work in a browser environment (JS and WASM targets) because it sends the
Authorization
header, which isn't allowed to be managed directly.
👍 1
m
what do you mean it isn’t allowed to be managed directly? I can manually add the header and it works. why does it matter if the plugin sets the header?
also the serialization/deserialization doesn’t work in WASM either and has to be done manually.
was hoping both these things would be solved in a coming release so I don’t have to have workarounds just to support WASM.
I really love the WASM target though. so great to be able to publish to web as well.
a
Sorry, I was wrong. The
Authorization
header can be sent through the Fetch API. Can you describe the exact problem which occurs while using the
Auth
plugin?
m
I was following https://ktor.io/docs/client-bearer-auth.html. If I do this it works just fine for android and ios. but for WASM I get 401 error.
Copy code
install(Auth) {
    bearer {
        loadTokens {
            // Load tokens from a local storage and return them as the 'BearerTokens' instance
            BearerTokens("abc123", "xyz111")
        }
    }
}
The call looks like this:
Copy code
val response: HttpResponse = client.get("https://<API>") {
//                    header("Authorization", "Bearer $accessToken")
                }
If I set the bearer using the Auth plugin as above I can comment/remove the Authorization header line and it will work on ios and android but for WASM I will get a 401. If I keep this line then WASM works fine too. The bigger problem though is that I can’t take advantage of the refresh tokens block and I have to manually handle refreshing for every API call which adds a lot of complexity.
Copy code
install(Auth) {
    bearer {
        // Load tokens ...
        refreshTokens { // this: RefreshTokensParams
            // Refresh tokens and return them as the 'BearerTokens' instance
            BearerTokens("def456", "xyz111")
        }
    }
}
In terms of serialize/deserialize not working in WASM I mean like this:
Copy code
// Get bodyAsText and manual decodeFromString since deserialization doesn't seem to work properly yet on WASM
val responseBody = response.bodyAsText()
val someObject = Json.decodeFromString<SomeObject>(responseBody)
// this doesn't currently work on WASM
// val someObject: SomeObject = response.body()
Again it works fine on ios and android if I use that last line instead but on WASM I get this error: An unexpected error occurred: NoTransformationFoundException: Expected response body of the type ‘class SomeObject’ but was ‘class SourceByteReadChannel’
a
Unfortunately, I cannot reproduce the Bearer Authentication problem with the following code:
Copy code
GlobalScope.launch {
    val client = HttpClient {
        install(Auth) {
            bearer {
                loadTokens {
                    BearerTokens("", "")
                }

                refreshTokens {
                    println("Refreshing...")
                    BearerTokens("token", "token")
                }
            }
        }
    }

    val response = client.get("<https://httpbin.org/bearer>")
    println(response.bodyAsText())
}
You can find a sample project attached.
😲 1
m
ok I got mine to work too now. it seems that using platform specific HttpClients breaks it. When I initially created the project at least one of them didn’t work with the default CIO so I did platform specific. Maybe something changed in ktor 3.0.0? I still think it should work with platform specific clients and perhaps you can reproduce if you try that. But good news is that the default works for all of them now which is actually simpler anyway. Thanks for your help!
even the serialization/deserialization works now too using the default engine for all platofrms. so maybe something wrong with the Js engine.
or at least maybe the Js engine doesn’t support WASM yet but CIO does.
doesn’t seem like I can add the CIO engine only for WASM though.
Oh and another thing. I was trying to get websockets working today and it also wouldn’t work on WASM for some reason. Kept getting “IllegalStateException: Plugin Plugin@1038825240 is not installed. Consider using ’install(AttributeKey: Websocket) composeApp-uninstantiated.mjs: 185 in client config first.” I had the plugin installed and it was working on android. I didn’t work on ios either but not sure why. However I just tried it using default engine and it worked!
and also ios works too with default engine!
so seems Js engine not working on multiple things (Auth, Serialzation/Deserialization, Websockets). and Darwin engine not working on websockets. but there is a nice workaround which is to just use the default multiplatform engine and all is well. great news. Thanks for your help!
something interesting I found also is that I still need the platform specific dependencies otherwise it doesn’t work. Maybe the configuration is handled automatically now so we don’t need to configure it for each platform? Anyway if I do configure it manually it breaks it. Using expect/actual I mean. That was the normal way before. But not sure if it’s using the platform specific engines why it would matter how I setup the client.
a
or at least maybe the Js engine doesn’t support WASM yet but CIO does
The CIO engine doesn't support the WASM target.
Maybe the configuration is handled automatically now so we don’t need to configure it for each platform?
Yes. If there are respective dependencies in place and the engine isn't passed to the
HttpClient
constructor, the engine will be resolved automatically based on the platform.
👍 1