From 7f969a5be3daf788bf1202266e2b9d3235eee2e4 Mon Sep 17 00:00:00 2001
From: csalas
Date: Tue, 26 Apr 2022 17:00:39 -0500
Subject: [PATCH 1/6] MDS integrations added to both backend and client
---
.../CreateAuth/CreateAuthChallengeFIDO2.js | 12 +-
.../FIDO2KitAPI/FIDO2KitAPI.js | 16 +-
.../src/main/java/com/yubicolabs/App.java | 190 ++--
.../data/AttestationRegistration.java | 29 +
.../data/CredentialRegistration.java | 6 +-
backend/template.yaml | 913 +++++++++---------
clients/web/react/public/i18n/en-US.json | 6 +-
.../RegisterPage/RegisterKeySuccessStep.tsx | 2 +-
.../_components/Credential/AddCredential.tsx | 39 +-
.../src/_components/Credential/Credential.tsx | 3 +-
.../_components/Credential/EditCredential.tsx | 70 +-
.../TrustedDevices/AddTrustedDevice.tsx | 7 +-
.../TrustedDevices/TrustedDevice.tsx | 23 +-
.../react/src/_components/WebAuthnClient.ts | 5 +-
.../src/_components/component.module.css | 5 +-
15 files changed, 730 insertions(+), 596 deletions(-)
create mode 100644 backend/lambda-functions/JavaWebAuthnLib/src/main/java/com/yubicolabs/data/AttestationRegistration.java
diff --git a/backend/lambda-functions/CreateAuth/CreateAuthChallengeFIDO2.js b/backend/lambda-functions/CreateAuth/CreateAuthChallengeFIDO2.js
index f147d51..26fddc7 100644
--- a/backend/lambda-functions/CreateAuth/CreateAuthChallengeFIDO2.js
+++ b/backend/lambda-functions/CreateAuth/CreateAuthChallengeFIDO2.js
@@ -131,9 +131,9 @@ async function getCreateCredentialsOptions(event, creds) {
const coseLookup = {"ES256": -7, "EdDSA": -8, "RS256": -257};
- startRegisterPayload.requestId = startRegisterPayload.requestId.base64;
- startRegisterPayload.publicKeyCredentialCreationOptions.user.id = startRegisterPayload.publicKeyCredentialCreationOptions.user.id.base64;
- startRegisterPayload.publicKeyCredentialCreationOptions.challenge = startRegisterPayload.publicKeyCredentialCreationOptions.challenge.base64;
+ startRegisterPayload.requestId = startRegisterPayload.requestId.base64url;
+ startRegisterPayload.publicKeyCredentialCreationOptions.user.id = startRegisterPayload.publicKeyCredentialCreationOptions.user.id.base64url;
+ startRegisterPayload.publicKeyCredentialCreationOptions.challenge = startRegisterPayload.publicKeyCredentialCreationOptions.challenge.base64url;
startRegisterPayload.publicKeyCredentialCreationOptions.attestation = startRegisterPayload.publicKeyCredentialCreationOptions.attestation.toLowerCase();
startRegisterPayload.publicKeyCredentialCreationOptions.authenticatorSelection.userVerification = startRegisterPayload.publicKeyCredentialCreationOptions.authenticatorSelection.userVerification.toLowerCase();
startRegisterPayload.publicKeyCredentialCreationOptions.authenticatorSelection.authenticatorAttachment = authSelectorResolve[startRegisterPayload.publicKeyCredentialCreationOptions.authenticatorSelection.authenticatorAttachment];
@@ -179,14 +179,14 @@ async function getCredentialsOptions(username) {
let startAuthPayload = JSON.parse(JSON.parse(response.Payload));
console.log("startAuthPayload: ", startAuthPayload);
- startAuthPayload.requestId = startAuthPayload.requestId.base64;
+ startAuthPayload.requestId = startAuthPayload.requestId.base64url;
console.log("requestId: ", startAuthPayload.requestId);
startAuthPayload.publicKeyCredentialRequestOptions.userVerification = startAuthPayload.publicKeyCredentialRequestOptions.userVerification.toLowerCase();
- startAuthPayload.publicKeyCredentialRequestOptions.challenge = startAuthPayload.publicKeyCredentialRequestOptions.challenge.base64;
+ startAuthPayload.publicKeyCredentialRequestOptions.challenge = startAuthPayload.publicKeyCredentialRequestOptions.challenge.base64url;
console.log("challenge: ", startAuthPayload.publicKeyCredentialRequestOptions.challenge);
startAuthPayload.publicKeyCredentialRequestOptions.allowCredentials = startAuthPayload.publicKeyCredentialRequestOptions.allowCredentials.map( (cred) => {
cred.type = cred.type.toLowerCase().replace('_','-');
- cred.id = cred.id.base64;
+ cred.id = cred.id.base64url;
return cred
});
console.log("response payload: ", startAuthPayload);
diff --git a/backend/lambda-functions/FIDO2KitAPI/FIDO2KitAPI.js b/backend/lambda-functions/FIDO2KitAPI/FIDO2KitAPI.js
index b1a4a7e..165cb9a 100644
--- a/backend/lambda-functions/FIDO2KitAPI/FIDO2KitAPI.js
+++ b/backend/lambda-functions/FIDO2KitAPI/FIDO2KitAPI.js
@@ -180,7 +180,7 @@ async function updateFIDO2CredentialNickname(username, body) {
const payload = JSON.stringify({
"type": "updateCredentialNickname",
"username": username,
- "credentialId": data.credential.credentialId.base64,
+ "credentialId": data.credential.credentialId.base64url,
"nickname": data.credentialNickname.value,
});
console.log("updateCredentialNickname request payload: "+payload);
@@ -264,15 +264,15 @@ async function startUsernamelessAuthentication() {
let startAuthPayload = JSON.parse(JSON.parse(response.Payload));
console.log("startAuthPayload: ", startAuthPayload);
- startAuthPayload.requestId = startAuthPayload.requestId.base64;
+ startAuthPayload.requestId = startAuthPayload.requestId.base64url;
console.log("requestId: ", startAuthPayload.requestId);
startAuthPayload.publicKeyCredentialRequestOptions.userVerification = startAuthPayload.publicKeyCredentialRequestOptions.userVerification.toLowerCase();
- startAuthPayload.publicKeyCredentialRequestOptions.challenge = startAuthPayload.publicKeyCredentialRequestOptions.challenge.base64;
+ startAuthPayload.publicKeyCredentialRequestOptions.challenge = startAuthPayload.publicKeyCredentialRequestOptions.challenge.base64url;
console.log("challenge: ", startAuthPayload.publicKeyCredentialRequestOptions.challenge);
if(startAuthPayload.publicKeyCredentialRequestOptions.allowCredentials){
startAuthPayload.publicKeyCredentialRequestOptions.allowCredentials = startAuthPayload.publicKeyCredentialRequestOptions.allowCredentials.map( (cred) => {
cred.type = cred.type.toLowerCase().replace('_','-');
- cred.id = cred.id.base64;
+ cred.id = cred.id.url;
return cred
});
}
@@ -322,9 +322,9 @@ async function startRegisterFIDO2Credential(profile, body, uid) {
const coseLookup = {"ES256": -7, "EdDSA": -8, "RS256": -257};
- startRegisterPayload.requestId = startRegisterPayload.requestId.base64;
- startRegisterPayload.publicKeyCredentialCreationOptions.user.id = startRegisterPayload.publicKeyCredentialCreationOptions.user.id.base64;
- startRegisterPayload.publicKeyCredentialCreationOptions.challenge = startRegisterPayload.publicKeyCredentialCreationOptions.challenge.base64;
+ startRegisterPayload.requestId = startRegisterPayload.requestId.base64url;
+ startRegisterPayload.publicKeyCredentialCreationOptions.user.id = startRegisterPayload.publicKeyCredentialCreationOptions.user.id.base64url;
+ startRegisterPayload.publicKeyCredentialCreationOptions.challenge = startRegisterPayload.publicKeyCredentialCreationOptions.challenge.base64url;
startRegisterPayload.publicKeyCredentialCreationOptions.attestation = startRegisterPayload.publicKeyCredentialCreationOptions.attestation.toLowerCase();
startRegisterPayload.publicKeyCredentialCreationOptions.authenticatorSelection.userVerification = startRegisterPayload.publicKeyCredentialCreationOptions.authenticatorSelection.userVerification.toLowerCase();
startRegisterPayload.publicKeyCredentialCreationOptions.authenticatorSelection.residentKey = startRegisterPayload.publicKeyCredentialCreationOptions.authenticatorSelection.residentKey.toLowerCase();
@@ -341,7 +341,7 @@ async function startRegisterFIDO2Credential(profile, body, uid) {
});
startRegisterPayload.publicKeyCredentialCreationOptions.excludeCredentials = startRegisterPayload.publicKeyCredentialCreationOptions.excludeCredentials.map( (cred) => {
cred.type = cred.type.toLowerCase().replace('_','-');
- cred.id = cred.id.base64;
+ cred.id = cred.id.base64url;
console.log("cred: "+ JSON.stringify(cred));
return cred;
});
diff --git a/backend/lambda-functions/JavaWebAuthnLib/src/main/java/com/yubicolabs/App.java b/backend/lambda-functions/JavaWebAuthnLib/src/main/java/com/yubicolabs/App.java
index d6e885f..0fb24c8 100644
--- a/backend/lambda-functions/JavaWebAuthnLib/src/main/java/com/yubicolabs/App.java
+++ b/backend/lambda-functions/JavaWebAuthnLib/src/main/java/com/yubicolabs/App.java
@@ -10,6 +10,13 @@
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
+import com.yubico.fido.metadata.AAGUID;
+import com.yubico.fido.metadata.AAID;
+import com.yubico.fido.metadata.AttachmentHint;
+import com.yubico.fido.metadata.AuthenticatorGetInfo;
+import com.yubico.fido.metadata.FidoMetadataDownloader;
+import com.yubico.fido.metadata.FidoMetadataService;
+import com.yubico.fido.metadata.MetadataBLOB;
import com.yubico.internal.util.JacksonCodecs;
import com.yubico.webauthn.AssertionResult;
import com.yubico.webauthn.FinishAssertionOptions;
@@ -19,31 +26,26 @@
import com.yubico.webauthn.RelyingParty;
import com.yubico.webauthn.StartAssertionOptions;
import com.yubico.webauthn.StartRegistrationOptions;
-import com.yubico.webauthn.attestation.Attestation;
-import com.yubico.webauthn.attestation.AttestationResolver;
-import com.yubico.webauthn.attestation.MetadataObject;
-import com.yubico.webauthn.attestation.MetadataService;
-import com.yubico.webauthn.attestation.StandardMetadataService;
-import com.yubico.webauthn.attestation.TrustResolver;
-import com.yubico.webauthn.attestation.resolver.CompositeAttestationResolver;
-import com.yubico.webauthn.attestation.resolver.CompositeTrustResolver;
-import com.yubico.webauthn.attestation.resolver.SimpleAttestationResolver;
-import com.yubico.webauthn.attestation.resolver.SimpleTrustResolverWithEquality;
import com.yubico.webauthn.data.AttestationConveyancePreference;
import com.yubico.webauthn.data.AuthenticatorSelectionCriteria;
+import com.yubico.webauthn.data.AuthenticatorTransport;
import com.yubico.webauthn.data.ByteArray;
import com.yubico.webauthn.data.PublicKeyCredentialDescriptor;
+import com.yubico.webauthn.data.ResidentKeyRequirement;
import com.yubico.webauthn.data.UserIdentity;
import com.yubico.webauthn.data.exception.Base64UrlException;
import com.yubico.webauthn.exception.AssertionFailedException;
import com.yubico.webauthn.exception.RegistrationFailedException;
import com.yubicolabs.data.AssertionRequestWrapper;
import com.yubicolabs.data.AssertionResponse;
+import com.yubicolabs.data.AttestationRegistration;
import com.yubico.webauthn.data.AuthenticatorAttachment;
import com.yubicolabs.data.CredentialRegistration;
import com.yubicolabs.data.RegistrationRequest;
import com.yubicolabs.data.RegistrationResponse;
import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.security.cert.PKIXRevocationChecker.Option;
import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;
@@ -51,8 +53,19 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
import java.util.Optional;
+
+import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
+import java.io.File;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.yubico.fido.metadata.MetadataBLOBPayloadEntry;
+import com.yubico.fido.metadata.MetadataStatement;
/**
* Lambda function entry point. You can change to use other pojo type or
@@ -81,85 +94,40 @@ public class App implements RequestHandler
+ )}
-
- {checkAttestation(credential) && (
- <>
-
- {t("credential.yubico-att-label")}
-
-
- {t("credential.att-device-name")}{" "}
- {
- credential.attestationMetadata.value.deviceProperties
- .displayName
- }{" "}
- -{" "}
-
- {t("credential.att-device-info")}
-
-
-
-
{t("credential.att-device-interfaces")}{" "}
-
- {credential.attestationMetadata.value.transports.map(
- (transport, index) => (
- - {transport}
- )
- )}
-
-
- >
- )}
-
+
{t("recovery-codes.close-button")}
+
+ {t("recovery-codes.ignore")}
+
>
From fdf2112b481c67bada2ab7bd6295f2b8b323ff49 Mon Sep 17 00:00:00 2001
From: csalas
Date: Mon, 9 May 2022 08:47:46 -0500
Subject: [PATCH 5/6] Edits to news file to prepare for 2.1.0
---
NEWS | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/NEWS b/NEWS
index a367e5b..b6658ea 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,11 @@
-== Version 2.0.0 RC ==
+== Version 2.1.0 ==
+
+- Integration with FIDO MDS
+- Automatic nicknames given to authenticators through MDS
+- New Edit modal for Trusted Devices
+- Various bug fixes for internationalization, Android resident key settings, and Safari user handle default values
+
+== Version 2.0.0 ==
- Updated look and feel of UI
- Attestation data now displayed to the user (if they are using a YubiKey)
From a482b7429f09b0d9e2f60bff78ca990ef73caa4c Mon Sep 17 00:00:00 2001
From: csalas
Date: Mon, 9 May 2022 10:29:23 -0500
Subject: [PATCH 6/6] Removed unneeded console outputs from recovery code modal
testing
---
.../react/src/_components/RecoveryCodes/RecoveryCodes.tsx | 8 --------
1 file changed, 8 deletions(-)
diff --git a/clients/web/react/src/_components/RecoveryCodes/RecoveryCodes.tsx b/clients/web/react/src/_components/RecoveryCodes/RecoveryCodes.tsx
index b648119..0ee50c1 100644
--- a/clients/web/react/src/_components/RecoveryCodes/RecoveryCodes.tsx
+++ b/clients/web/react/src/_components/RecoveryCodes/RecoveryCodes.tsx
@@ -59,7 +59,6 @@ const RecoveryCodes = function ({ credentials }) {
};
const handleIgnore = () => {
- console.warn("This method did get called");
localStorage.setItem("recoveryCodesModal", "true");
setShowCodes(false);
};
@@ -70,19 +69,12 @@ const RecoveryCodes = function ({ credentials }) {
*/
useEffect(() => {
if ((!recoveryCodesViewed || allRecoveryCodesUsed) && !ignoreModal) {
- console.warn("we in here: ", {
- recoveryCodesViewed,
- allRecoveryCodesUsed,
- ignoreModal,
- });
-
handleShow();
}
}, [recoveryCodesViewed, allRecoveryCodesUsed]);
useEffect(() => {
if (localStorage.getItem("recoveryCodesModal") === "true") {
- console.warn("ignore modal is true");
setIgnoreMoral(true);
}
}, []);