Search in sources :

Example 1 with ByteArray

use of com.yubico.webauthn.data.ByteArray in project java-webauthn-server by Yubico.

the class WebAuthnServer method startRegistration.

public Either<String, RegistrationRequest> startRegistration(@NonNull String username, @NonNull String displayName, Optional<String> credentialNickname, ResidentKeyRequirement residentKeyRequirement, Optional<ByteArray> sessionToken) throws ExecutionException {
    logger.trace("startRegistration username: {}, credentialNickname: {}", username, credentialNickname);
    final Collection<CredentialRegistration> registrations = userStorage.getRegistrationsByUsername(username);
    final Optional<UserIdentity> existingUser = registrations.stream().findAny().map(CredentialRegistration::getUserIdentity);
    final boolean permissionGranted = existingUser.map(userIdentity -> sessions.isSessionForUser(userIdentity.getId(), sessionToken)).orElse(true);
    if (permissionGranted) {
        final UserIdentity registrationUserId = existingUser.orElseGet(() -> UserIdentity.builder().name(username).displayName(displayName).id(generateRandom(32)).build());
        RegistrationRequest request = new RegistrationRequest(username, credentialNickname, generateRandom(32), rp.startRegistration(StartRegistrationOptions.builder().user(registrationUserId).authenticatorSelection(AuthenticatorSelectionCriteria.builder().residentKey(residentKeyRequirement).build()).build()), Optional.of(sessions.createSession(registrationUserId.getId())));
        registerRequestStorage.put(request.getRequestId(), request);
        return Either.right(request);
    } else {
        return Either.left("The username \"" + username + "\" is already registered.");
    }
}
Also used : AppId(com.yubico.webauthn.extension.appid.AppId) X509Certificate(java.security.cert.X509Certificate) Arrays(java.util.Arrays) U2fRegistrationResult(demo.webauthn.data.U2fRegistrationResult) SortedSet(java.util.SortedSet) AuthenticatorData(com.yubico.webauthn.data.AuthenticatorData) LoggerFactory(org.slf4j.LoggerFactory) AuthenticatorSelectionCriteria(com.yubico.webauthn.data.AuthenticatorSelectionCriteria) JacksonCodecs(com.yubico.internal.util.JacksonCodecs) Either(com.yubico.util.Either) FinishRegistrationOptions(com.yubico.webauthn.FinishRegistrationOptions) COSEAlgorithmIdentifier(com.yubico.webauthn.data.COSEAlgorithmIdentifier) SecureRandom(java.security.SecureRandom) PublicKeyCredentialDescriptor(com.yubico.webauthn.data.PublicKeyCredentialDescriptor) CredentialRegistration(demo.webauthn.data.CredentialRegistration) RegistrationRequest(demo.webauthn.data.RegistrationRequest) U2fRegistrationResponse(demo.webauthn.data.U2fRegistrationResponse) Map(java.util.Map) FidoMetadataDownloaderException(com.yubico.fido.metadata.FidoMetadataDownloaderException) DigestException(java.security.DigestException) JsonSerializer(com.fasterxml.jackson.databind.JsonSerializer) InvalidAppIdException(com.yubico.webauthn.extension.appid.InvalidAppIdException) JsonNode(com.fasterxml.jackson.databind.JsonNode) UnexpectedLegalHeader(com.yubico.fido.metadata.UnexpectedLegalHeader) RelyingPartyIdentity(com.yubico.webauthn.data.RelyingPartyIdentity) CertPathValidatorException(java.security.cert.CertPathValidatorException) StartAssertionOptions(com.yubico.webauthn.StartAssertionOptions) AuthenticatorTransport(com.yubico.webauthn.data.AuthenticatorTransport) RegistrationFailedException(com.yubico.webauthn.exception.RegistrationFailedException) NonNull(lombok.NonNull) SignatureException(java.security.SignatureException) Collection(java.util.Collection) Set(java.util.Set) AssertionRequestWrapper(demo.webauthn.data.AssertionRequestWrapper) List(java.util.List) ResidentKeyRequirement(com.yubico.webauthn.data.ResidentKeyRequirement) CertificateParser(com.yubico.internal.util.CertificateParser) AssertionResponse(demo.webauthn.data.AssertionResponse) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) Optional(java.util.Optional) InvalidKeyException(java.security.InvalidKeyException) CacheBuilder(com.google.common.cache.CacheBuilder) ByteArray(com.yubico.webauthn.data.ByteArray) AssertionResult(com.yubico.webauthn.AssertionResult) JsonGenerator(com.fasterxml.jackson.core.JsonGenerator) HashMap(java.util.HashMap) Attestation(com.yubico.webauthn.attestation.Attestation) Supplier(java.util.function.Supplier) TreeSet(java.util.TreeSet) InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) Value(lombok.Value) AssertionFailedException(com.yubico.webauthn.exception.AssertionFailedException) StartRegistrationOptions(com.yubico.webauthn.StartRegistrationOptions) RegistrationResponse(demo.webauthn.data.RegistrationResponse) FinishAssertionOptions(com.yubico.webauthn.FinishAssertionOptions) JsonSerialize(com.fasterxml.jackson.databind.annotation.JsonSerialize) RelyingParty(com.yubico.webauthn.RelyingParty) UserIdentity(com.yubico.webauthn.data.UserIdentity) SerializerProvider(com.fasterxml.jackson.databind.SerializerProvider) RegisteredCredential(com.yubico.webauthn.RegisteredCredential) Logger(org.slf4j.Logger) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) CBORObject(com.upokecenter.cbor.CBORObject) IOException(java.io.IOException) CertificateException(java.security.cert.CertificateException) U2fVerifier(com.yubico.webauthn.U2fVerifier) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) ExceptionUtil(com.yubico.internal.util.ExceptionUtil) Base64UrlException(com.yubico.webauthn.data.exception.Base64UrlException) Clock(java.time.Clock) RegistrationResult(com.yubico.webauthn.RegistrationResult) AttestationConveyancePreference(com.yubico.webauthn.data.AttestationConveyancePreference) Cache(com.google.common.cache.Cache) AllArgsConstructor(lombok.AllArgsConstructor) Collections(java.util.Collections) YubicoJsonMetadataService(com.yubico.webauthn.attestation.YubicoJsonMetadataService) CredentialRegistration(demo.webauthn.data.CredentialRegistration) UserIdentity(com.yubico.webauthn.data.UserIdentity) RegistrationRequest(demo.webauthn.data.RegistrationRequest)

