Skip to content

Commit

Permalink
Fall back to cached BLOB if MDS BLOB download fails
Browse files Browse the repository at this point in the history
  • Loading branch information
emlun committed Sep 15, 2022
1 parent 8cf2b92 commit 6d3b5b3
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 10 deletions.
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ Fixes:
`useTrustRootCache`.
* BouncyCastle dependency dropped.
* Guava dependency dropped (but still remains in core module).
* If BLOB download fails, `FidoMetadataDownloader` now correctly falls back to
cache if available.


== Version 2.0.0 ==
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,13 @@ private Optional<MetadataBLOB> refreshBlobInternal(
} else {
throw e;
}
} catch (Exception e) {
if (cached.isPresent()) {
log.warn("Failed to download new BLOB - falling back to cached BLOB.", e);
return cached;
} else {
throw e;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.yubico.webauthn.TestAuthenticator
import com.yubico.webauthn.data.ByteArray
import com.yubico.webauthn.data.COSEAlgorithmIdentifier
import org.bouncycastle.asn1.x500.X500Name
import org.eclipse.jetty.http.HttpStatus
import org.eclipse.jetty.server.HttpConfiguration
import org.eclipse.jetty.server.HttpConnectionFactory
import org.eclipse.jetty.server.Request
Expand Down Expand Up @@ -198,14 +199,16 @@ class FidoMetadataDownloaderSpec
path: String,
response: String,
): (Server, String, X509Certificate) =
makeHttpServer(Map(path -> response.getBytes(StandardCharsets.UTF_8)))
makeHttpServer(
Map(path -> (200, response.getBytes(StandardCharsets.UTF_8)))
)
private def makeHttpServer(
path: String,
response: Array[Byte],
): (Server, String, X509Certificate) =
makeHttpServer(Map(path -> response))
makeHttpServer(Map(path -> (200, response)))
private def makeHttpServer(
responses: Map[String, Array[Byte]]
responses: Map[String, (Int, Array[Byte])]
): (Server, String, X509Certificate) = {
val tlsKey = TestAuthenticator.generateEcKeypair()
val tlsCert = TestAuthenticator.buildCertificate(
Expand Down Expand Up @@ -248,9 +251,9 @@ class FidoMetadataDownloaderSpec
response: HttpServletResponse,
): Unit = {
responses.get(target) match {
case Some(responseBody) => {
case Some((status, responseBody)) => {
response.getOutputStream.write(responseBody)
response.setStatus(200)
response.setStatus(status)
}
case None => response.setStatus(404)
}
Expand Down Expand Up @@ -1062,7 +1065,7 @@ class FidoMetadataDownloaderSpec
blob.getNo should equal(blobNo)
}

it("The BLOB is downloaded if the cached one is out of date.") {
it("The cache is used if the BLOB download fails.") {
val oldBlobNo = 1
val newBlobNo = 2

Expand Down Expand Up @@ -1093,7 +1096,12 @@ class FidoMetadataDownloaderSpec
)

val (server, serverUrl, httpsCert) =
makeHttpServer("/blob.jwt", newBlobJwt)
makeHttpServer(
Map(
"/blob.jwt" -> (HttpStatus.TOO_MANY_REQUESTS_429, newBlobJwt
.getBytes(StandardCharsets.UTF_8))
)
)
startServer(server)

val blob = load(
Expand All @@ -1117,7 +1125,7 @@ class FidoMetadataDownloaderSpec
.build()
).getPayload
blob should not be null
blob.getNo should equal(newBlobNo)
blob.getNo should equal(oldBlobNo)
}
}

Expand Down Expand Up @@ -1152,8 +1160,10 @@ class FidoMetadataDownloaderSpec
val (server, _, httpsCert) =
makeHttpServer(
Map(
"/chain.pem" -> certChainPem.getBytes(StandardCharsets.UTF_8),
"/blob.jwt" -> blobJwt.getBytes(StandardCharsets.UTF_8),
"/chain.pem" -> (200, certChainPem.getBytes(
StandardCharsets.UTF_8
)),
"/blob.jwt" -> (200, blobJwt.getBytes(StandardCharsets.UTF_8)),
)
)
startServer(server)
Expand Down

0 comments on commit 6d3b5b3

Please sign in to comment.