apollographql / apollo-kotlin

:rocket:  A strongly-typed, caching GraphQL client for the JVM, Android, and Kotlin multiplatform.
https://www.apollographql.com/docs/kotlin
MIT License
3.74k stars 653 forks source link

WASM (KMP) - Adding interceptor to authenticate for all request causing blocked by CORS #6159

Open ronjunevaldoz opened 1 day ago

ronjunevaldoz commented 1 day ago

Version

4.0.0

Summary

This error only encountered on WASM but not in Android, iOS & Desktop. When I execute a query or mutation with Authorization header it gives OPTIONS request method that caused CORS blocked.

Steps to reproduce the behavior

Setup ApolloClient with custom interceptor.

Given:

ApolloClient.Builder()
        .serverUrl(serverUrl = serverUrl) 
        .addHttpInterceptor(authInterceptor)
        .httpHeaders(
            listOf(
                HttpHeader("Accept", "application/json"),
                HttpHeader("Content-Type", "application/json"),
            )
        )
        .build()
class AuthorizationInterceptor(
    private val keyValueStorage: KeyValueStorage
) : HttpInterceptor {
    private val mutex = Mutex()

    override suspend fun intercept(
        request: HttpRequest,
        chain: HttpInterceptorChain
    ): HttpResponse {
        var token = mutex.withLock {
            // get current token
            keyValueStorage.token
        }
        val response = chain.proceed(request)

        return if (response.statusCode == 401) {
            token = mutex.withLock {
                // get new token
                keyValueStorage.token
            }
            chain.proceed(request.newBuilder().addHeader("Authorization", "Bearer $token").build())
        } else {
            response
        }
    }
}

Logs

Access to fetch at 'http://localhost:8080/graphql' from origin 'http://localhost:8081' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Server logs

When Authorization header is added, the requested method became OPTIONS instead of POST (WASM only)?

Status: 403 Forbidden, HTTP method: OPTIONS, Headers: Host: [localhost:8080], Connection: [keep-alive], Accept: [*/*], Access-Control-Request-Method: [POST], Access-Control-Request-Headers: [authorization,content-type], Origin: [http://localhost:8081], User-Agent: [Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36], Sec-Fetch-Mode: [cors], Sec-Fetch-Site: [same-site], Sec-Fetch-Dest: [empty], Referer: [http://localhost:8081/], Accept-Encoding: [gzip, deflate, br, zstd], Accept-Language: [en-US,en;q=0.9]
BoD commented 5 hours ago

Hi!

This behavior is to be expected in the browser - your server needs to configure CORS and reply with the necessary Access-Control-Allow-* headers. The OPTIONS request you see is the preflight one.

ronjunevaldoz commented 3 hours ago

Hi!

This behavior is to be expected in the browser - your server needs to configure CORS and reply with the necessary Access-Control-Allow-* headers. The OPTIONS request you see is the preflight one.

Hello, Access-Control-Allow is already configured on server side (ktor server) and its working properly using Android, iOS and Desktop. The only issue is when executed uaing WASM web

BoD commented 2 hours ago

CORS is only a browser mechanism so it is expected that it doesn't impact Android and other non-browser based clients. I am not familiar with how to implement CORS with Ktor but in your log above, it looks like the results to the OPTION preflight request is 403 - I think this indicates some misconfiguration, as it should probably reply with 200 to go on.