Example 2 with ByteArray

use of com.yubico.webauthn.data.ByteArray in project java-webauthn-server by Yubico.

the class WebAuthnServer method deregisterCredential.

public Either<List<String>, DeregisterCredentialResult> deregisterCredential(@NonNull ByteArray sessionToken, ByteArray credentialId) {
    logger.trace("deregisterCredential session: {}, credentialId: {}", sessionToken, credentialId);
    if (credentialId == null || credentialId.getBytes().length == 0) {
        return Either.left(Collections.singletonList("Credential ID must not be empty."));
    }
    Optional<ByteArray> session = sessions.getSession(sessionToken);
    if (session.isPresent()) {
        ByteArray userHandle = session.get();
        Optional<String> username = userStorage.getUsernameForUserHandle(userHandle);
        if (username.isPresent()) {
            Optional<CredentialRegistration> credReg = userStorage.getRegistrationByUsernameAndCredentialId(username.get(), credentialId);
            if (credReg.isPresent()) {
                userStorage.removeRegistrationByUsername(username.get(), credReg.get());
                return Either.right(new DeregisterCredentialResult(credReg.get(), !userStorage.userExists(username.get())));
            } else {
                return Either.left(Collections.singletonList("Credential ID not registered:" + credentialId));
            }
        } else {
            return Either.left(Collections.singletonList("Invalid user handle"));
        }
    } else {
        return Either.left(Collections.singletonList("Invalid session"));
    }
}
Also used : CredentialRegistration(demo.webauthn.data.CredentialRegistration) ByteArray(com.yubico.webauthn.data.ByteArray)

