Skip to content

Commit f7ee426

Browse files
authored
Merge pull request #47 from Yubico/update-attestation-metadata
Update attestation metadata
2 parents 709b9ce + 040fbee commit f7ee426

File tree

6 files changed

+93
-27
lines changed

6 files changed

+93
-27
lines changed

NEWS

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1-
== Version 1.5.1 (unreleased) ==
1+
== Version 1.6.0 (unreleased) ==
22

33
Security fixes:
44

55
- Bumped Jackson dependency to version 2.9.10.1 which has patched CVE-2019-16942
66

7+
`webauthn-server-core`:
8+
79
Bug fixes:
810

911
- Fixed bug introduced in 1.4.0, which caused
1012
`RegistrationResult.attestationMetadata` to always be empty.
1113

1214

15+
`webauthn-server-attestation`:
16+
17+
- New enum constant `Transport.LIGHTNING`
18+
- Fixed transports field of YubiKey NEO/NEO-n in `metadata.json`.
19+
- Added YubiKey 5Ci to `metadata.json`.
20+
- Most `deviceUrl` fields in `metadata.json` changed to point to stable
21+
addresses in Yubico knowledge base instead of dead redirects in store.
22+
23+
1324
== Version 1.5.0 ==
1425

1526
Changes:

webauthn-server-attestation/src/main/resources/metadata.json

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"identifier": "2fb54029-7613-4f1d-94f1-fb876c14a6fe",
3-
"version": 5,
3+
"version": 11,
44
"vendorInfo": {
55
"url": "https://yubico.com",
66
"imageUrl": "https://developers.yubico.com/U2F/Images/yubico.png",
@@ -14,7 +14,7 @@
1414
"deviceId": "1.3.6.1.4.1.41482.1.1",
1515
"displayName": "Security Key NFC by Yubico",
1616
"transports": 12,
17-
"deviceUrl": "https://www.yubico.com/product/security-key-nfc-by-yubico/",
17+
"deviceUrl": "https://support.yubico.com/support/solutions/articles/15000019469-security-key-nfc",
1818
"imageUrl": "https://developers.yubico.com/U2F/Images/SKY-NFC.png",
1919
"selectors": [
2020
{
@@ -34,7 +34,7 @@
3434
"deviceId": "1.3.6.1.4.1.41482.1.1",
3535
"displayName": "Security Key by Yubico",
3636
"transports": 4,
37-
"deviceUrl": "https://www.yubico.com/products/yubikey-hardware/fido-u2f-security-key/",
37+
"deviceUrl": "https://support.yubico.com/support/solutions/articles/15000006900-security-key-by-yubico",
3838
"imageUrl": "https://developers.yubico.com/U2F/Images/SKY.png",
3939
"selectors": [
4040
{
@@ -55,8 +55,8 @@
5555
{
5656
"deviceId": "1.3.6.1.4.1.41482.1.2",
5757
"displayName": "YubiKey NEO/NEO-n",
58-
"transports": 4,
59-
"deviceUrl": "https://www.yubico.com/products/yubikey-hardware/yubikey-neo/",
58+
"transports": 12,
59+
"deviceUrl": "https://support.yubico.com/support/solutions/articles/15000006494-yubikey-neo",
6060
"imageUrl": "https://developers.yubico.com/U2F/Images/NEO.png",
6161
"selectors": [
6262
{
@@ -100,7 +100,7 @@
100100
"deviceId": "1.3.6.1.4.1.41482.1.4",
101101
"displayName": "YubiKey Edge",
102102
"transports": 4,
103-
"deviceUrl": "https://www.yubico.com/products/yubikey-hardware/",
103+
"deviceUrl": "https://support.yubico.com/support/solutions/articles/15000006492-yubikey-edge",
104104
"imageUrl": "https://developers.yubico.com/U2F/Images/YKE.png",
105105
"selectors": [
106106
{
@@ -116,7 +116,7 @@
116116
"deviceId": "1.3.6.1.4.1.41482.1.5",
117117
"displayName": "YubiKey 4/YubiKey 4 Nano",
118118
"transports": 4,
119-
"deviceUrl": "https://www.yubico.com/products/yubikey-hardware/yubikey4/",
119+
"deviceUrl": "https://support.yubico.com/support/solutions/articles/15000006486-yubikey-4",
120120
"imageUrl": "https://developers.yubico.com/U2F/Images/YK4.png",
121121
"selectors": [
122122
{
@@ -132,7 +132,7 @@
132132
"deviceId": "1.3.6.1.4.1.41482.1.7",
133133
"displayName": "YubiKey 5 NFC",
134134
"transports": 12,
135-
"deviceUrl": "https://www.yubico.com/products/yubikey-5-overview/",
135+
"deviceUrl": "https://support.yubico.com/support/solutions/articles/15000014174--yubikey-5-nfc",
136136
"imageUrl": "https://developers.yubico.com/U2F/Images/YK5.png",
137137
"selectors": [
138138
{
@@ -151,7 +151,7 @@
151151
"deviceId": "1.3.6.1.4.1.41482.1.7",
152152
"displayName": "YubiKey 5 Series security key",
153153
"transports": 4,
154-
"deviceUrl": "https://www.yubico.com/products/yubikey-5-overview/",
154+
"deviceUrl": "https://support.yubico.com/support/solutions/articles/15000014180-yubikey-5c",
155155
"imageUrl": "https://developers.yubico.com/U2F/Images/YK5-series.png",
156156
"selectors": [
157157
{
@@ -165,6 +165,25 @@
165165
}
166166
}
167167
]
168+
},
169+
{
170+
"deviceId": "1.3.6.1.4.1.41482.1.7",
171+
"displayName": "YubiKey 5Ci",
172+
"transports": 20,
173+
"deviceUrl": "https://support.yubico.com/support/solutions/articles/15000027140-yubikey-5ci",
174+
"imageUrl": "https://developers.yubico.com/U2F/Images/YK5Ci.png",
175+
"selectors": [
176+
{
177+
"type": "x509Extension",
178+
"parameters": {
179+
"key": "1.3.6.1.4.1.45724.1.1.4",
180+
"value": {
181+
"type": "hex",
182+
"value": "c5ef55ffad9a4b9fb580adebafe026d0"
183+
}
184+
}
185+
}
186+
]
168187
}
169188
]
170189
}

webauthn-server-attestation/src/test/scala/com/yubico/webauthn/attestation/DeviceIdentificationSpec.scala

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ import com.yubico.webauthn.attestation.resolver.SimpleTrustResolver
3333
import com.yubico.webauthn.test.RealExamples
3434
import com.yubico.webauthn.FinishRegistrationOptions
3535
import com.yubico.webauthn.RelyingParty
36+
import com.yubico.webauthn.attestation.Transport.LIGHTNING
37+
import com.yubico.webauthn.attestation.Transport.NFC
38+
import com.yubico.webauthn.attestation.Transport.USB
3639
import com.yubico.webauthn.data.PublicKeyCredentialCreationOptions
3740
import com.yubico.webauthn.data.PublicKeyCredentialParameters
3841
import com.yubico.webauthn.test.Helpers
@@ -57,7 +60,7 @@ class DeviceIdentificationSpec extends FunSpec with Matchers {
5760
describe("A RelyingParty with the default StandardMetadataService") {
5861

5962
describe("correctly identifies") {
60-
def check(expectedName: String, testData: RealExamples.Example) {
63+
def check(expectedName: String, testData: RealExamples.Example, transports: Set[Transport]) {
6164
val rp = RelyingParty.builder()
6265
.identity(testData.rp)
6366
.credentialRepository(Helpers.CredentialRepository.empty)
@@ -78,62 +81,72 @@ class DeviceIdentificationSpec extends FunSpec with Matchers {
7881
result.getAttestationMetadata.isPresent should be (true)
7982
result.getAttestationMetadata.get.getDeviceProperties.isPresent should be (true)
8083
result.getAttestationMetadata.get.getDeviceProperties.get().get("displayName") should equal (expectedName)
84+
result.getAttestationMetadata.get.getTransports.isPresent should be (true)
85+
result.getAttestationMetadata.get.getTransports.get.asScala should equal (transports)
8186
}
8287

8388
it("a YubiKey NEO.") {
84-
check("YubiKey NEO/NEO-n", RealExamples.YubiKeyNeo)
89+
check("YubiKey NEO/NEO-n", RealExamples.YubiKeyNeo, Set(USB, NFC))
8590
}
8691
it("a YubiKey 4.") {
87-
check("YubiKey 4/YubiKey 4 Nano", RealExamples.YubiKey4)
92+
check("YubiKey 4/YubiKey 4 Nano", RealExamples.YubiKey4, Set(USB))
8893
}
8994
it("a YubiKey 5 NFC.") {
90-
check("YubiKey 5 NFC", RealExamples.YubiKey5)
95+
check("YubiKey 5 NFC", RealExamples.YubiKey5, Set(USB, NFC))
9196
}
9297
it("a YubiKey 5 Nano.") {
93-
check("YubiKey 5 Series security key", RealExamples.YubiKey5Nano)
98+
check("YubiKey 5 Series security key", RealExamples.YubiKey5Nano, Set(USB))
99+
}
100+
it("a YubiKey 5Ci.") {
101+
check("YubiKey 5Ci", RealExamples.YubiKey5Ci, Set(USB, LIGHTNING))
94102
}
95103
it("a Security Key by Yubico.") {
96-
check("Security Key by Yubico", RealExamples.SecurityKey)
104+
check("Security Key by Yubico", RealExamples.SecurityKey, Set(USB))
97105
}
98106
it("a Security Key 2 by Yubico.") {
99-
check("Security Key by Yubico", RealExamples.SecurityKey2)
107+
check("Security Key by Yubico", RealExamples.SecurityKey2, Set(USB))
100108
}
101109
it("a Security Key NFC by Yubico.") {
102-
check("Security Key NFC by Yubico", RealExamples.SecurityKeyNfc)
110+
check("Security Key NFC by Yubico", RealExamples.SecurityKeyNfc, Set(USB, NFC))
103111
}
104112
}
105113
}
106114

107115
describe("The default AttestationResolver") {
108116
describe("successfully identifies") {
109-
def check(expectedName: String, testData: RealExamples.Example) {
117+
def check(expectedName: String, testData: RealExamples.Example, transports: Set[Transport]) {
110118
val cert = CertificateParser.parseDer(testData.attestationCert.getBytes)
111119
val resolved = StandardMetadataService.createDefaultAttestationResolver().resolve(cert)
112120
resolved.isPresent should be (true)
113121
resolved.get.getDeviceProperties.isPresent should be (true)
114122
resolved.get.getDeviceProperties.get.get("displayName") should equal (expectedName)
123+
resolved.get.getTransports.isPresent should be (true)
124+
resolved.get.getTransports.get.asScala should equal (transports)
115125
}
116126

117127
it("a YubiKey NEO.") {
118-
check("YubiKey NEO/NEO-n", RealExamples.YubiKeyNeo)
128+
check("YubiKey NEO/NEO-n", RealExamples.YubiKeyNeo, Set(USB, NFC))
119129
}
120130
it("a YubiKey 4.") {
121-
check("YubiKey 4/YubiKey 4 Nano", RealExamples.YubiKey4)
131+
check("YubiKey 4/YubiKey 4 Nano", RealExamples.YubiKey4, Set(USB))
122132
}
123133
it("a YubiKey 5 NFC.") {
124-
check("YubiKey 5 NFC", RealExamples.YubiKey5)
134+
check("YubiKey 5 NFC", RealExamples.YubiKey5, Set(USB, NFC))
125135
}
126136
it("a YubiKey 5 Nano.") {
127-
check("YubiKey 5 Series security key", RealExamples.YubiKey5Nano)
137+
check("YubiKey 5 Series security key", RealExamples.YubiKey5Nano, Set(USB))
138+
}
139+
it("a YubiKey 5Ci.") {
140+
check("YubiKey 5Ci", RealExamples.YubiKey5Ci, Set(USB, LIGHTNING))
128141
}
129142
it("a Security Key by Yubico.") {
130-
check("Security Key by Yubico", RealExamples.SecurityKey)
143+
check("Security Key by Yubico", RealExamples.SecurityKey, Set(USB))
131144
}
132145
it("a Security Key 2 by Yubico.") {
133-
check("Security Key by Yubico", RealExamples.SecurityKey2)
146+
check("Security Key by Yubico", RealExamples.SecurityKey2, Set(USB))
134147
}
135148
it("a Security Key NFC by Yubico.") {
136-
check("Security Key NFC by Yubico", RealExamples.SecurityKeyNfc)
149+
check("Security Key NFC by Yubico", RealExamples.SecurityKeyNfc, Set(USB, NFC))
137150
}
138151
}
139152
}

webauthn-server-core/src/main/java/com/yubico/webauthn/attestation/Transport.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,12 @@ public enum Transport {
5050
/**
5151
* The authenticator supports communication via Near Field Communication (NFC).
5252
*/
53-
NFC(8);
53+
NFC(8),
54+
55+
/**
56+
* The authenticator supports communication via Lightning.
57+
*/
58+
LIGHTNING(16);
5459

5560
private final int bitpos;
5661

webauthn-server-core/src/test/scala/com/yubico/webauthn/RelyingPartyCeremoniesSpec.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ class RelyingPartyCeremoniesSpec extends FunSpec with Matchers {
106106
it("a YubiKey 5 Nano.") {
107107
check(RealExamples.YubiKey5Nano)
108108
}
109+
it("a YubiKey 5Ci.") {
110+
check(RealExamples.YubiKey5Ci)
111+
}
109112
it("a Security Key by Yubico.") {
110113
check(RealExamples.SecurityKey)
111114
}

webauthn-server-core/src/test/scala/com/yubico/webauthn/test/RealExamples.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,21 @@ object RealExamples {
123123
)
124124
)
125125

126+
val YubiKey5Ci = Example(
127+
RelyingPartyIdentity.builder().id("example.com").name("Example RP").build(),
128+
UserIdentity.builder().name("[email protected]").displayName("A. User").id(ByteArray.fromBase64Url("dXNlcl9pZA==")).build(),
129+
AttestationExample(
130+
"""{"type": "webauthn.create", "clientExtensions": {}, "challenge": "Y2hhbGxlbmdl", "origin": "https://example.com"}""",
131+
ByteArray.fromBase64Url("o2NmbXRmcGFja2VkZ2F0dFN0bXSjY2FsZyZjc2lnWEYwRAIgXOZEuIaBrKT5VYJu9_D410HgJRm1SenwlKiXtcQxe0ICIG1_ycPCKHPjEsgRFVr4WdK5IY8K7aCyAc03c1-wnBJCY3g1Y4FZAsEwggK9MIIBpaADAgECAgQr8Xx4MA0GCSqGSIb3DQEBCwUAMC4xLDAqBgNVBAMTI1l1YmljbyBVMkYgUm9vdCBDQSBTZXJpYWwgNDU3MjAwNjMxMCAXDTE0MDgwMTAwMDAwMFoYDzIwNTAwOTA0MDAwMDAwWjBuMQswCQYDVQQGEwJTRTESMBAGA1UECgwJWXViaWNvIEFCMSIwIAYDVQQLDBlBdXRoZW50aWNhdG9yIEF0dGVzdGF0aW9uMScwJQYDVQQDDB5ZdWJpY28gVTJGIEVFIFNlcmlhbCA3MzcyNDYzMjgwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR0wseEI8hxLptI8llYZvxwQK5M3wfXd9WFrwSTme36kjy-tJ-XFvn1WnhsNCUfyPNePehbVnBQOMcLoScZYHmLo2wwajAiBgkrBgEEAYLECgIEFTEuMy42LjEuNC4xLjQxNDgyLjEuNzATBgsrBgEEAYLlHAIBAQQEAwICJDAhBgsrBgEEAYLlHAEBBAQSBBDF71X_rZpLn7WAreuv4CbQMAwGA1UdEwEB_wQCMAAwDQYJKoZIhvcNAQELBQADggEBAItuk3adeE1u6dkA0nECf8J35Lgm5mw5udSIucstLQU9ZrTVNjwXugnxsT5oVriRN7o1BB-Lz7KJmtDw34kvh_uA11A9Ksf6veIV3hK-ugN7WNok7gn0t6IWOZF1xVr7lyo0XgbV88Kh-_D1biUqc5u49qSvTH-Jx1WrUxeFh1S1CTpmvmYGdzgWE32qLsNeoscPkbtkVSYbB8hwPb7SbV_WbBBLzJEPn79oMJ_e-63B12iLdyu2K_PKuibBsqSVHioe6cnvksZktkDykn-ZedRDpNOyBGo-89eBA9tLIYx_bP8Mg9tCoIP8GZzh2P2joujOF4F0O1xkICNI9MB3-6JoYXV0aERhdGFYxKN5pvbur7mlXjeMEYA04nUeaC-rny0wqxPSElWGzhlHQQAAAATF71X_rZpLn7WAreuv4CbQAEDDAvEvv-vY_dFxV_gwT7mhKUN9M6PatW8FqDSEjXAaJL4EjL5exyo-FIaoqgH4lfmw-19_6ao6j9zPlFGHBmUOpQECAyYgASFYILUgImoYph7H0FqX_aKS3A4Ph1Aki_Edg9YB6oxw7nrIIlgghBKeVu0Z4cV6-Cya1H2ZTeeWdisBlK6QWDM89ne6794=")
132+
),
133+
AssertionExample(
134+
id = ByteArray.fromBase64Url("wwLxL7_r2P3RcVf4ME-5oSlDfTOj2rVvBag0hI1wGiS-BIy-XscqPhSGqKoB-JX5sPtff-mqOo_cz5RRhwZlDg=="),
135+
clientData = """{"type": "webauthn.get", "clientExtensions": {}, "challenge": "Q0hBTExFTkdF", "origin": "https://example.com"}""",
136+
authDataBytes = ByteArray.fromBase64Url("o3mm9u6vuaVeN4wRgDTidR5oL6ufLTCrE9ISVYbOGUcBAAAABw=="),
137+
sig = ByteArray.fromBase64Url("MEQCIHqWh09siRtXwUCVOnTrWUTfJfe9zv0_-WYd376qUcBqAiBMdsCPp-LpUEhgSbOz8y6hS1YTKFgpN-nIrpYDTxQhiA=="),
138+
)
139+
)
140+
126141
val SecurityKey = Example(
127142
RelyingPartyIdentity.builder().id("example.com").name("Example RP").build(),
128143
UserIdentity.builder().name("[email protected]").displayName("A. User").id(ByteArray.fromBase64Url("dXNlcl9pZA==")).build(),

0 commit comments

Comments
 (0)