Last active
October 4, 2021 20:17
-
-
Save handstandsam/425407658f7ae0be7676de10576dd850 to your computer and use it in GitHub Desktop.
Protecting session sensitive responses with Retrofit 2 and okhttp 3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.net.SocketTimeoutException; | |
/** This exception extends {@link SocketTimeoutException} so that okhttp3 will not retry if retry is enabled. */ | |
public class SessionMismatchException extends SocketTimeoutException { | |
public SessionMismatchException() { | |
super("Session Mismatch"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.IOException; | |
import android.util.Log; | |
import okhttp3.Request; | |
import okhttp3.Response; | |
import retrofit2.Call; | |
/** | |
* Throw an exception for HTTP responses for invalidated sessions. This will end up calling the Retrofit 2 callback method: | |
* | |
* @see retrofit2.Callback#onFailure(Call, Throwable) | |
*/ | |
public class SessionSensitiveInterceptor implements okhttp3.Interceptor { | |
private static final String TAG = SessionMismatchException.class.getSimpleName(); | |
private final SessionManager sessionManager; | |
public SessionSensitiveInterceptor(SessionManager sessionManager) { | |
this.sessionManager = sessionManager; | |
} | |
/** | |
* Catches the response and before sending it back, makes sure the same Authorization Token is still active. | |
*/ | |
@Override | |
public Response intercept(Chain chain) throws IOException { | |
final Request request = chain.request(); | |
// Execute Request Synchronously and pass through all other interceptors | |
Response response = chain.proceed(request); | |
// Request is complete, grab current session token to compare and block if it's changed, but shouldn't have. | |
final String originalRequestAuthHeader = request.header("Authorization"); | |
final String currentSessionAuthHeader = sessionManager.getAuthorizationHeaderValue(); | |
if (originalRequestAuthHeader == null || originalRequestAuthHeader.length() == 0) { | |
// Unauthenticated API, this is fine. | |
return response; | |
} else if (currentSessionAuthHeader != null && originalRequestAuthHeader.equals(currentSessionAuthHeader)) { | |
// Authenticated API, same session is active, this is fine. | |
return response; | |
} else { | |
// Authenticated API, but authorization header has changed. Send a custom exception to the failure handler. | |
SessionMismatchException sessionMismatchException = new SessionMismatchException(); | |
Log.w(TAG, "Session Mismatch", new Exception()); | |
throw sessionMismatchException; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment