summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pdf-over-commons/src/main/java/at/asit/pdfover/commons/Constants.java6
-rw-r--r--pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/MobileBKUConnector.java64
-rw-r--r--pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUEnterNumberComposite.java3
-rw-r--r--pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUEnterTANComposite.java80
-rw-r--r--pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUFido2Composite.java102
-rw-r--r--pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUFingerprintComposite.java3
-rw-r--r--pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUQRComposite.java3
-rw-r--r--pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/WaitingForAppComposite.java4
-rw-r--r--pdf-over-gui/src/main/java/at/asit/pdfover/gui/utils/SWTUtils.java7
-rw-r--r--pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/states/MobileBKUState.java85
-rw-r--r--pdf-over-gui/src/main/resources/at/asit/pdfover/gui/messages.properties2
-rw-r--r--pdf-over-gui/src/main/resources/at/asit/pdfover/gui/messages_de.properties2
-rw-r--r--pdf-over-gui/src/main/resources/img/fido_logo.pngbin0 -> 25056 bytes
-rw-r--r--pdf-over-gui/src/main/resources/img/webauthn-logo.pngbin0 -> 121670 bytes
14 files changed, 254 insertions, 107 deletions
diff --git a/pdf-over-commons/src/main/java/at/asit/pdfover/commons/Constants.java b/pdf-over-commons/src/main/java/at/asit/pdfover/commons/Constants.java
index 9c6d2111..c3d1eb84 100644
--- a/pdf-over-commons/src/main/java/at/asit/pdfover/commons/Constants.java
+++ b/pdf-over-commons/src/main/java/at/asit/pdfover/commons/Constants.java
@@ -351,6 +351,12 @@ public class Constants {
/** Mobile phone image resource */
public static final String RES_IMG_MOBILE = "/img/handy.png";
+ /** FIDO2 logo resource */
+ public static final String RES_IMG_FIDO2 = "/img/fido_logo.png";
+
+ /** WebAuthN logo resource */
+ public static final String RES_IMG_WEBAUTHN = "/img/webauthn-logo.png";
+
/** Package resource path */
public static String RES_PKG_PATH = "/at/asit/pdfover/gui/";
diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/MobileBKUConnector.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/MobileBKUConnector.java
index 1748f631..78943eee 100644
--- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/MobileBKUConnector.java
+++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/bku/MobileBKUConnector.java
@@ -47,10 +47,6 @@ import at.asit.pdfover.signer.BkuSlConnector;
import at.asit.pdfover.signer.SignatureException;
import at.asit.pdfover.signer.UserCancelledException;
import at.asit.pdfover.signer.pdfas.PdfAs4SLRequest;
-import at.asit.webauthn.PublicKeyCredentialRequestOptions;
-import at.asit.webauthn.WebAuthN;
-import at.asit.webauthn.exceptions.WebAuthNOperationFailed;
-import at.asit.webauthn.exceptions.WebAuthNUserCancelled;
import static at.asit.pdfover.commons.Constants.ISNOTNULL;
@@ -353,38 +349,36 @@ public class MobileBKUConnector implements BkuSlConnector {
}
}
if (html.fido2Block != null) {
- // TODO composite for this
- if (WebAuthN.isAvailable()) {
- try {
- var fido2Assertion = PublicKeyCredentialRequestOptions.FromJSONString(html.fido2Block.fidoOptions).get("https://service.a-trust.at");
-
- Base64.Encoder base64 = Base64.getEncoder();
-
- JSONObject aTrustAssertion = new JSONObject();
- aTrustAssertion.put("id", fido2Assertion.id);
- aTrustAssertion.put("rawId", base64.encodeToString(fido2Assertion.rawId));
- aTrustAssertion.put("type", fido2Assertion.type);
- aTrustAssertion.put("extensions", new JSONObject()); // TODO fix extensions in library
-
- JSONObject aTrustAssertionResponse = new JSONObject();
- aTrustAssertion.put("response", aTrustAssertionResponse);
- aTrustAssertionResponse.put("authenticatorData", base64.encodeToString(fido2Assertion.response.authenticatorData));
- aTrustAssertionResponse.put("clientDataJson", base64.encodeToString(fido2Assertion.response.clientDataJSON));
- aTrustAssertionResponse.put("signature", base64.encodeToString(fido2Assertion.response.signature));
- if (fido2Assertion.response.userHandle != null)
- aTrustAssertionResponse.put("userHandle", base64.encodeToString(fido2Assertion.response.userHandle));
- else
- aTrustAssertionResponse.put("userHandle", JSONObject.NULL);
-
- html.fido2Block.setFIDOResult(aTrustAssertion.toString());
- return buildFormSubmit(html, "#FidoContinue");
- } catch (WebAuthNUserCancelled e) {
- log.debug("WebAuthN authentication cancelled by user");
- throw new UserCancelledException();
- } catch (WebAuthNOperationFailed e) {
- log.warn("WebAuthN authentication failed", e);
- }
+
+ var fido2Result = this.state.promptUserForFIDO2Auth(html.fido2Block.fidoOptions, html.signatureDataLink, html.smsTanLink != null);
+
+ switch (fido2Result.type) {
+ case TO_SMS: return new HttpGet(html.smsTanLink);
+ case CREDENTIAL: break;
}
+
+ var fido2Assertion = ISNOTNULL(fido2Result.credential);
+
+ Base64.Encoder base64 = Base64.getEncoder();
+
+ JSONObject aTrustAssertion = new JSONObject();
+ aTrustAssertion.put("id", fido2Assertion.id);
+ aTrustAssertion.put("rawId", base64.encodeToString(fido2Assertion.rawId));
+ aTrustAssertion.put("type", fido2Assertion.type);
+ aTrustAssertion.put("extensions", new JSONObject()); // TODO fix extensions in library
+
+ JSONObject aTrustAssertionResponse = new JSONObject();
+ aTrustAssertion.put("response", aTrustAssertionResponse);
+ aTrustAssertionResponse.put("authenticatorData", base64.encodeToString(fido2Assertion.response.authenticatorData));
+ aTrustAssertionResponse.put("clientDataJson", base64.encodeToString(fido2Assertion.response.clientDataJSON));
+ aTrustAssertionResponse.put("signature", base64.encodeToString(fido2Assertion.response.signature));
+ if (fido2Assertion.response.userHandle != null)
+ aTrustAssertionResponse.put("userHandle", base64.encodeToString(fido2Assertion.response.userHandle));
+ else
+ aTrustAssertionResponse.put("userHandle", JSONObject.NULL);
+
+ html.fido2Block.setFIDOResult(aTrustAssertion.toString());
+ return buildFormSubmit(html, "#FidoContinue");
}
throw new IllegalStateException("No top-level block is set? Something has gone terribly wrong.");
}
diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUEnterNumberComposite.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUEnterNumberComposite.java
index 575c2ad7..d5980229 100644
--- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUEnterNumberComposite.java
+++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUEnterNumberComposite.java
@@ -13,7 +13,7 @@
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
-package at.asit.pdfover.gui.composites;
+package at.asit.pdfover.gui.composites.mobilebku;
// Imports
import org.eclipse.swt.SWT;
@@ -33,6 +33,7 @@ import org.slf4j.LoggerFactory;
import at.asit.pdfover.commons.Constants;
import at.asit.pdfover.gui.bku.OLDmobile.MobileBKUHelper;
+import at.asit.pdfover.gui.composites.StateComposite;
import at.asit.pdfover.gui.exceptions.InvalidPasswordException;
import at.asit.pdfover.gui.utils.SWTUtils;
import at.asit.pdfover.commons.Messages;
diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUEnterTANComposite.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUEnterTANComposite.java
index 83913c74..28aaf4c7 100644
--- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUEnterTANComposite.java
+++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUEnterTANComposite.java
@@ -13,7 +13,7 @@
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
-package at.asit.pdfover.gui.composites;
+package at.asit.pdfover.gui.composites.mobilebku;
// Imports
import java.net.URI;
@@ -44,6 +44,7 @@ import com.beust.jcommander.internal.Nullable;
import at.asit.pdfover.commons.Constants;
import at.asit.pdfover.commons.Messages;
import at.asit.pdfover.gui.bku.OLDmobile.ATrustStatus;
+import at.asit.pdfover.gui.composites.StateComposite;
import at.asit.pdfover.gui.utils.SWTUtils;
import at.asit.pdfover.gui.workflow.states.State;
@@ -52,42 +53,28 @@ import at.asit.pdfover.gui.workflow.states.State;
*/
public class MobileBKUEnterTANComposite extends StateComposite {
- /**
- *
- */
- private final class OkSelectionListener extends SelectionAdapter {
-
- @Override
- public void widgetSelected(SelectionEvent e) {
- if(!MobileBKUEnterTANComposite.this.btn_ok.getEnabled()) {
- return;
- }
+ private void validateAndConfirmTAN() {
+ String tan = this.txt_tan.getText();
- String tan = MobileBKUEnterTANComposite.this.txt_tan.getText();
+ tan = tan.trim();
- tan = tan.trim();
-
- if (tan.isEmpty()) {
- MobileBKUEnterTANComposite.this.setMessage(Messages
- .getString("error.NoTan"));
- return;
- }
-
- if (MobileBKUEnterTANComposite.this.refVal.startsWith(tan)) {
- MobileBKUEnterTANComposite.this.setMessage(Messages
- .getString("error.EnteredReferenceValue"));
- return;
- }
+ if (tan.isEmpty()) {
+ this.setMessage(Messages.getString("error.NoTan"));
+ return;
+ }
- if (tan.length() > 6) {
- MobileBKUEnterTANComposite.this.setMessage(Messages
- .getString("error.TanTooLong"));
- return;
- }
+ if (MobileBKUEnterTANComposite.this.refVal.startsWith(tan)) {
+ this.setMessage(Messages.getString("error.EnteredReferenceValue"));
+ return;
+ }
- MobileBKUEnterTANComposite.this.tan = tan;
- MobileBKUEnterTANComposite.this.userAck = true;
+ if (tan.length() > 6) {
+ this.setMessage(Messages.getString("error.TanTooLong"));
+ return;
}
+
+ this.tan = tan;
+ this.userAck = true;
}
/**
@@ -270,29 +257,16 @@ public class MobileBKUEnterTANComposite extends StateComposite {
SWTUtils.anchor(txt_tan).left(50,10).right(100,-20).top(50,10);
this.txt_tan.setEditable(true);
- this.txt_tan.addTraverseListener(new TraverseListener() {
- @Override
- public void keyTraversed(TraverseEvent e) {
- if (e.detail == SWT.TRAVERSE_RETURN) {
- if(MobileBKUEnterTANComposite.this.btn_ok.isEnabled()) {
- (new OkSelectionListener()).widgetSelected(null);
- }
- }
+ this.txt_tan.addTraverseListener((e) -> {
+ if (e.detail == SWT.TRAVERSE_RETURN) {
+ validateAndConfirmTAN();
}
});
- this.txt_tan.addModifyListener(new ModifyListener() {
- @Override
- public void modifyText(ModifyEvent e) {
-
- String text = MobileBKUEnterTANComposite.this.txt_tan.getText();
- //log.debug("Current TAN: " + text);
- if (text.length() > 3
- && MobileBKUEnterTANComposite.this.getRefVal()
- .startsWith(text.trim())) {
- MobileBKUEnterTANComposite.this.setMessage(Messages.getString("error.EnteredReferenceValue"));
- }
- }
+ this.txt_tan.addModifyListener((e) -> {
+ String text = this.txt_tan.getText();
+ if (text.length() > 3 && this.getRefVal().startsWith(text.trim()))
+ this.setMessage(Messages.getString("error.EnteredReferenceValue"));
});
this.lnk_sig_data = new Link(containerComposite, SWT.NATIVE | SWT.RESIZE);
@@ -302,7 +276,7 @@ public class MobileBKUEnterTANComposite extends StateComposite {
this.btn_ok = new Button(containerComposite, SWT.NATIVE);
SWTUtils.anchor(btn_ok).right(100,-20).bottom(100,-20);
- this.btn_ok.addSelectionListener(new OkSelectionListener());
+ SWTUtils.addSelectionListener(btn_ok, (e) -> { validateAndConfirmTAN(); });
this.btn_cancel = new Button(containerComposite, SWT.NATIVE);
SWTUtils.anchor(btn_cancel).right(btn_ok, -20).bottom(100, -20);
diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUFido2Composite.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUFido2Composite.java
new file mode 100644
index 00000000..f303d6c3
--- /dev/null
+++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUFido2Composite.java
@@ -0,0 +1,102 @@
+package at.asit.pdfover.gui.composites.mobilebku;
+
+import javax.annotation.Nonnull;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.asit.pdfover.commons.Constants;
+import at.asit.pdfover.gui.composites.StateComposite;
+import at.asit.pdfover.gui.utils.SWTUtils;
+import at.asit.pdfover.gui.workflow.states.State;
+import at.asit.webauthn.PublicKeyCredential;
+import at.asit.webauthn.PublicKeyCredentialRequestOptions;
+import at.asit.webauthn.WebAuthN;
+import at.asit.webauthn.exceptions.WebAuthNOperationFailed;
+import at.asit.webauthn.exceptions.WebAuthNUserCancelled;
+import at.asit.webauthn.responsefields.AuthenticatorAssertionResponse;
+
+public class MobileBKUFido2Composite extends StateComposite {
+ private static final Logger log = LoggerFactory.getLogger(MobileBKUFido2Composite.class);
+
+ private @Nonnull String fido2OptionsString = "";
+
+ private PublicKeyCredential<AuthenticatorAssertionResponse> credential;
+ private boolean userCancel;
+ private boolean userSms;
+
+ private Button btn_authenticate;
+
+ public void initialize(@Nonnull String fido2Options) {
+ this.fido2OptionsString = fido2Options;
+ this.credential = null;
+ this.userCancel = this.userSms = false;
+ this.btn_authenticate.setEnabled(WebAuthN.isAvailable());
+ }
+
+ public boolean isDone() { return ((this.credential != null) || this.userCancel || this.userSms); }
+ public PublicKeyCredential<AuthenticatorAssertionResponse> getResultingCredential() { return this.credential; }
+ public boolean wasUserCancelClicked() { return userCancel; }
+ public boolean wasUserSMSClicked() { return userSms; }
+
+ public MobileBKUFido2Composite(Composite parent, int style, State state) {
+ super(parent, style, state);
+ setLayout(new FormLayout());
+
+ final Composite containerComposite = new Composite(this, SWT.NATIVE);
+ containerComposite.addPaintListener((e) -> {
+ Rectangle clientArea = containerComposite.getClientArea();
+ e.gc.setForeground(Constants.MAINBAR_ACTIVE_BACK_DARK);
+ e.gc.setLineWidth(3);
+ e.gc.setLineStyle(SWT.LINE_SOLID);
+ e.gc.drawRoundRectangle(clientArea.x, clientArea.y,
+ clientArea.width - 2, clientArea.height - 2, 10, 10);
+
+ });
+ containerComposite.setLayout(new FormLayout());
+ SWTUtils.anchor(containerComposite).top(50, -120).bottom(50, 120).left(50, -200).right(50, 200);
+
+ ImageData webauthnLogoImg = new ImageData(this.getClass().getResourceAsStream(Constants.RES_IMG_WEBAUTHN));
+ Label webauthnLogo = new Label(containerComposite, SWT.NATIVE);
+ SWTUtils.anchor(webauthnLogo).top(0, 10).right(100, -10).height(50).width(187);
+ webauthnLogo.setImage(new Image(getDisplay(), webauthnLogoImg.scaledTo(187, 50)));
+
+ ImageData fidoLogoImg = new ImageData(this.getClass().getResourceAsStream(Constants.RES_IMG_FIDO2));
+ Label fidoLogo = new Label(containerComposite, SWT.NATIVE);
+ SWTUtils.anchor(fidoLogo).top(webauthnLogo, 10).right(100, -10).height(50).width(81);
+ fidoLogo.setImage(new Image(getDisplay(), fidoLogoImg.scaledTo(81, 50)));
+
+ this.btn_authenticate = new Button(containerComposite, SWT.NATIVE);
+ SWTUtils.anchor(btn_authenticate).top(50, -10).left(0, 90).right(100, -90);
+ SWTUtils.addSelectionListener(btn_authenticate, () -> {
+ SWTUtils.setLocalizedText(btn_authenticate, "common.working");
+ btn_authenticate.setEnabled(false);
+ try {
+ /* let the click process first so we don't steal back focus from the fido2 popup */
+ try { Thread.sleep(10); } catch (InterruptedException e) {}
+ this.credential = PublicKeyCredentialRequestOptions.FromJSONString(this.fido2OptionsString).get("https://service.a-trust.at");
+ } catch (WebAuthNUserCancelled e) {
+ this.userCancel = true;
+ } catch (WebAuthNOperationFailed e) {
+ // TODO
+ log.error("webauthn fail", e);
+ } finally { btn_authenticate.setEnabled(true); reloadResources(); }
+ });
+ }
+
+ @Override protected void checkSubclass() {}
+ @Override public void doLayout() { getShell().setDefaultButton(this.btn_authenticate); }
+
+ @Override
+ public void reloadResources() {
+ SWTUtils.setLocalizedText(btn_authenticate, "mobileBKU.authorize");
+ }
+}
diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUFingerprintComposite.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUFingerprintComposite.java
index c0561fe4..14ca1dc7 100644
--- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUFingerprintComposite.java
+++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUFingerprintComposite.java
@@ -13,7 +13,7 @@
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
-package at.asit.pdfover.gui.composites;
+package at.asit.pdfover.gui.composites.mobilebku;
// Imports
import org.eclipse.swt.SWT;
@@ -34,6 +34,7 @@ import org.slf4j.LoggerFactory;
import at.asit.pdfover.commons.Constants;
import at.asit.pdfover.commons.Messages;
+import at.asit.pdfover.gui.composites.StateComposite;
import at.asit.pdfover.gui.utils.SWTUtils;
import at.asit.pdfover.gui.workflow.states.State;
diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUQRComposite.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUQRComposite.java
index 91765610..1b2600c8 100644
--- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUQRComposite.java
+++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/MobileBKUQRComposite.java
@@ -13,7 +13,7 @@
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
-package at.asit.pdfover.gui.composites;
+package at.asit.pdfover.gui.composites.mobilebku;
// Imports
import java.io.ByteArrayInputStream;
@@ -40,6 +40,7 @@ import org.slf4j.LoggerFactory;
import at.asit.pdfover.commons.Constants;
import at.asit.pdfover.commons.Messages;
+import at.asit.pdfover.gui.composites.StateComposite;
import at.asit.pdfover.gui.utils.SWTUtils;
import at.asit.pdfover.gui.workflow.states.State;
diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/WaitingForAppComposite.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/WaitingForAppComposite.java
index 7d5b4dfd..ed311957 100644
--- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/WaitingForAppComposite.java
+++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/mobilebku/WaitingForAppComposite.java
@@ -13,7 +13,7 @@
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
-package at.asit.pdfover.gui.composites;
+package at.asit.pdfover.gui.composites.mobilebku;
// Imports
@@ -22,6 +22,8 @@ import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ProgressBar;
+
+import at.asit.pdfover.gui.composites.StateComposite;
import at.asit.pdfover.gui.utils.SWTUtils;
import at.asit.pdfover.gui.workflow.states.State;
import org.eclipse.swt.widgets.Button;
diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/utils/SWTUtils.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/utils/SWTUtils.java
index d276ecd6..c82e0309 100644
--- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/utils/SWTUtils.java
+++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/utils/SWTUtils.java
@@ -178,6 +178,13 @@ public final class SWTUtils {
}
}
+ /**
+ * @see SWTUtils#addSelectionListener(Object, Consumer)
+ */
+ public static void addSelectionListener(Object swtObj, Runnable callback) {
+ addSelectionListener(swtObj, (e) -> { callback.run(); });
+ }
+
public static void openURL(@Nullable URI uri) {
try {
if (uri == null) return;
diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/states/MobileBKUState.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/states/MobileBKUState.java
index 48415ab5..f9a0d967 100644
--- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/states/MobileBKUState.java
+++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/states/MobileBKUState.java
@@ -29,6 +29,8 @@ import javax.annotation.Nullable;
// Imports
import at.asit.pdfover.signer.UserCancelledException;
import at.asit.pdfover.signer.pdfas.PdfAs4SigningState;
+import at.asit.webauthn.PublicKeyCredential;
+import at.asit.webauthn.responsefields.AuthenticatorAssertionResponse;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
@@ -45,18 +47,21 @@ import at.asit.pdfover.gui.MainWindowBehavior;
import at.asit.pdfover.gui.bku.MobileBKUConnector;
import at.asit.pdfover.gui.bku.OLDmobile.ATrustHandler;
import at.asit.pdfover.gui.bku.OLDmobile.ATrustStatus;
-import at.asit.pdfover.gui.composites.MobileBKUEnterNumberComposite;
-import at.asit.pdfover.gui.composites.MobileBKUEnterTANComposite;
-import at.asit.pdfover.gui.composites.MobileBKUFingerprintComposite;
-import at.asit.pdfover.gui.composites.MobileBKUQRComposite;
import at.asit.pdfover.gui.composites.WaitingComposite;
-import at.asit.pdfover.gui.composites.WaitingForAppComposite;
+import at.asit.pdfover.gui.composites.mobilebku.MobileBKUEnterNumberComposite;
+import at.asit.pdfover.gui.composites.mobilebku.MobileBKUEnterTANComposite;
+import at.asit.pdfover.gui.composites.mobilebku.MobileBKUFido2Composite;
+import at.asit.pdfover.gui.composites.mobilebku.MobileBKUFingerprintComposite;
+import at.asit.pdfover.gui.composites.mobilebku.MobileBKUQRComposite;
+import at.asit.pdfover.gui.composites.mobilebku.WaitingForAppComposite;
import at.asit.pdfover.gui.controls.Dialog.BUTTONS;
import at.asit.pdfover.gui.controls.ErrorDialog;
import at.asit.pdfover.commons.Messages;
import at.asit.pdfover.gui.workflow.StateMachine;
import at.asit.pdfover.gui.workflow.config.ConfigurationManager;
+import static at.asit.pdfover.commons.Constants.ISNOTNULL;
+
/**
* Logical state for performing the BKU Request to the A-Trust Mobile BKU
*/
@@ -138,6 +143,16 @@ public class MobileBKUState extends State {
return this.mobileBKUFingerprintComposite;
}
+ MobileBKUFido2Composite mobileBKUFido2Composite = null;
+ MobileBKUFido2Composite getMobileBKUFido2Composite() {
+ if (this.mobileBKUFido2Composite == null) {
+ this.mobileBKUFido2Composite = getStateMachine()
+ .createComposite(MobileBKUFido2Composite.class, SWT.RESIZE, this);
+ }
+
+ return this.mobileBKUFido2Composite;
+ }
+
/**
* @return the signingState
*/
@@ -330,8 +345,8 @@ public class MobileBKUState extends State {
private SMSTanResult(@Nonnull ResultType type) { this.type = type; this.smsTan = null; }
}
- public SMSTanResult getSMSTanFromUser(final @Nonnull String referenceValue, final int triesRemaining, final @Nullable URI signatureDataURI, final boolean showFido2, final @Nullable String errorMessage) throws UserCancelledException {
- return Display.getDefault().syncCall(() -> {
+ public @Nonnull SMSTanResult getSMSTanFromUser(final @Nonnull String referenceValue, final int triesRemaining, final @Nullable URI signatureDataURI, final boolean showFido2, final @Nullable String errorMessage) throws UserCancelledException {
+ return ISNOTNULL(Display.getDefault().syncCall(() -> {
MobileBKUEnterTANComposite tan = getMobileBKUEnterTANComposite();
tan.reset();
@@ -357,7 +372,7 @@ public class MobileBKUState extends State {
return new SMSTanResult(SMSTanResult.ResultType.TO_FIDO2);
return new SMSTanResult(tan.getTan());
- });
+ }));
}
/**
@@ -398,8 +413,8 @@ public class MobileBKUState extends State {
UPDATE
};
- public QRResult waitForQRCodeResult() throws UserCancelledException {
- return Display.getDefault().syncCall(() -> {
+ public @Nonnull QRResult waitForQRCodeResult() throws UserCancelledException {
+ return ISNOTNULL(Display.getDefault().syncCall(() -> {
MobileBKUQRComposite qr = getMobileBKUQRComposite();
Display display = getStateMachine().getMainShell().getDisplay();
@@ -423,7 +438,7 @@ public class MobileBKUState extends State {
return QRResult.TO_FIDO2;
return QRResult.UPDATE;
- });
+ }));
}
/**
@@ -458,8 +473,8 @@ public class MobileBKUState extends State {
UPDATE
};
- public AppOpenResult waitForAppOpen() throws UserCancelledException {
- return Display.getDefault().syncCall(() -> {
+ public @Nonnull AppOpenResult waitForAppOpen() throws UserCancelledException {
+ return ISNOTNULL(Display.getDefault().syncCall(() -> {
WaitingForAppComposite wfa = getWaitingForAppComposite();
Display display = wfa.getDisplay();
@@ -482,7 +497,7 @@ public class MobileBKUState extends State {
return AppOpenResult.TO_FIDO2;
return AppOpenResult.UPDATE;
- });
+ }));
}
/**
@@ -562,10 +577,50 @@ public class MobileBKUState extends State {
* @return a boolean true if the user has pressed the sms tan button
*/
public boolean getSMSStatus() {
-
return this.getMobileBKUFingerprintComposite().isUserSMS();
}
+ public static class FIDO2Result {
+ public static enum ResultType { TO_SMS, CREDENTIAL };
+ public final @Nonnull ResultType type;
+ public final @Nullable PublicKeyCredential<AuthenticatorAssertionResponse> credential;
+
+ private FIDO2Result(@Nonnull ResultType type) { this.type = type; this.credential = null; }
+ private FIDO2Result(@Nonnull PublicKeyCredential<AuthenticatorAssertionResponse> cred) { this.type = ResultType.CREDENTIAL; this.credential = cred; }
+ }
+
+ /**
+ * prompts user for fido2 auth and blocks until result is available
+ * @param fido2Options JSON data from A-Trust
+ * @return
+ * @throws UserCancelledException
+ */
+ public @Nonnull FIDO2Result promptUserForFIDO2Auth(final @Nonnull String fido2Options, @Nullable URI signatureDataURI, final boolean showSmsTan) throws UserCancelledException {
+ return ISNOTNULL(Display.getDefault().syncCall(() -> {
+ MobileBKUFido2Composite fido2 = getMobileBKUFido2Composite();
+ fido2.initialize(fido2Options);
+ // TODO signature data, sms tan support
+
+ getStateMachine().display(fido2);
+
+ Display display = fido2.getDisplay();
+ while (!fido2.isDone()) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+
+ getStateMachine().display(this.getWaitingComposite());
+
+ if (fido2.wasUserCancelClicked())
+ throw new UserCancelledException();
+
+ if (fido2.wasUserSMSClicked())
+ return new FIDO2Result(FIDO2Result.ResultType.TO_SMS);
+
+ return new FIDO2Result(ISNOTNULL(fido2.getResultingCredential()));
+ }));
+ }
+
/*
* (non-Javadoc)
*
diff --git a/pdf-over-gui/src/main/resources/at/asit/pdfover/gui/messages.properties b/pdf-over-gui/src/main/resources/at/asit/pdfover/gui/messages.properties
index 2d5d74f1..524f6c32 100644
--- a/pdf-over-gui/src/main/resources/at/asit/pdfover/gui/messages.properties
+++ b/pdf-over-gui/src/main/resources/at/asit/pdfover/gui/messages.properties
@@ -114,6 +114,7 @@ common.browse=&Browse
common.info=Information
common.open=Open
common.warning=Warning
+common.working=Working...
config.About=A&bout %s
config.AboutText=This software is freely provided by A-SIT under the conditions of the EUPL.\nTerms and details at <a>https\://technology.a-sit.at/en/terms-of-a-license/</a>.\n\nNote that components may have different licenses, partly restricting their free use to EUPL-licensed software.
config.LicenseURL=https://technology.a-sit.at/en/terms-of-a-license/
@@ -216,6 +217,7 @@ mobileBKU.tan_tries_exceeded=TAN tries exceeded, request a new TAN?
mobileBKU.wrong_tan=TAN not accepted
mobileBKU.rememberPassword=Re&member
mobileBKU.rememberPasswordNote=If you check this, you will not be prompted for your password again until you re-start PDF-Over
+mobileBKU.authorize=Begin authorization
output.file_ask_overwrite=File %s already exists, do you want to overwrite it?
output.link_open_message=You can open the signed file <a>here</a>.
output.link_save_message=You can save the signed file
diff --git a/pdf-over-gui/src/main/resources/at/asit/pdfover/gui/messages_de.properties b/pdf-over-gui/src/main/resources/at/asit/pdfover/gui/messages_de.properties
index a75dfbb4..8173a13a 100644
--- a/pdf-over-gui/src/main/resources/at/asit/pdfover/gui/messages_de.properties
+++ b/pdf-over-gui/src/main/resources/at/asit/pdfover/gui/messages_de.properties
@@ -105,6 +105,7 @@ common.browse=&Durchsuchen
common.info=Information
common.open=Öffnen
common.warning=Warnung
+common.working=In Arbeit...
config.About=Ü&ber %s
config.AboutText=Diese Software wird von A-SIT unter den Bedingungen der EUPL frei zur Verfügung gestellt.\nLizenbedingungen unter <a>https://technology.a-sit.at/lizenzbedingungen/</a>.\n\nBeachten Sie, dass Komponenten unter eigenen Lizenzen zur Verfügung gestellt werden, die teilweise nur für EUPL-lizensierte Software zur freien Verwendung vorgesehen sind.
config.LicenseURL=https://technology.a-sit.at/lizenzbedingungen/
@@ -207,6 +208,7 @@ mobileBKU.tan_tries_exceeded=Zu viele TAN-Versuche, neue TAN anfordern?
mobileBKU.wrong_tan=TAN nicht akzeptiert
mobileBKU.rememberPassword=Daten &merken
mobileBKU.rememberPasswordNote=Wählen Sie diese Box aus, um bis zum nächsten Start von PDF-Over nicht erneut gefragt zu werden
+mobileBKU.authorize=Autorisierung starten
output.file_ask_overwrite=Datei %s existiert bereits, wollen Sie sie überschreiben?
output.link_open_message=Sie können das signierte Dokument <a>hier</a> öffnen.
output.link_save_message=Sie können das signierte Dokument speichern
diff --git a/pdf-over-gui/src/main/resources/img/fido_logo.png b/pdf-over-gui/src/main/resources/img/fido_logo.png
new file mode 100644
index 00000000..78ab7806
--- /dev/null
+++ b/pdf-over-gui/src/main/resources/img/fido_logo.png
Binary files differ
diff --git a/pdf-over-gui/src/main/resources/img/webauthn-logo.png b/pdf-over-gui/src/main/resources/img/webauthn-logo.png
new file mode 100644
index 00000000..f9024864
--- /dev/null
+++ b/pdf-over-gui/src/main/resources/img/webauthn-logo.png
Binary files differ