Create AuthInterceptor.kt — the token on every call
In the code column — AuthInterceptor.kt. It implements the Interceptor interface: intercept() receives every request, checks the path, and if it's not public — adds Authorization: Bearer <token>. The token comes from TokenStorage (lesson 8a).
Now the interceptor needs to be plugged into the network. Remember lesson 6's coreModule — it only had Retrofit and PicaApi. Now it grows to its real shape: an OkHttpClient with the interceptor, and Retrofit uses it:
// coreModule — add OkHttp with auth
single<OkHttpClient> {
OkHttpClient.Builder()
.addInterceptor(AuthInterceptor(get())) // get() = TokenStorage (8a)
.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY // see requests in Logcat
})
.build()
}
single<Retrofit> {
Retrofit.Builder()
.baseUrl("http://10.0.2.2:8080/")
.client(get()) // ← use the OkHttp with auth
.addConverterFactory(get<Json>().asConverterFactory("application/json".toMediaType()))
.build()
}
One line — .client(get()) — and every Retrofit request now goes through the interceptor. No ViewModel or repository changes.
Verify. Log in, then in Logcat (HttpLoggingInterceptor) look at a protected request — you should see the header:
--> GET http://10.0.2.2:8080/orders
Authorization: Bearer eyJhbGciOi...
While --> POST http://10.0.2.2:8080/login has no such header — because it's a public path.
Gotcha (chicken and egg). If the interceptor doesn't exclude
/loginand/register, it will try to attach a token to the login request too. But at login there's no token yet (or it's expired) — and the server returns 401. Result: you can't log in to get a token, because logging in requires... a token. A vicious cycle. That's why thepublicPathslist is mandatory — it lets these paths through without the header.