Example 3 with ByteArray

use of com.yubico.webauthn.data.ByteArray in project java-webauthn-server by Yubico.

the class FidoMetadataDownloader method retrieveBlob.

/**
 * @throws Base64UrlException if the metadata BLOB is not a well-formed JWT in compact
 *     serialization.
 * @throws CertPathValidatorException if the downloaded or explicitly configured BLOB fails
 *     certificate path validation.
 * @throws CertificateException if the BLOB signing certificate chain fails to parse.
 * @throws IOException if any of the following fails: downloading the BLOB, reading or writing the
 *     cache file (if any), or parsing the BLOB contents.
 * @throws InvalidAlgorithmParameterException if certificate path validation fails.
 * @throws InvalidKeyException if signature verification fails.
 * @throws UnexpectedLegalHeader if the downloaded BLOB (if any) contains a <code>"legalHeader"
 *     </code> value not configured in {@link
 *     FidoMetadataDownloaderBuilder.Step1#expectLegalHeader(String...)
 *     expectLegalHeader(String...)} but is otherwise valid. The downloaded BLOB will not be
 *     written to cache in this case.
 * @throws NoSuchAlgorithmException if signature verification fails.
 * @throws SignatureException if signature verification fails.
 * @throws FidoMetadataDownloaderException if the explicitly configured BLOB (if any) has a bad
 *     signature.
 */
