mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 14:52:16 +00:00
Bug 1862132 - Part 1. Move data class to WebAuthnUtils. r=jschanck,geckoview-reviewers,owlish
I would like to move data class from WebAuthnTokenManager to new class since WebAuthnTokenManager may becomes complex when we add Credential Manager support. Differential Revision: https://phabricator.services.mozilla.com/D207500
This commit is contained in:
parent
afaf41dcef
commit
e067299302
@ -14,9 +14,8 @@ namespace mozilla::jni {
|
||||
template <>
|
||||
RefPtr<dom::WebAuthnRegisterResult> Java2Native(
|
||||
mozilla::jni::Object::Param aData, JNIEnv* aEnv) {
|
||||
MOZ_ASSERT(
|
||||
aData.IsInstanceOf<java::WebAuthnTokenManager::MakeCredentialResponse>());
|
||||
java::WebAuthnTokenManager::MakeCredentialResponse::LocalRef response(aData);
|
||||
MOZ_ASSERT(aData.IsInstanceOf<java::WebAuthnUtils::MakeCredentialResponse>());
|
||||
java::WebAuthnUtils::MakeCredentialResponse::LocalRef response(aData);
|
||||
RefPtr<dom::WebAuthnRegisterResult> result =
|
||||
new dom::WebAuthnRegisterResult(response);
|
||||
return result;
|
||||
@ -25,9 +24,8 @@ RefPtr<dom::WebAuthnRegisterResult> Java2Native(
|
||||
template <>
|
||||
RefPtr<dom::WebAuthnSignResult> Java2Native(mozilla::jni::Object::Param aData,
|
||||
JNIEnv* aEnv) {
|
||||
MOZ_ASSERT(
|
||||
aData.IsInstanceOf<java::WebAuthnTokenManager::GetAssertionResponse>());
|
||||
java::WebAuthnTokenManager::GetAssertionResponse::LocalRef response(aData);
|
||||
MOZ_ASSERT(aData.IsInstanceOf<java::WebAuthnUtils::GetAssertionResponse>());
|
||||
java::WebAuthnUtils::GetAssertionResponse::LocalRef response(aData);
|
||||
RefPtr<dom::WebAuthnSignResult> result =
|
||||
new dom::WebAuthnSignResult(response);
|
||||
return result;
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "nsString.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
# include "mozilla/java/WebAuthnTokenManagerNatives.h"
|
||||
# include "mozilla/java/WebAuthnUtilsNatives.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
@ -44,8 +44,7 @@ class WebAuthnRegisterResult final : public nsIWebAuthnRegisterResult {
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
explicit WebAuthnRegisterResult(
|
||||
const java::WebAuthnTokenManager::MakeCredentialResponse::LocalRef&
|
||||
aResponse) {
|
||||
const java::WebAuthnUtils::MakeCredentialResponse::LocalRef& aResponse) {
|
||||
mAttestationObject.AppendElements(
|
||||
reinterpret_cast<uint8_t*>(
|
||||
aResponse->AttestationObject()->GetElements().Elements()),
|
||||
@ -167,8 +166,7 @@ class WebAuthnSignResult final : public nsIWebAuthnSignResult {
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
explicit WebAuthnSignResult(
|
||||
const java::WebAuthnTokenManager::GetAssertionResponse::LocalRef&
|
||||
aResponse) {
|
||||
const java::WebAuthnUtils::GetAssertionResponse::LocalRef& aResponse) {
|
||||
mAuthenticatorData.AppendElements(
|
||||
reinterpret_cast<uint8_t*>(
|
||||
aResponse->AuthData()->GetElements().Elements()),
|
||||
|
@ -0,0 +1,263 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil; -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=100: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.util;
|
||||
|
||||
import android.util.Base64;
|
||||
import com.google.android.gms.fido.common.Transport;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
|
||||
public class WebAuthnUtils {
|
||||
private static final String LOGTAG = "WebAuthnUtils";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
// from dom/webauthn/WebAuthnTransportIdentifiers.h
|
||||
private static final byte AUTHENTICATOR_TRANSPORT_USB = 1;
|
||||
private static final byte AUTHENTICATOR_TRANSPORT_NFC = 2;
|
||||
private static final byte AUTHENTICATOR_TRANSPORT_BLE = 4;
|
||||
private static final byte AUTHENTICATOR_TRANSPORT_INTERNAL = 8;
|
||||
|
||||
// From WebAuthentication.webidl
|
||||
public enum AttestationPreference {
|
||||
NONE,
|
||||
INDIRECT,
|
||||
DIRECT,
|
||||
}
|
||||
|
||||
public static List<Transport> getTransportsForByte(final byte transports) {
|
||||
final ArrayList<Transport> result = new ArrayList<Transport>();
|
||||
if ((transports & AUTHENTICATOR_TRANSPORT_USB) == AUTHENTICATOR_TRANSPORT_USB) {
|
||||
result.add(Transport.USB);
|
||||
}
|
||||
if ((transports & AUTHENTICATOR_TRANSPORT_NFC) == AUTHENTICATOR_TRANSPORT_NFC) {
|
||||
result.add(Transport.NFC);
|
||||
}
|
||||
if ((transports & AUTHENTICATOR_TRANSPORT_BLE) == AUTHENTICATOR_TRANSPORT_BLE) {
|
||||
result.add(Transport.BLUETOOTH_LOW_ENERGY);
|
||||
}
|
||||
if ((transports & AUTHENTICATOR_TRANSPORT_INTERNAL) == AUTHENTICATOR_TRANSPORT_INTERNAL) {
|
||||
result.add(Transport.INTERNAL);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static class WebAuthnPublicCredential {
|
||||
public final byte[] id;
|
||||
public final byte transports;
|
||||
|
||||
public WebAuthnPublicCredential(final byte[] aId, final byte aTransports) {
|
||||
this.id = aId;
|
||||
this.transports = aTransports;
|
||||
}
|
||||
|
||||
public static ArrayList<WebAuthnPublicCredential> CombineBuffers(
|
||||
final Object[] idObjectList, final ByteBuffer transportList) {
|
||||
if (idObjectList.length != transportList.remaining()) {
|
||||
throw new RuntimeException("Couldn't extract allowed list!");
|
||||
}
|
||||
|
||||
final ArrayList<WebAuthnPublicCredential> credList =
|
||||
new ArrayList<WebAuthnPublicCredential>();
|
||||
|
||||
final byte[] transportBytes = new byte[transportList.remaining()];
|
||||
transportList.get(transportBytes);
|
||||
|
||||
for (int i = 0; i < idObjectList.length; i++) {
|
||||
final ByteBuffer id = (ByteBuffer) idObjectList[i];
|
||||
final byte[] idBytes = new byte[id.remaining()];
|
||||
id.get(idBytes);
|
||||
|
||||
credList.add(new WebAuthnPublicCredential(idBytes, transportBytes[i]));
|
||||
}
|
||||
return credList;
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI
|
||||
public static class MakeCredentialResponse {
|
||||
public final byte[] clientDataJson;
|
||||
public final byte[] keyHandle;
|
||||
public final byte[] attestationObject;
|
||||
public final String[] transports;
|
||||
public final String authenticatorAttachment;
|
||||
|
||||
public static final class Builder {
|
||||
private byte[] mClientDataJson;
|
||||
private byte[] mKeyHandle;
|
||||
private byte[] mAttestationObject;
|
||||
private String[] mTransports;
|
||||
private String mAuthenticatorAttachment;
|
||||
|
||||
public Builder() {}
|
||||
|
||||
public Builder setClientDataJson(final byte[] clientDataJson) {
|
||||
this.mClientDataJson = clientDataJson;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setKeyHandle(final byte[] keyHandle) {
|
||||
this.mKeyHandle = keyHandle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAttestationObject(final byte[] attestationObject) {
|
||||
this.mAttestationObject = attestationObject;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTransports(final String[] transports) {
|
||||
this.mTransports = transports;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAuthenticatorAttachment(final String authenticatorAttachment) {
|
||||
this.mAuthenticatorAttachment = authenticatorAttachment;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MakeCredentialResponse build() {
|
||||
return new MakeCredentialResponse(this);
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI(skip = true)
|
||||
protected MakeCredentialResponse(final Builder builder) {
|
||||
this.clientDataJson = builder.mClientDataJson;
|
||||
this.keyHandle = builder.mKeyHandle;
|
||||
this.attestationObject = builder.mAttestationObject;
|
||||
this.transports = builder.mTransports;
|
||||
this.authenticatorAttachment = builder.mAuthenticatorAttachment;
|
||||
}
|
||||
|
||||
@WrapForJNI(skip = true)
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("{");
|
||||
sb.append("clientDataJson=")
|
||||
.append(
|
||||
Base64.encodeToString(
|
||||
this.clientDataJson, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING))
|
||||
.append(", keyHandle=")
|
||||
.append(
|
||||
Base64.encodeToString(
|
||||
this.keyHandle, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING))
|
||||
.append(", attestationObject=")
|
||||
.append(
|
||||
Base64.encodeToString(
|
||||
this.attestationObject, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING))
|
||||
.append(", transports=")
|
||||
.append(String.join(", ", this.transports))
|
||||
.append(", authenticatorAttachment=")
|
||||
.append(this.authenticatorAttachment)
|
||||
.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI
|
||||
public static class GetAssertionResponse {
|
||||
public final byte[] clientDataJson;
|
||||
public final byte[] keyHandle;
|
||||
public final byte[] authData;
|
||||
public final byte[] signature;
|
||||
public final byte[] userHandle;
|
||||
public final String authenticatorAttachment;
|
||||
|
||||
public static final class Builder {
|
||||
private byte[] mClientDataJson;
|
||||
private byte[] mKeyHandle;
|
||||
private byte[] mAuthData;
|
||||
private byte[] mSignature;
|
||||
private byte[] mUserHandle;
|
||||
private String mAuthenticatorAttachment;
|
||||
|
||||
public Builder() {}
|
||||
|
||||
public Builder setClientDataJson(final byte[] clientDataJson) {
|
||||
this.mClientDataJson = clientDataJson;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setKeyHandle(final byte[] keyHandle) {
|
||||
this.mKeyHandle = keyHandle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAuthData(final byte[] authData) {
|
||||
this.mAuthData = authData;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSignature(final byte[] signature) {
|
||||
this.mSignature = signature;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUserHandle(final byte[] userHandle) {
|
||||
this.mUserHandle = userHandle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAuthenticatorAttachment(final String authenticatorAttachment) {
|
||||
this.mAuthenticatorAttachment = authenticatorAttachment;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GetAssertionResponse build() {
|
||||
return new GetAssertionResponse(this);
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI(skip = true)
|
||||
protected GetAssertionResponse(final Builder builder) {
|
||||
this.clientDataJson = builder.mClientDataJson;
|
||||
this.keyHandle = builder.mKeyHandle;
|
||||
this.authData = builder.mAuthData;
|
||||
this.signature = builder.mSignature;
|
||||
if (builder.mUserHandle == null) {
|
||||
this.userHandle = new byte[0];
|
||||
} else {
|
||||
this.userHandle = builder.mUserHandle;
|
||||
}
|
||||
this.authenticatorAttachment = builder.mAuthenticatorAttachment;
|
||||
}
|
||||
|
||||
@WrapForJNI(skip = true)
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("{");
|
||||
sb.append("clientDataJson=")
|
||||
.append(
|
||||
Base64.encodeToString(
|
||||
this.clientDataJson, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING))
|
||||
.append(", keyHandle=")
|
||||
.append(
|
||||
Base64.encodeToString(
|
||||
this.keyHandle, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING))
|
||||
.append(", authData=")
|
||||
.append(
|
||||
Base64.encodeToString(
|
||||
this.authData, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING))
|
||||
.append(", signature=")
|
||||
.append(
|
||||
Base64.encodeToString(
|
||||
this.signature, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING))
|
||||
.append(", userHandle=")
|
||||
.append(
|
||||
userHandle.length > 0
|
||||
? Base64.encodeToString(
|
||||
this.userHandle, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING)
|
||||
: "(empty)")
|
||||
.append(", authenticatorAttachment=")
|
||||
.append(this.authenticatorAttachment)
|
||||
.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
@ -7,10 +7,8 @@ package org.mozilla.geckoview;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.net.Uri;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import com.google.android.gms.fido.Fido;
|
||||
import com.google.android.gms.fido.common.Transport;
|
||||
import com.google.android.gms.fido.fido2.Fido2ApiClient;
|
||||
import com.google.android.gms.fido.fido2.Fido2PrivilegedApiClient;
|
||||
import com.google.android.gms.fido.fido2.api.common.Algorithm;
|
||||
@ -43,16 +41,11 @@ import java.util.List;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.WebAuthnUtils;
|
||||
|
||||
/* package */ class WebAuthnTokenManager {
|
||||
private static final String LOGTAG = "WebAuthnTokenManager";
|
||||
|
||||
// from dom/webauthn/WebAuthnTransportIdentifiers.h
|
||||
private static final byte AUTHENTICATOR_TRANSPORT_USB = 1;
|
||||
private static final byte AUTHENTICATOR_TRANSPORT_NFC = 2;
|
||||
private static final byte AUTHENTICATOR_TRANSPORT_BLE = 4;
|
||||
private static final byte AUTHENTICATOR_TRANSPORT_INTERNAL = 8;
|
||||
|
||||
private static final Algorithm[] SUPPORTED_ALGORITHMS = {
|
||||
EC2Algorithm.ES256,
|
||||
EC2Algorithm.ES384,
|
||||
@ -67,95 +60,17 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
RSAAlgorithm.RS512
|
||||
};
|
||||
|
||||
private static List<Transport> getTransportsForByte(final byte transports) {
|
||||
final ArrayList<Transport> result = new ArrayList<Transport>();
|
||||
if ((transports & AUTHENTICATOR_TRANSPORT_USB) == AUTHENTICATOR_TRANSPORT_USB) {
|
||||
result.add(Transport.USB);
|
||||
}
|
||||
if ((transports & AUTHENTICATOR_TRANSPORT_NFC) == AUTHENTICATOR_TRANSPORT_NFC) {
|
||||
result.add(Transport.NFC);
|
||||
}
|
||||
if ((transports & AUTHENTICATOR_TRANSPORT_BLE) == AUTHENTICATOR_TRANSPORT_BLE) {
|
||||
result.add(Transport.BLUETOOTH_LOW_ENERGY);
|
||||
}
|
||||
if ((transports & AUTHENTICATOR_TRANSPORT_INTERNAL) == AUTHENTICATOR_TRANSPORT_INTERNAL) {
|
||||
result.add(Transport.INTERNAL);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static class WebAuthnPublicCredential {
|
||||
public final byte[] id;
|
||||
public final byte transports;
|
||||
|
||||
public WebAuthnPublicCredential(final byte[] aId, final byte aTransports) {
|
||||
this.id = aId;
|
||||
this.transports = aTransports;
|
||||
}
|
||||
|
||||
static ArrayList<WebAuthnPublicCredential> CombineBuffers(
|
||||
final Object[] idObjectList, final ByteBuffer transportList) {
|
||||
if (idObjectList.length != transportList.remaining()) {
|
||||
throw new RuntimeException("Couldn't extract allowed list!");
|
||||
}
|
||||
|
||||
final ArrayList<WebAuthnPublicCredential> credList =
|
||||
new ArrayList<WebAuthnPublicCredential>();
|
||||
|
||||
final byte[] transportBytes = new byte[transportList.remaining()];
|
||||
transportList.get(transportBytes);
|
||||
|
||||
for (int i = 0; i < idObjectList.length; i++) {
|
||||
final ByteBuffer id = (ByteBuffer) idObjectList[i];
|
||||
final byte[] idBytes = new byte[id.remaining()];
|
||||
id.get(idBytes);
|
||||
|
||||
credList.add(new WebAuthnPublicCredential(idBytes, transportBytes[i]));
|
||||
}
|
||||
return credList;
|
||||
}
|
||||
}
|
||||
|
||||
// From WebAuthentication.webidl
|
||||
public enum AttestationPreference {
|
||||
NONE,
|
||||
INDIRECT,
|
||||
DIRECT,
|
||||
}
|
||||
|
||||
@WrapForJNI
|
||||
public static class MakeCredentialResponse {
|
||||
public final byte[] clientDataJson;
|
||||
public final byte[] keyHandle;
|
||||
public final byte[] attestationObject;
|
||||
public final String[] transports;
|
||||
public final String authenticatorAttachment;
|
||||
|
||||
public MakeCredentialResponse(
|
||||
final byte[] clientDataJson,
|
||||
final byte[] keyHandle,
|
||||
final byte[] attestationObject,
|
||||
final String[] transports,
|
||||
final String authenticatorAttachment) {
|
||||
this.clientDataJson = clientDataJson;
|
||||
this.keyHandle = keyHandle;
|
||||
this.attestationObject = attestationObject;
|
||||
this.transports = transports;
|
||||
this.authenticatorAttachment = authenticatorAttachment;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Exception extends RuntimeException {
|
||||
public Exception(final String error) {
|
||||
super(error);
|
||||
}
|
||||
}
|
||||
|
||||
public static GeckoResult<MakeCredentialResponse> makeCredential(
|
||||
public static GeckoResult<WebAuthnUtils.MakeCredentialResponse> makeCredential(
|
||||
final GeckoBundle credentialBundle,
|
||||
final byte[] userId,
|
||||
final byte[] challenge,
|
||||
final WebAuthnTokenManager.WebAuthnPublicCredential[] excludeList,
|
||||
final WebAuthnUtils.WebAuthnPublicCredential[] excludeList,
|
||||
final GeckoBundle authenticatorSelection,
|
||||
final GeckoBundle extensions) {
|
||||
if (!credentialBundle.containsKey("isWebAuthn")) {
|
||||
@ -227,12 +142,12 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
|
||||
final List<PublicKeyCredentialDescriptor> excludedList =
|
||||
new ArrayList<PublicKeyCredentialDescriptor>();
|
||||
for (final WebAuthnTokenManager.WebAuthnPublicCredential cred : excludeList) {
|
||||
for (final WebAuthnUtils.WebAuthnPublicCredential cred : excludeList) {
|
||||
excludedList.add(
|
||||
new PublicKeyCredentialDescriptor(
|
||||
PublicKeyCredentialType.PUBLIC_KEY.toString(),
|
||||
cred.id,
|
||||
getTransportsForByte(cred.transports)));
|
||||
WebAuthnUtils.getTransportsForByte(cred.transports)));
|
||||
}
|
||||
|
||||
final PublicKeyCredentialRpEntity rp =
|
||||
@ -286,7 +201,7 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
intentTask = fidoClient.getRegisterPendingIntent(requestOptions);
|
||||
}
|
||||
|
||||
final GeckoResult<MakeCredentialResponse> result = new GeckoResult<>();
|
||||
final GeckoResult<WebAuthnUtils.MakeCredentialResponse> result = new GeckoResult<>();
|
||||
|
||||
intentTask.addOnSuccessListener(
|
||||
pendingIntent -> {
|
||||
@ -321,36 +236,18 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
|
||||
final AuthenticatorAttestationResponse responseData =
|
||||
(AuthenticatorAttestationResponse) response;
|
||||
final WebAuthnUtils.MakeCredentialResponse credentialResponse =
|
||||
new WebAuthnUtils.MakeCredentialResponse.Builder()
|
||||
.setKeyHandle(publicKeyCredentialData.getRawId())
|
||||
.setAuthenticatorAttachment(
|
||||
publicKeyCredentialData.getAuthenticatorAttachment())
|
||||
.setClientDataJson(responseData.getClientDataJSON())
|
||||
.setAttestationObject(responseData.getAttestationObject())
|
||||
.setTransports(responseData.getTransports())
|
||||
.build();
|
||||
|
||||
Log.d(
|
||||
LOGTAG,
|
||||
"key handle: "
|
||||
+ Base64.encodeToString(
|
||||
publicKeyCredentialData.getRawId(), Base64.DEFAULT));
|
||||
Log.d(
|
||||
LOGTAG,
|
||||
"clientDataJSON: "
|
||||
+ Base64.encodeToString(
|
||||
responseData.getClientDataJSON(), Base64.DEFAULT));
|
||||
Log.d(
|
||||
LOGTAG,
|
||||
"attestation Object: "
|
||||
+ Base64.encodeToString(
|
||||
responseData.getAttestationObject(), Base64.DEFAULT));
|
||||
|
||||
Log.d(LOGTAG, "transports: " + String.join(", ", responseData.getTransports()));
|
||||
Log.d(
|
||||
LOGTAG,
|
||||
"authenticatorAttachment :"
|
||||
+ publicKeyCredentialData.getAuthenticatorAttachment());
|
||||
|
||||
result.complete(
|
||||
new WebAuthnTokenManager.MakeCredentialResponse(
|
||||
responseData.getClientDataJSON(),
|
||||
publicKeyCredentialData.getRawId(),
|
||||
responseData.getAttestationObject(),
|
||||
responseData.getTransports(),
|
||||
publicKeyCredentialData.getAuthenticatorAttachment()));
|
||||
Log.d(LOGTAG, "MakeCredentialResponse: " + credentialResponse.toString());
|
||||
result.complete(credentialResponse);
|
||||
},
|
||||
e -> {
|
||||
Log.w(LOGTAG, "Failed to launch activity: ", e);
|
||||
@ -368,7 +265,7 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static GeckoResult<MakeCredentialResponse> webAuthnMakeCredential(
|
||||
private static GeckoResult<WebAuthnUtils.MakeCredentialResponse> webAuthnMakeCredential(
|
||||
final GeckoBundle credentialBundle,
|
||||
final ByteBuffer userId,
|
||||
final ByteBuffer challenge,
|
||||
@ -376,7 +273,7 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
final ByteBuffer transportList,
|
||||
final GeckoBundle authenticatorSelection,
|
||||
final GeckoBundle extensions) {
|
||||
final ArrayList<WebAuthnPublicCredential> excludeList;
|
||||
final ArrayList<WebAuthnUtils.WebAuthnPublicCredential> excludeList;
|
||||
|
||||
final byte[] challBytes = new byte[challenge.remaining()];
|
||||
final byte[] userBytes = new byte[userId.remaining()];
|
||||
@ -384,7 +281,7 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
challenge.get(challBytes);
|
||||
userId.get(userBytes);
|
||||
|
||||
excludeList = WebAuthnPublicCredential.CombineBuffers(idList, transportList);
|
||||
excludeList = WebAuthnUtils.WebAuthnPublicCredential.CombineBuffers(idList, transportList);
|
||||
} catch (final RuntimeException e) {
|
||||
Log.w(LOGTAG, "Couldn't extract nio byte arrays!", e);
|
||||
return GeckoResult.fromException(new WebAuthnTokenManager.Exception("UNKNOWN_ERR"));
|
||||
@ -395,7 +292,7 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
credentialBundle,
|
||||
userBytes,
|
||||
challBytes,
|
||||
excludeList.toArray(new WebAuthnPublicCredential[0]),
|
||||
excludeList.toArray(new WebAuthnUtils.WebAuthnPublicCredential[0]),
|
||||
authenticatorSelection,
|
||||
extensions);
|
||||
} catch (final Exception e) {
|
||||
@ -408,31 +305,6 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI
|
||||
public static class GetAssertionResponse {
|
||||
public final byte[] clientDataJson;
|
||||
public final byte[] keyHandle;
|
||||
public final byte[] authData;
|
||||
public final byte[] signature;
|
||||
public final byte[] userHandle;
|
||||
public final String authenticatorAttachment;
|
||||
|
||||
public GetAssertionResponse(
|
||||
final byte[] clientDataJson,
|
||||
final byte[] keyHandle,
|
||||
final byte[] authData,
|
||||
final byte[] signature,
|
||||
final byte[] userHandle,
|
||||
final String authenticatorAttachment) {
|
||||
this.clientDataJson = clientDataJson;
|
||||
this.keyHandle = keyHandle;
|
||||
this.authData = authData;
|
||||
this.signature = signature;
|
||||
this.userHandle = userHandle;
|
||||
this.authenticatorAttachment = authenticatorAttachment;
|
||||
}
|
||||
}
|
||||
|
||||
private static WebAuthnTokenManager.Exception parseErrorResponse(
|
||||
final AuthenticatorResponse response) {
|
||||
if (!(response instanceof AuthenticatorErrorResponse)) {
|
||||
@ -447,9 +319,9 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
return new WebAuthnTokenManager.Exception(responseData.getErrorCode().name());
|
||||
}
|
||||
|
||||
private static GeckoResult<GetAssertionResponse> getAssertion(
|
||||
private static GeckoResult<WebAuthnUtils.GetAssertionResponse> getAssertion(
|
||||
final byte[] challenge,
|
||||
final WebAuthnTokenManager.WebAuthnPublicCredential[] allowList,
|
||||
final WebAuthnUtils.WebAuthnPublicCredential[] allowList,
|
||||
final GeckoBundle assertionBundle,
|
||||
final GeckoBundle extensions) {
|
||||
|
||||
@ -460,12 +332,12 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
|
||||
final List<PublicKeyCredentialDescriptor> allowedList =
|
||||
new ArrayList<PublicKeyCredentialDescriptor>();
|
||||
for (final WebAuthnTokenManager.WebAuthnPublicCredential cred : allowList) {
|
||||
for (final WebAuthnUtils.WebAuthnPublicCredential cred : allowList) {
|
||||
allowedList.add(
|
||||
new PublicKeyCredentialDescriptor(
|
||||
PublicKeyCredentialType.PUBLIC_KEY.toString(),
|
||||
cred.id,
|
||||
getTransportsForByte(cred.transports)));
|
||||
WebAuthnUtils.getTransportsForByte(cred.transports)));
|
||||
}
|
||||
|
||||
final AuthenticationExtensions.Builder extBuilder = new AuthenticationExtensions.Builder();
|
||||
@ -505,7 +377,7 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
intentTask = fidoClient.getSignPendingIntent(requestOptions);
|
||||
}
|
||||
|
||||
final GeckoResult<GetAssertionResponse> result = new GeckoResult<>();
|
||||
final GeckoResult<WebAuthnUtils.GetAssertionResponse> result = new GeckoResult<>();
|
||||
intentTask.addOnSuccessListener(
|
||||
pendingIntent -> {
|
||||
GeckoRuntime.getInstance()
|
||||
@ -539,46 +411,19 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
}
|
||||
|
||||
final AuthenticatorAssertionResponse responseData =
|
||||
(AuthenticatorAssertionResponse) publicKeyCredentialData.getResponse();
|
||||
|
||||
Log.d(
|
||||
LOGTAG,
|
||||
"key handle: "
|
||||
+ Base64.encodeToString(
|
||||
publicKeyCredentialData.getRawId(), Base64.DEFAULT));
|
||||
Log.d(
|
||||
LOGTAG,
|
||||
"clientDataJSON: "
|
||||
+ Base64.encodeToString(
|
||||
responseData.getClientDataJSON(), Base64.DEFAULT));
|
||||
Log.d(
|
||||
LOGTAG,
|
||||
"auth data: "
|
||||
+ Base64.encodeToString(
|
||||
responseData.getAuthenticatorData(), Base64.DEFAULT));
|
||||
Log.d(
|
||||
LOGTAG,
|
||||
"signature: "
|
||||
+ Base64.encodeToString(responseData.getSignature(), Base64.DEFAULT));
|
||||
Log.d(
|
||||
LOGTAG,
|
||||
"authenticatorAttachment :"
|
||||
+ publicKeyCredentialData.getAuthenticatorAttachment());
|
||||
|
||||
// Nullable field
|
||||
byte[] userHandle = responseData.getUserHandle();
|
||||
if (userHandle == null) {
|
||||
userHandle = new byte[0];
|
||||
}
|
||||
|
||||
result.complete(
|
||||
new WebAuthnTokenManager.GetAssertionResponse(
|
||||
responseData.getClientDataJSON(),
|
||||
publicKeyCredentialData.getRawId(),
|
||||
responseData.getAuthenticatorData(),
|
||||
responseData.getSignature(),
|
||||
userHandle,
|
||||
publicKeyCredentialData.getAuthenticatorAttachment()));
|
||||
(AuthenticatorAssertionResponse) response;
|
||||
final WebAuthnUtils.GetAssertionResponse assertionResponse =
|
||||
new WebAuthnUtils.GetAssertionResponse.Builder()
|
||||
.setClientDataJson(responseData.getClientDataJSON())
|
||||
.setKeyHandle(publicKeyCredentialData.getRawId())
|
||||
.setAuthData(responseData.getAuthenticatorData())
|
||||
.setSignature(responseData.getSignature())
|
||||
.setUserHandle(responseData.getUserHandle())
|
||||
.setAuthenticatorAttachment(
|
||||
publicKeyCredentialData.getAuthenticatorAttachment())
|
||||
.build();
|
||||
Log.d(LOGTAG, "GetAssertionResponse: " + assertionResponse.toString());
|
||||
result.complete(assertionResponse);
|
||||
},
|
||||
e -> {
|
||||
Log.w(LOGTAG, "Failed to get FIDO intent", e);
|
||||
@ -590,18 +435,18 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static GeckoResult<GetAssertionResponse> webAuthnGetAssertion(
|
||||
private static GeckoResult<WebAuthnUtils.GetAssertionResponse> webAuthnGetAssertion(
|
||||
final ByteBuffer challenge,
|
||||
final Object[] idList,
|
||||
final ByteBuffer transportList,
|
||||
final GeckoBundle assertionBundle,
|
||||
final GeckoBundle extensions) {
|
||||
final ArrayList<WebAuthnPublicCredential> allowList;
|
||||
final ArrayList<WebAuthnUtils.WebAuthnPublicCredential> allowList;
|
||||
|
||||
final byte[] challBytes = new byte[challenge.remaining()];
|
||||
try {
|
||||
challenge.get(challBytes);
|
||||
allowList = WebAuthnPublicCredential.CombineBuffers(idList, transportList);
|
||||
allowList = WebAuthnUtils.WebAuthnPublicCredential.CombineBuffers(idList, transportList);
|
||||
} catch (final RuntimeException e) {
|
||||
Log.w(LOGTAG, "Couldn't extract nio byte arrays!", e);
|
||||
return GeckoResult.fromException(new WebAuthnTokenManager.Exception("UNKNOWN_ERR"));
|
||||
@ -610,7 +455,7 @@ import org.mozilla.gecko.util.GeckoBundle;
|
||||
try {
|
||||
return getAssertion(
|
||||
challBytes,
|
||||
allowList.toArray(new WebAuthnPublicCredential[0]),
|
||||
allowList.toArray(new WebAuthnUtils.WebAuthnPublicCredential[0]),
|
||||
assertionBundle,
|
||||
extensions);
|
||||
} catch (final java.lang.Exception e) {
|
||||
|
@ -82,6 +82,7 @@ classes_with_WrapForJNI = [
|
||||
"SurfaceTextureListener",
|
||||
"TelemetryUtils",
|
||||
"WebAuthnTokenManager",
|
||||
"WebAuthnUtils",
|
||||
"WebMessage",
|
||||
"WebNotification",
|
||||
"WebNotificationDelegate",
|
||||
|
Loading…
Reference in New Issue
Block a user