diff options
author | Jakob Heher <jakob.heher@iaik.tugraz.at> | 2022-10-05 16:03:01 +0200 |
---|---|---|
committer | Jakob Heher <jakob.heher@iaik.tugraz.at> | 2022-10-05 16:03:01 +0200 |
commit | 0e45fec2be59e0247aaa27c24ac719f548cd96cb (patch) | |
tree | d75047f4c801a4bbbf38130ff8b64bfafd20e1d0 | |
parent | f180a7e254d204aaa645ff4fd4e5fff7b1d7c47b (diff) | |
download | pdf-over-0e45fec2be59e0247aaa27c24ac719f548cd96cb.tar.gz pdf-over-0e45fec2be59e0247aaa27c24ac719f548cd96cb.tar.bz2 pdf-over-0e45fec2be59e0247aaa27c24ac719f548cd96cb.zip |
fido2 composite
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 Binary files differnew file mode 100644 index 00000000..78ab7806 --- /dev/null +++ b/pdf-over-gui/src/main/resources/img/fido_logo.png diff --git a/pdf-over-gui/src/main/resources/img/webauthn-logo.png b/pdf-over-gui/src/main/resources/img/webauthn-logo.png Binary files differnew file mode 100644 index 00000000..f9024864 --- /dev/null +++ b/pdf-over-gui/src/main/resources/img/webauthn-logo.png |