private MetadataBLOB retrieveBlob(X509Certificate trustRootCertificate) throws Base64UrlException, CertPathValidatorException, CertificateException, IOException, InvalidAlgorithmParameterException, InvalidKeyException, UnexpectedLegalHeader, NoSuchAlgorithmException, SignatureException, FidoMetadataDownloaderException {
    if (blobJwt != null) {
        return parseAndVerifyBlob(new ByteArray(blobJwt.getBytes(StandardCharsets.UTF_8)), trustRootCertificate);
    } else {
        final Optional<ByteArray> cachedContents;
        if (blobCacheFile != null) {
            cachedContents = readCacheFile(blobCacheFile);
        } else {
            cachedContents = blobCacheSupplier.get();
        }
        final MetadataBLOB cachedBlob = cachedContents.map(cached -> {
            try {
                return parseAndVerifyBlob(cached, trustRootCertificate);
            } catch (Exception e) {
                return null;
            }
        }).orElse(null);
        if (cachedBlob != null && cachedBlob.getPayload().getNextUpdate().atStartOfDay().atZone(clock.getZone()).isAfter(clock.instant().atZone(clock.getZone()))) {
            return cachedBlob;
        } else {
            final ByteArray downloaded = download(blobUrl);
            try {
                final MetadataBLOB downloadedBlob = parseAndVerifyBlob(downloaded, trustRootCertificate);
                if (cachedBlob == null || downloadedBlob.getPayload().getNo() > cachedBlob.getPayload().getNo()) {
                    if (expectedLegalHeaders.contains(downloadedBlob.getPayload().getLegalHeader())) {
                        if (blobCacheFile != null) {
                            new FileOutputStream(blobCacheFile).write(downloaded.getBytes());
                        }
                        if (blobCacheConsumer != null) {
                            blobCacheConsumer.accept(downloaded);
                        }
                        return downloadedBlob;
                    } else {
                        throw new UnexpectedLegalHeader(cachedBlob, downloadedBlob);
                    }
                } else {
                    return cachedBlob;
                }
            } catch (FidoMetadataDownloaderException e) {
                if (e.getReason() == FidoMetadataDownloaderException.Reason.BAD_SIGNATURE && cachedBlob != null) {
                    return cachedBlob;
                } else {
                    throw e;
                }
            }
        }
    }
}
Also used : X509Certificate(java.security.cert.X509Certificate) SSLContext(javax.net.ssl.SSLContext) CertificateFactory(java.security.cert.CertificateFactory) URL(java.net.URL) Date(java.util.Date) HexException(com.yubico.webauthn.data.exception.HexException) RequiredArgsConstructor(lombok.RequiredArgsConstructor) Scanner(java.util.Scanner) KeyStoreException(java.security.KeyStoreException) DeserializationFeature(com.fasterxml.jackson.databind.DeserializationFeature) CertStoreParameters(java.security.cert.CertStoreParameters) ByteArrayInputStream(java.io.ByteArrayInputStream) DigestException(java.security.DigestException) CertPathValidatorException(java.security.cert.CertPathValidatorException) CRL(java.security.cert.CRL) TrustManagerFactory(javax.net.ssl.TrustManagerFactory) NonNull(lombok.NonNull) SignatureException(java.security.SignatureException) Collection(java.util.Collection) Signature(java.security.Signature) CertPathValidator(java.security.cert.CertPathValidator) Set(java.util.Set) KeyStore(java.security.KeyStore) KeyManagementException(java.security.KeyManagementException) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) FileNotFoundException(java.io.FileNotFoundException) StandardCharsets(java.nio.charset.StandardCharsets) List(java.util.List) Slf4j(lombok.extern.slf4j.Slf4j) Stream(java.util.stream.Stream) CertificateParser(com.yubico.internal.util.CertificateParser) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) Optional(java.util.Optional) InvalidKeyException(java.security.InvalidKeyException) ByteArray(com.yubico.webauthn.data.ByteArray) TrustAnchor(java.security.cert.TrustAnchor) MessageDigest(java.security.MessageDigest) BinaryUtil(com.yubico.internal.util.BinaryUtil) Supplier(java.util.function.Supplier) InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) ArrayList(java.util.ArrayList) AccessLevel(lombok.AccessLevel) URLConnection(java.net.URLConnection) HttpsURLConnection(javax.net.ssl.HttpsURLConnection) MalformedURLException(java.net.MalformedURLException) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) FileOutputStream(java.io.FileOutputStream) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) CertPath(java.security.cert.CertPath) CertificateException(java.security.cert.CertificateException) PKIXParameters(java.security.cert.PKIXParameters) File(java.io.File) Reason(com.yubico.fido.metadata.FidoMetadataDownloaderException.Reason) CollectionCertStoreParameters(java.security.cert.CollectionCertStoreParameters) Consumer(java.util.function.Consumer) Base64Variants(com.fasterxml.jackson.core.Base64Variants) CertStore(java.security.cert.CertStore) Base64UrlException(com.yubico.webauthn.data.exception.Base64UrlException) Clock(java.time.Clock) AllArgsConstructor(lombok.AllArgsConstructor) Collections(java.util.Collections) InputStream(java.io.InputStream) FileOutputStream(java.io.FileOutputStream) ByteArray(com.yubico.webauthn.data.ByteArray) HexException(com.yubico.webauthn.data.exception.HexException) KeyStoreException(java.security.KeyStoreException) DigestException(java.security.DigestException) CertPathValidatorException(java.security.cert.CertPathValidatorException) SignatureException(java.security.SignatureException) KeyManagementException(java.security.KeyManagementException) FileNotFoundException(java.io.FileNotFoundException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) InvalidKeyException(java.security.InvalidKeyException) InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException) CertificateException(java.security.cert.CertificateException) Base64UrlException(com.yubico.webauthn.data.exception.Base64UrlException)

Example 4 with ByteArray

use of com.yubico.webauthn.data.ByteArray in project java-webauthn-server by Yubico.

the class FidoMetadataDownloader method retrieveTrustRootCert.

/**
 * @throws CertificateException if the trust root certificate was downloaded and passed the
 *     SHA-256 integrity check, but does not contain a currently valid X.509 DER certificate.
 * @throws DigestException if the trust root certificate was downloaded but failed the SHA-256
 *     integrity check.
 * @throws IOException if the trust root certificate download failed, or if reading or writing the
 *     cache file (if any) failed.
 * @throws NoSuchAlgorithmException if the SHA-256 algorithm is not available.
 */
