diff --git a/api-core/src/main/java/com/vimeo/networking2/VimeoResponse.kt b/api-core/src/main/java/com/vimeo/networking2/VimeoResponse.kt index b9f1bb061..9d4cefb28 100644 --- a/api-core/src/main/java/com/vimeo/networking2/VimeoResponse.kt +++ b/api-core/src/main/java/com/vimeo/networking2/VimeoResponse.kt @@ -46,6 +46,20 @@ sealed class VimeoResponse(open val httpStatusCode: Int) { override val httpStatusCode: Int ) : Error("API error: ${reason.errorCode ?: NA}", httpStatusCode) + /** + * The Vimeo API returned a fatal error that indicates that the token used to make the request is invalid. The + * token should be discarded and a new token should be acquired. Further requests should not be made with the + * token. + * + * @param reason Info on the error. + * @param httpStatusCode HTTP status code, [HTTP_NONE] if not applicable or if the error was + * created locally. + */ + data class InvalidToken( + val reason: ApiError?, + override val httpStatusCode: Int + ) : Error("Unauthorized error: ${reason?.errorCode ?: NA}", httpStatusCode) + /** * An exception was thrown when making the request, e.g. the internet connection failed and a * [java.io.IOException] is thrown. This should only be used if a response was not received from the server. If diff --git a/vimeo-networking/src/main/java/com/vimeo/networking/utils/VimeoNetworkUtil.java b/vimeo-networking/src/main/java/com/vimeo/networking/utils/VimeoNetworkUtil.java index 241b7830e..1bf152bb3 100644 --- a/vimeo-networking/src/main/java/com/vimeo/networking/utils/VimeoNetworkUtil.java +++ b/vimeo-networking/src/main/java/com/vimeo/networking/utils/VimeoNetworkUtil.java @@ -32,7 +32,6 @@ import com.vimeo.networking.logging.ClientLogger; import com.vimeo.networking2.AlbumPrivacy; import com.vimeo.networking2.AlbumPrivacyUtils; -import com.vimeo.networking2.ApiConstants; import com.vimeo.networking2.ApiError; import com.vimeo.networking2.InvalidParameter; import com.vimeo.networking2.VimeoResponse; @@ -64,6 +63,12 @@ @SuppressWarnings("unused") public final class VimeoNetworkUtil { + @NotNull + private static final String INVALID_TOKEN_VALUE = "Bearer error=\"invalid_token\""; + + @NotNull + private static final String AUTHENTICATE_HEADER = "WWW-Authenticate"; + @Nullable private static Gson sGson; @@ -210,11 +215,14 @@ public static VimeoResponse.Error getErrorFromResponse(@NotNull } final VimeoResponse.Error vimeoError; String errorBody = null; + final boolean isUnauthorizedError = INVALID_TOKEN_VALUE.equals(response.headers().get(AUTHENTICATE_HEADER)); if (response.errorBody() != null) { try { errorBody = response.errorBody().string(); final ApiError apiError = getMoshi().adapter(ApiError.class).fromJson(errorBody); - if (apiError != null) { + if (isUnauthorizedError) { + return new VimeoResponse.Error.InvalidToken(apiError, response.code()); + } else if (apiError != null) { return new VimeoResponse.Error.Api(apiError, response.code()); } else { return new VimeoResponse.Error.Unknown(errorBody, response.code()); @@ -224,8 +232,14 @@ public static VimeoResponse.Error getErrorFromResponse(@NotNull if (errorBody == null) { errorBody = "Unable to read error body"; } - return new VimeoResponse.Error.Unknown(errorBody, response.code()); + if (isUnauthorizedError) { + return new VimeoResponse.Error.InvalidToken(null, response.code()); + } else { + return new VimeoResponse.Error.Unknown(errorBody, response.code()); + } } + } else if (isUnauthorizedError) { + return new VimeoResponse.Error.InvalidToken(null, response.code()); } else { return new VimeoResponse.Error.Unknown("Null error body", response.code()); }