Docs
Try Apollo Studio

Authenticate your operations


Authentication is not included in the GraphQL specification. This page aims at giving some guidance for the most common scenarios but doesn't pretend to be exhaustive.

Authenticating your HTTP requests with OkHttp

OkHttp Interceptors are an easy way to add an "Authorization" header to your HTTP requests.

OkHttp Interceptors have been around for a long time and work well but only work on Android and the JVM.

Authenticating your HTTP requests with Apollo HttpInterceptor

In order to authenticate your HTTP requests in a multi-platform way, you can use an Apollo HttpInterceptor.

HttpInterceptor is multiplatform and uses an API very similar to OkHttp's:

class AuthorizationInterceptor() : HttpInterceptor {
private val mutex = Mutex()
override suspend fun intercept(request: HttpRequest, chain: HttpInterceptorChain): HttpResponse {
var token = mutex.withLock {
// get current token
}
val response = chain.proceed(request.newBuilder().addHeader("Authorization", "Bearer $token").build())
return if (response.statusCode == 401) {
token = mutex.withLock {
// get new token
}
chain.proceed(request.newBuilder().addHeader("Authorization", "Bearer $token").build())
} else {
response
}
}
}

For a more advanced example, you can take a look at the AuthorizationInterceptor integration tests

Authenticating your WebSockets

Authenticating WebSockets is typically handled with a specific connection payload:

val apolloClient = ApolloClient.Builder()
.httpServerUrl("http://localhost:8080/graphql")
.webSocketServerUrl("http://localhost:8080/subscriptions")
.wsProtocol(
SubscriptionWsProtocol.Factory(
connectionPayload = {
// some servers use "authorization" directly
mapOf("authorization" to token)
// others require to wrap in a "headers" map
mapOf("headers" to mapOf("authorization" to token))
// others will expect different maps
// refer to your backend docs for the actual map to use
}
)
)
.build()

Alternatively, you can also send headers in the initial WebSocket handshake request:

val apolloClient = ApolloClient.Builder()
.httpServerUrl("http://localhost:8080/graphql")
.subscriptionNetworkTransport(
WebSocketNetworkTransport.Builder()
.serverUrl("http://localhost:8080/subscriptions")
.addHeader("Authorization", authorization)
.build()
)
.build()

Updating your WebSocket token

When using authenticated subscriptions over WebSockets, you might want to refresh your authentication token because it was invalidated or simply because it expired.

Note: if your user logged out, you might want to consider creating a new ApolloClient instead. This will make sure that all other state besides the WebSocket, like cache for an example, is new and not shared amongst different users.

Sometimes the websocket will emit an error that you can use in webSocketReopenWhen to create a new WebSocket. Other times that information will come from elsewhere in your app and you will have to force disconnect the WebSocket.

First define your own Exception:

class WebSocketReconnectException: Exception("The WebSocket needs to be reopened")
val apolloClient = ApolloClient.Builder()
.httpServerUrl("http://localhost:8080/graphql")
.webSocketServerUrl("http://localhost:8080/subscriptions")
.wsProtocol(
SubscriptionWsProtocol.Factory(
connectionPayload = {
// the connection_init payload
// This is an example. You will most likely have to tweak it for your backend
mapOf("Authorization" to token)
}
)
)
.webSocketReopenWhen { e, attempt ->
if (e is WebSocketReconnectException) {
true
} else {
// Another WebSocket error happened, decide what to do with it
// Here we're trying to reconnect at most 3 times
attempt < 3
}
}
.build()

When you need to reopen the WebSocket, call closeConnection:

apolloClient.subscriptionNetworkTransport.closeConnection(WebSocketReconnectException())`

The WebSocket will close and reopen with a fresh new connectionPayload.

Edit on GitHub
Previous
Using the models without apollo-runtime
Next
WebSocket errors