private X509Certificate retrieveTrustRootCert() throws CertificateException, DigestException, IOException, NoSuchAlgorithmException {
    if (trustRootCertificate != null) {
        return trustRootCertificate;
    } else {
        final Optional<ByteArray> cachedContents;
        if (trustRootCacheFile != null) {
            cachedContents = readCacheFile(trustRootCacheFile);
        } else {
            cachedContents = trustRootCacheSupplier.get();
        }
        X509Certificate cert = null;
        if (cachedContents.isPresent()) {
            try {
                final X509Certificate cachedCert = CertificateParser.parseDer(cachedContents.get().getBytes());
                cachedCert.checkValidity(Date.from(clock.instant()));
                cert = cachedCert;
            } catch (CertificateException e) {
            // Fall through
            }
        }
        if (cert == null) {
            final ByteArray downloaded = verifyHash(download(trustRootUrl), trustRootSha256);
            if (downloaded == null) {
                throw new DigestException("Downloaded trust root certificate matches none of the acceptable hashes.");
            }
            cert = CertificateParser.parseDer(downloaded.getBytes());
            cert.checkValidity(Date.from(clock.instant()));
            if (trustRootCacheFile != null) {
                new FileOutputStream(trustRootCacheFile).write(downloaded.getBytes());
            }
            if (trustRootCacheConsumer != null) {
                trustRootCacheConsumer.accept(downloaded);
            }
        }
        return cert;
    }
}
Also used : FileOutputStream(java.io.FileOutputStream) DigestException(java.security.DigestException) ByteArray(com.yubico.webauthn.data.ByteArray) CertificateException(java.security.cert.CertificateException) X509Certificate(java.security.cert.X509Certificate)

Example 5 with ByteArray

use of com.yubico.webauthn.data.ByteArray in project java-webauthn-server by Yubico.

the class FidoU2fAttestationStatementVerifier method getRawUserPublicKey.

private static ByteArray getRawUserPublicKey(AttestationObject attestationObject) throws IOException, CoseException {
    final ByteArray pubkeyCose = attestationObject.getAuthenticatorData().getAttestedCredentialData().get().getCredentialPublicKey();
    final PublicKey pubkey;
    try {
        pubkey = WebAuthnCodecs.importCosePublicKey(pubkeyCose);
    } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
        throw ExceptionUtil.wrapAndLog(log, "Failed to decode public key: " + pubkeyCose.getHex(), e);
    }
    final ECPublicKey ecPubkey;
    try {
        ecPubkey = (ECPublicKey) pubkey;
    } catch (ClassCastException e) {
        throw new RuntimeException("U2F supports only EC keys, was: " + pubkey);
    }
    return WebAuthnCodecs.ecPublicKeyToRaw(ecPubkey);
}
Also used : ECPublicKey(java.security.interfaces.ECPublicKey) PublicKey(java.security.PublicKey) ECPublicKey(java.security.interfaces.ECPublicKey) ByteArray(com.yubico.webauthn.data.ByteArray) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException)

Aggregations

ByteArray (com.yubico.webauthn.data.ByteArray)23 IOException (java.io.IOException)10 JsonNode (com.fasterxml.jackson.databind.JsonNode)7 X509Certificate (java.security.cert.X509Certificate)7 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)6 CertificateException (java.security.cert.CertificateException)6 List (java.util.List)5 Optional (java.util.Optional)5 CertificateParser (com.yubico.internal.util.CertificateParser)4 Base64UrlException (com.yubico.webauthn.data.exception.Base64UrlException)4 Collection (java.util.Collection)4 Collections (java.util.Collections)4 AllArgsConstructor (lombok.AllArgsConstructor)4 NonNull (lombok.NonNull)4 ASN1Primitive (org.bouncycastle.asn1.ASN1Primitive)4 DEROctetString (org.bouncycastle.asn1.DEROctetString)4 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)3 DigestException (java.security.DigestException)3 Slf4j (lombok.extern.slf4j.Slf4j)3 CoseException (COSE.CoseException)2