Instruction
Understanding the Importance of Authentication
One of the key aspects of secure communication with web services is authentication. Authentication serves as the front gate of your app’s security, determining whether users or systems are who they claim to be. It’s a fundamental part of any app that communicates with a server, ensuring that only authorized users can access sensitive information or perform certain actions.
In the world of web services and APIs, authentication can take various forms. Some common methods include:
- Basic Authentication: Sending a username and password with each request.
- Token-based Authentication: Sending a secure token, often obtained after a login procedure, with each request.
- OAuth: A more complex protocol that lets an app obtain limited access to user accounts on an HTTP service.
- API Keys: Unique identifiers used to authenticate a user or an app making a request.
Each of these methods has its use cases, advantages, and considerations. The choice of authentication method depends on your app’s specific requirements and security considerations. Usually, you’ll just be fulfilling whatever authentication challenge a server sends your way.
Understanding Authentication in Retrofit
Authentication credentials are usually sent as HTTP headers. Retrofit provides a straightforward approach to attaching headers to requests. You have the following options:
- Static header: This lets you attach a static token to a request method.
- Dynamic header: Allows you to pass in a token dynamically for a specific request.
- Using interceptors: This lets you dynamically attach the authentication header with a token for multiple requests.
- Using Authenticator: Authenticator lets you react to a server’s authentication challenge.
Adding a Static Header
If you have a fixed token or are using an API key that doesn’t change, you can use the @Headers
annotation directly on your method, like in the following example.
@Headers("Authorization: Bearer example_token")
@GET("user/profile")
suspend fun getUserProfile(): UserProfile
@Headers is a Retrofit annotation that lets you specify what headers you want to add to the
annotated request. You can pass in a single string or a vararg of strings. If you pass
multiple headers with the same name, they’ll all be applied and won’t override each other.
Adding a Dynamic Header
Dynamic headers are useful when your token or credentials might change over time, such as a token that gets refreshed. Check out the following example:
@GET("user/profile")
suspend fun getUserProfile(@Header("Authorization") token: String): UserProfile
When you want to add the header dynamically, you can use @Header, passing in a string
representing the header’s name. This way, you can control which token you pass every time
you call the method, whereas, in the previous example, the token stays hard-coded in the
annotation.
Notice that in the previous example, you used @Headers — plural. But in this case, it’s @Header — singular. You can’t mix
them because you can apply @Header only to a function parameter.
Using Interceptors
An Interceptor is a mechanism that intercepts outgoing requests and incoming
responses before the rest of the app processes them. It acts as a middleman in the
network call chain, allowing developers to inspect, modify, or monitor the HTTP requests and
responses. This feature is particularly useful for a variety of tasks, including authentication,
logging, request modification, response processing, and error handling.
Types of Interceptors
You’ll find two main types of interceptors in OkHttp, as you can see in the image below:
— Application interceptors: These are invoked once per call, even if the HTTP
response is served from the cache. They’re permitted to short-circuit Chain.proceed() calls
but also to retry and make multiple calls to Chain.proceed().
Application interceptors are a good choice when you want to do some action based on the
response’s contents.
— Network interceptors: These are invoked for every intermediate response like retries or
redirects, but they aren’t invoked for cached responses. You’d usually use network
interceptors if you need to take some action based on the network state or headers. Avoid
making any app-related decisions in network interceptors.
You’ll learn how to add HttpLoggingInterceptor to the OkHttpClient instance in the next
demo section.
Using Authenticator
OkHttp can automatically retry requests that fail due to lack of authentication.
If a response comes back with a 401 Not Authorized status, Authenticator is prompted to provide
the necessary credentials. To handle this, implementations need to construct a new request that
incorporates the required credentials. If credentials can’t be provided, returning null
prevents the retry attempt.
Proceed to the next section to learn how to add HttpLoggingInterceptor and Authenticator to
your networking code.