001package Torello.Browser; 002 003import java.util.*; 004import javax.json.*; 005import javax.json.stream.*; 006import java.io.*; 007 008import java.lang.reflect.Method; 009import java.lang.reflect.Parameter; 010import java.util.function.Function; 011 012import Torello.Java.Additional.*; 013import Torello.Java.JSON.*; 014 015import static Torello.Java.JSON.JFlag.*; 016 017import Torello.Java.StrCmpr; 018import Torello.JavaDoc.StaticFunctional; 019import Torello.JavaDoc.JDHeaderBackgroundImg; 020import Torello.JavaDoc.Excuse; 021 022/** 023 * <SPAN CLASS=COPIEDJDK><B>This domain allows configuring virtual authenticators to test the WebAuthn 024 * API.</B></SPAN> 025 * 026 * <EMBED CLASS='external-html' DATA-FILE-ID=CODE_GEN_NOTE> 027 */ 028@StaticFunctional(Excused={"counter"}, Excuses={Excuse.CONFIGURATION}) 029@JDHeaderBackgroundImg(EmbedTagFileID="WOOD_PLANK_NOTE") 030public class WebAuthn 031{ 032 // ******************************************************************************************** 033 // ******************************************************************************************** 034 // Class Header Stuff 035 // ******************************************************************************************** 036 // ******************************************************************************************** 037 038 039 // No Pubic Constructors 040 private WebAuthn () { } 041 042 // These two Vector's are used by all the "Methods" exported by this class. java.lang.reflect 043 // is used to generate the JSON String's. It saves thousands of lines of Auto-Generated Code. 044 private static final Map<String, Vector<String>> parameterNames = new HashMap<>(); 045 private static final Map<String, Vector<Class<?>>> parameterTypes = new HashMap<>(); 046 047 // Some Methods do not take any parameters - for instance all the "enable()" and "disable()" 048 // I simply could not get ride of RAW-TYPES and UNCHECKED warnings... so there are now, 049 // offically, two empty-vectors. One for String's, and the other for Classes. 050 051 private static final Vector<String> EMPTY_VEC_STR = new Vector<>(); 052 private static final Vector<Class<?>> EMPTY_VEC_CLASS = new Vector<>(); 053 054 static 055 { 056 for (Method m : WebAuthn.class.getMethods()) 057 { 058 // This doesn't work! The parameter names are all "arg0" ... "argN" 059 // It works for java.lang.reflect.Field, BUT NOT java.lang.reflect.Parameter! 060 // 061 // Vector<String> parameterNamesList = new Vector<>(); -- NOPE! 062 063 Vector<Class<?>> parameterTypesList = new Vector<>(); 064 065 for (Parameter p : m.getParameters()) parameterTypesList.add(p.getType()); 066 067 parameterTypes.put( 068 m.getName(), 069 (parameterTypesList.size() > 0) ? parameterTypesList : EMPTY_VEC_CLASS 070 ); 071 } 072 } 073 074 static 075 { 076 Vector<String> v = null; 077 078 parameterNames.put("enable", EMPTY_VEC_STR); 079 080 parameterNames.put("disable", EMPTY_VEC_STR); 081 082 v = new Vector<String>(1); 083 parameterNames.put("addVirtualAuthenticator", v); 084 Collections.addAll(v, new String[] 085 { "options", }); 086 087 v = new Vector<String>(1); 088 parameterNames.put("removeVirtualAuthenticator", v); 089 Collections.addAll(v, new String[] 090 { "authenticatorId", }); 091 092 v = new Vector<String>(2); 093 parameterNames.put("addCredential", v); 094 Collections.addAll(v, new String[] 095 { "authenticatorId", "credential", }); 096 097 v = new Vector<String>(2); 098 parameterNames.put("getCredential", v); 099 Collections.addAll(v, new String[] 100 { "authenticatorId", "credentialId", }); 101 102 v = new Vector<String>(1); 103 parameterNames.put("getCredentials", v); 104 Collections.addAll(v, new String[] 105 { "authenticatorId", }); 106 107 v = new Vector<String>(2); 108 parameterNames.put("removeCredential", v); 109 Collections.addAll(v, new String[] 110 { "authenticatorId", "credentialId", }); 111 112 v = new Vector<String>(1); 113 parameterNames.put("clearCredentials", v); 114 Collections.addAll(v, new String[] 115 { "authenticatorId", }); 116 117 v = new Vector<String>(2); 118 parameterNames.put("setUserVerified", v); 119 Collections.addAll(v, new String[] 120 { "authenticatorId", "isUserVerified", }); 121 122 v = new Vector<String>(2); 123 parameterNames.put("setAutomaticPresenceSimulation", v); 124 Collections.addAll(v, new String[] 125 { "authenticatorId", "enabled", }); 126 } 127 128 129 // ******************************************************************************************** 130 // ******************************************************************************************** 131 // Types - Static Inner Classes 132 // ******************************************************************************************** 133 // ******************************************************************************************** 134 135 // public static class AuthenticatorId => String 136 137 /** <CODE>[No Description Provided by Google]</CODE> */ 138 public static final String[] AuthenticatorProtocol = 139 { "u2f", "ctap2", }; 140 141 /** <CODE>[No Description Provided by Google]</CODE> */ 142 public static final String[] Ctap2Version = 143 { "ctap2_0", "ctap2_1", }; 144 145 /** <CODE>[No Description Provided by Google]</CODE> */ 146 public static final String[] AuthenticatorTransport = 147 { "usb", "nfc", "ble", "cable", "internal", }; 148 149 /** <CODE>[No Description Provided by Google]</CODE> */ 150 public static class VirtualAuthenticatorOptions 151 extends BaseType 152 implements java.io.Serializable 153 { 154 /** For Object Serialization. java.io.Serializable */ 155 protected static final long serialVersionUID = 1; 156 157 public boolean[] optionals() 158 { return new boolean[] { false, true, false, true, true, true, true, true, true, }; } 159 160 /** <CODE>[No Description Provided by Google]</CODE> */ 161 public final String protocol; 162 163 /** 164 * Defaults to ctap2_0. Ignored if |protocol| == u2f. 165 * <BR /> 166 * <BR /><B>OPTIONAL</B> 167 */ 168 public final String ctap2Version; 169 170 /** <CODE>[No Description Provided by Google]</CODE> */ 171 public final String transport; 172 173 /** 174 * Defaults to false. 175 * <BR /> 176 * <BR /><B>OPTIONAL</B> 177 */ 178 public final Boolean hasResidentKey; 179 180 /** 181 * Defaults to false. 182 * <BR /> 183 * <BR /><B>OPTIONAL</B> 184 */ 185 public final Boolean hasUserVerification; 186 187 /** 188 * If set to true, the authenticator will support the largeBlob extension. 189 * https://w3c.github.io/webauthn#largeBlob 190 * Defaults to false. 191 * <BR /> 192 * <BR /><B>OPTIONAL</B> 193 */ 194 public final Boolean hasLargeBlob; 195 196 /** 197 * If set to true, the authenticator will support the credBlob extension. 198 * https://fidoalliance.org/specs/fido-v2.1-rd-20201208/fido-client-to-authenticator-protocol-v2.1-rd-20201208.html#sctn-credBlob-extension 199 * Defaults to false. 200 * <BR /> 201 * <BR /><B>OPTIONAL</B> 202 */ 203 public final Boolean hasCredBlob; 204 205 /** 206 * If set to true, tests of user presence will succeed immediately. 207 * Otherwise, they will not be resolved. Defaults to true. 208 * <BR /> 209 * <BR /><B>OPTIONAL</B> 210 */ 211 public final Boolean automaticPresenceSimulation; 212 213 /** 214 * Sets whether User Verification succeeds or fails for an authenticator. 215 * Defaults to false. 216 * <BR /> 217 * <BR /><B>OPTIONAL</B> 218 */ 219 public final Boolean isUserVerified; 220 221 /** 222 * Constructor 223 * 224 * @param protocol - 225 * 226 * @param ctap2Version Defaults to ctap2_0. Ignored if |protocol| == u2f. 227 * <BR /><B>OPTIONAL</B> 228 * 229 * @param transport - 230 * 231 * @param hasResidentKey Defaults to false. 232 * <BR /><B>OPTIONAL</B> 233 * 234 * @param hasUserVerification Defaults to false. 235 * <BR /><B>OPTIONAL</B> 236 * 237 * @param hasLargeBlob 238 * If set to true, the authenticator will support the largeBlob extension. 239 * https://w3c.github.io/webauthn#largeBlob 240 * Defaults to false. 241 * <BR /><B>OPTIONAL</B> 242 * 243 * @param hasCredBlob 244 * If set to true, the authenticator will support the credBlob extension. 245 * https://fidoalliance.org/specs/fido-v2.1-rd-20201208/fido-client-to-authenticator-protocol-v2.1-rd-20201208.html#sctn-credBlob-extension 246 * Defaults to false. 247 * <BR /><B>OPTIONAL</B> 248 * 249 * @param automaticPresenceSimulation 250 * If set to true, tests of user presence will succeed immediately. 251 * Otherwise, they will not be resolved. Defaults to true. 252 * <BR /><B>OPTIONAL</B> 253 * 254 * @param isUserVerified 255 * Sets whether User Verification succeeds or fails for an authenticator. 256 * Defaults to false. 257 * <BR /><B>OPTIONAL</B> 258 */ 259 public VirtualAuthenticatorOptions( 260 String protocol, String ctap2Version, String transport, Boolean hasResidentKey, 261 Boolean hasUserVerification, Boolean hasLargeBlob, Boolean hasCredBlob, 262 Boolean automaticPresenceSimulation, Boolean isUserVerified 263 ) 264 { 265 // Exception-Check(s) to ensure that if any parameters which are not declared as 266 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 267 268 if (protocol == null) BRDPC.throwNPE("protocol"); 269 if (transport == null) BRDPC.throwNPE("transport"); 270 271 // Exception-Check(s) to ensure that if any parameters which must adhere to a 272 // provided List of Enumerated Values, fails, then IllegalArgumentException shall throw. 273 274 BRDPC.checkIAE("protocol", protocol, "WebAuthn.AuthenticatorProtocol", WebAuthn.AuthenticatorProtocol); 275 BRDPC.checkIAE("ctap2Version", ctap2Version, "WebAuthn.Ctap2Version", WebAuthn.Ctap2Version); 276 BRDPC.checkIAE("transport", transport, "WebAuthn.AuthenticatorTransport", WebAuthn.AuthenticatorTransport); 277 278 this.protocol = protocol; 279 this.ctap2Version = ctap2Version; 280 this.transport = transport; 281 this.hasResidentKey = hasResidentKey; 282 this.hasUserVerification = hasUserVerification; 283 this.hasLargeBlob = hasLargeBlob; 284 this.hasCredBlob = hasCredBlob; 285 this.automaticPresenceSimulation = automaticPresenceSimulation; 286 this.isUserVerified = isUserVerified; 287 } 288 289 /** 290 * JSON Object Constructor 291 * @param jo A Json-Object having data about an instance of {@code 'VirtualAuthenticatorOptions'}. 292 */ 293 public VirtualAuthenticatorOptions (JsonObject jo) 294 { 295 this.protocol = ReadJSON.getString(jo, "protocol", false, true); 296 this.ctap2Version = ReadJSON.getString(jo, "ctap2Version", true, false); 297 this.transport = ReadJSON.getString(jo, "transport", false, true); 298 this.hasResidentKey = ReadBoxedJSON.getBoolean(jo, "hasResidentKey", true); 299 this.hasUserVerification = ReadBoxedJSON.getBoolean(jo, "hasUserVerification", true); 300 this.hasLargeBlob = ReadBoxedJSON.getBoolean(jo, "hasLargeBlob", true); 301 this.hasCredBlob = ReadBoxedJSON.getBoolean(jo, "hasCredBlob", true); 302 this.automaticPresenceSimulation = ReadBoxedJSON.getBoolean(jo, "automaticPresenceSimulation", true); 303 this.isUserVerified = ReadBoxedJSON.getBoolean(jo, "isUserVerified", true); 304 } 305 306 307 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 308 public boolean equals(Object other) 309 { 310 if (other == null) return false; 311 if (other.getClass() != this.getClass()) return false; 312 313 VirtualAuthenticatorOptions o = (VirtualAuthenticatorOptions) other; 314 315 return 316 Objects.equals(this.protocol, o.protocol) 317 && Objects.equals(this.ctap2Version, o.ctap2Version) 318 && Objects.equals(this.transport, o.transport) 319 && Objects.equals(this.hasResidentKey, o.hasResidentKey) 320 && Objects.equals(this.hasUserVerification, o.hasUserVerification) 321 && Objects.equals(this.hasLargeBlob, o.hasLargeBlob) 322 && Objects.equals(this.hasCredBlob, o.hasCredBlob) 323 && Objects.equals(this.automaticPresenceSimulation, o.automaticPresenceSimulation) 324 && Objects.equals(this.isUserVerified, o.isUserVerified); 325 } 326 327 /** Generates a Hash-Code for {@code 'this'} instance */ 328 public int hashCode() 329 { 330 return 331 Objects.hashCode(this.protocol) 332 + Objects.hashCode(this.ctap2Version) 333 + Objects.hashCode(this.transport) 334 + Objects.hashCode(this.hasResidentKey) 335 + Objects.hashCode(this.hasUserVerification) 336 + Objects.hashCode(this.hasLargeBlob) 337 + Objects.hashCode(this.hasCredBlob) 338 + Objects.hashCode(this.automaticPresenceSimulation) 339 + Objects.hashCode(this.isUserVerified); 340 } 341 } 342 343 /** <CODE>[No Description Provided by Google]</CODE> */ 344 public static class Credential 345 extends BaseType 346 implements java.io.Serializable 347 { 348 /** For Object Serialization. java.io.Serializable */ 349 protected static final long serialVersionUID = 1; 350 351 public boolean[] optionals() 352 { return new boolean[] { false, false, true, false, true, false, true, }; } 353 354 /** <CODE>[No Description Provided by Google]</CODE> */ 355 public final String credentialId; 356 357 /** <CODE>[No Description Provided by Google]</CODE> */ 358 public final boolean isResidentCredential; 359 360 /** 361 * Relying Party ID the credential is scoped to. Must be set when adding a 362 * credential. 363 * <BR /> 364 * <BR /><B>OPTIONAL</B> 365 */ 366 public final String rpId; 367 368 /** The ECDSA P-256 private key in PKCS#8 format. (Encoded as a base64 string when passed over JSON) */ 369 public final String privateKey; 370 371 /** 372 * An opaque byte sequence with a maximum size of 64 bytes mapping the 373 * credential to a specific user. (Encoded as a base64 string when passed over JSON) 374 * <BR /> 375 * <BR /><B>OPTIONAL</B> 376 */ 377 public final String userHandle; 378 379 /** 380 * Signature counter. This is incremented by one for each successful 381 * assertion. 382 * See https://w3c.github.io/webauthn/#signature-counter 383 */ 384 public final int signCount; 385 386 /** 387 * The large blob associated with the credential. 388 * See https://w3c.github.io/webauthn/#sctn-large-blob-extension (Encoded as a base64 string when passed over JSON) 389 * <BR /> 390 * <BR /><B>OPTIONAL</B> 391 */ 392 public final String largeBlob; 393 394 /** 395 * Constructor 396 * 397 * @param credentialId - 398 * 399 * @param isResidentCredential - 400 * 401 * @param rpId 402 * Relying Party ID the credential is scoped to. Must be set when adding a 403 * credential. 404 * <BR /><B>OPTIONAL</B> 405 * 406 * @param privateKey The ECDSA P-256 private key in PKCS#8 format. (Encoded as a base64 string when passed over JSON) 407 * 408 * @param userHandle 409 * An opaque byte sequence with a maximum size of 64 bytes mapping the 410 * credential to a specific user. (Encoded as a base64 string when passed over JSON) 411 * <BR /><B>OPTIONAL</B> 412 * 413 * @param signCount 414 * Signature counter. This is incremented by one for each successful 415 * assertion. 416 * See https://w3c.github.io/webauthn/#signature-counter 417 * 418 * @param largeBlob 419 * The large blob associated with the credential. 420 * See https://w3c.github.io/webauthn/#sctn-large-blob-extension (Encoded as a base64 string when passed over JSON) 421 * <BR /><B>OPTIONAL</B> 422 */ 423 public Credential( 424 String credentialId, boolean isResidentCredential, String rpId, String privateKey, 425 String userHandle, int signCount, String largeBlob 426 ) 427 { 428 // Exception-Check(s) to ensure that if any parameters which are not declared as 429 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 430 431 if (credentialId == null) BRDPC.throwNPE("credentialId"); 432 if (privateKey == null) BRDPC.throwNPE("privateKey"); 433 434 this.credentialId = credentialId; 435 this.isResidentCredential = isResidentCredential; 436 this.rpId = rpId; 437 this.privateKey = privateKey; 438 this.userHandle = userHandle; 439 this.signCount = signCount; 440 this.largeBlob = largeBlob; 441 } 442 443 /** 444 * JSON Object Constructor 445 * @param jo A Json-Object having data about an instance of {@code 'Credential'}. 446 */ 447 public Credential (JsonObject jo) 448 { 449 this.credentialId = ReadJSON.getString(jo, "credentialId", false, true); 450 this.isResidentCredential = ReadPrimJSON.getBoolean(jo, "isResidentCredential"); 451 this.rpId = ReadJSON.getString(jo, "rpId", true, false); 452 this.privateKey = ReadJSON.getString(jo, "privateKey", false, true); 453 this.userHandle = ReadJSON.getString(jo, "userHandle", true, false); 454 this.signCount = ReadPrimJSON.getInt(jo, "signCount"); 455 this.largeBlob = ReadJSON.getString(jo, "largeBlob", true, false); 456 } 457 458 459 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 460 public boolean equals(Object other) 461 { 462 if (other == null) return false; 463 if (other.getClass() != this.getClass()) return false; 464 465 Credential o = (Credential) other; 466 467 return 468 Objects.equals(this.credentialId, o.credentialId) 469 && (this.isResidentCredential == o.isResidentCredential) 470 && Objects.equals(this.rpId, o.rpId) 471 && Objects.equals(this.privateKey, o.privateKey) 472 && Objects.equals(this.userHandle, o.userHandle) 473 && (this.signCount == o.signCount) 474 && Objects.equals(this.largeBlob, o.largeBlob); 475 } 476 477 /** Generates a Hash-Code for {@code 'this'} instance */ 478 public int hashCode() 479 { 480 return 481 Objects.hashCode(this.credentialId) 482 + (this.isResidentCredential ? 1 : 0) 483 + Objects.hashCode(this.rpId) 484 + Objects.hashCode(this.privateKey) 485 + Objects.hashCode(this.userHandle) 486 + this.signCount 487 + Objects.hashCode(this.largeBlob); 488 } 489 } 490 491 492 // Counter for keeping the WebSocket Request ID's distinct. 493 private static int counter = 1; 494 495 /** 496 * Enable the WebAuthn domain and start intercepting credential storage and 497 * retrieval with a virtual authenticator. 498 * 499 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 500 * {@link Ret0}></CODE> 501 * 502 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 503 * browser receives the invocation-request. 504 * 505 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 506 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 507 * {@code >} to ensure the Browser Function has run to completion. 508 */ 509 public static Script<String, JsonObject, Ret0> enable() 510 { 511 final int webSocketID = 44000000 + counter++; 512 final boolean[] optionals = new boolean[0]; 513 514 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 515 String requestJSON = WriteJSON.get( 516 parameterTypes.get("enable"), 517 parameterNames.get("enable"), 518 optionals, webSocketID, 519 "WebAuthn.enable" 520 ); 521 522 // This Remote Command does not have a Return-Value. 523 return new Script<> 524 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 525 } 526 527 /** 528 * Disable the WebAuthn domain. 529 * 530 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 531 * {@link Ret0}></CODE> 532 * 533 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 534 * browser receives the invocation-request. 535 * 536 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 537 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 538 * {@code >} to ensure the Browser Function has run to completion. 539 */ 540 public static Script<String, JsonObject, Ret0> disable() 541 { 542 final int webSocketID = 44001000 + counter++; 543 final boolean[] optionals = new boolean[0]; 544 545 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 546 String requestJSON = WriteJSON.get( 547 parameterTypes.get("disable"), 548 parameterNames.get("disable"), 549 optionals, webSocketID, 550 "WebAuthn.disable" 551 ); 552 553 // This Remote Command does not have a Return-Value. 554 return new Script<> 555 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 556 } 557 558 /** 559 * Creates and adds a virtual authenticator. 560 * 561 * @param options - 562 * 563 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 564 * String></CODE> 565 * 566 * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using 567 * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE><JsonObject, 568 * String></CODE> will be returned. 569 * 570 * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>, 571 * using {@link Promise#await()}, <I>and the returned result of this Browser Function may 572 * may be retrieved.</I> 573 * 574 * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B> 575 * <BR /><BR /><UL CLASS=JDUL> 576 * <LI><CODE>String (<B>authenticatorId</B></CODE>) 577 * <BR />- 578 * </LI> 579 * </UL> */ 580 public static Script<String, JsonObject, String> addVirtualAuthenticator 581 (WebAuthn.VirtualAuthenticatorOptions options) 582 { 583 // Exception-Check(s) to ensure that if any parameters which are not declared as 584 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 585 586 if (options == null) BRDPC.throwNPE("options"); 587 588 final int webSocketID = 44002000 + counter++; 589 final boolean[] optionals = { false, }; 590 591 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 592 String requestJSON = WriteJSON.get( 593 parameterTypes.get("addVirtualAuthenticator"), 594 parameterNames.get("addVirtualAuthenticator"), 595 optionals, webSocketID, 596 "WebAuthn.addVirtualAuthenticator", 597 options 598 ); 599 600 // 'JSON Binding' ... Converts Browser Response-JSON to 'String' 601 Function<JsonObject, String> responseProcessor = (JsonObject jo) -> 602 ReadJSON.getString(jo, "authenticatorId", false, true); 603 604 // Pass the 'defaultSender' to Script-Constructor 605 // The sender that is used can be changed before executing script. 606 return new Script<>(BRDPC.defaultSender, webSocketID, requestJSON, responseProcessor); 607 } 608 609 /** 610 * Removes the given authenticator. 611 * 612 * @param authenticatorId - 613 * 614 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 615 * {@link Ret0}></CODE> 616 * 617 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 618 * browser receives the invocation-request. 619 * 620 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 621 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 622 * {@code >} to ensure the Browser Function has run to completion. 623 */ 624 public static Script<String, JsonObject, Ret0> removeVirtualAuthenticator 625 (String authenticatorId) 626 { 627 // Exception-Check(s) to ensure that if any parameters which are not declared as 628 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 629 630 if (authenticatorId == null) BRDPC.throwNPE("authenticatorId"); 631 632 final int webSocketID = 44003000 + counter++; 633 final boolean[] optionals = { false, }; 634 635 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 636 String requestJSON = WriteJSON.get( 637 parameterTypes.get("removeVirtualAuthenticator"), 638 parameterNames.get("removeVirtualAuthenticator"), 639 optionals, webSocketID, 640 "WebAuthn.removeVirtualAuthenticator", 641 authenticatorId 642 ); 643 644 // This Remote Command does not have a Return-Value. 645 return new Script<> 646 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 647 } 648 649 /** 650 * Adds the credential to the specified authenticator. 651 * 652 * @param authenticatorId - 653 * 654 * @param credential - 655 * 656 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 657 * {@link Ret0}></CODE> 658 * 659 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 660 * browser receives the invocation-request. 661 * 662 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 663 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 664 * {@code >} to ensure the Browser Function has run to completion. 665 */ 666 public static Script<String, JsonObject, Ret0> addCredential 667 (String authenticatorId, WebAuthn.Credential credential) 668 { 669 // Exception-Check(s) to ensure that if any parameters which are not declared as 670 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 671 672 if (authenticatorId == null) BRDPC.throwNPE("authenticatorId"); 673 if (credential == null) BRDPC.throwNPE("credential"); 674 675 final int webSocketID = 44004000 + counter++; 676 final boolean[] optionals = { false, false, }; 677 678 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 679 String requestJSON = WriteJSON.get( 680 parameterTypes.get("addCredential"), 681 parameterNames.get("addCredential"), 682 optionals, webSocketID, 683 "WebAuthn.addCredential", 684 authenticatorId, credential 685 ); 686 687 // This Remote Command does not have a Return-Value. 688 return new Script<> 689 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 690 } 691 692 /** 693 * Returns a single credential stored in the given virtual authenticator that 694 * matches the credential ID. 695 * 696 * @param authenticatorId - 697 * 698 * @param credentialId - 699 * 700 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 701 * {@link WebAuthn.Credential}></CODE> 702 * 703 * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using 704 * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE><JsonObject, 705 * {@link WebAuthn.Credential}></CODE> will be returned. 706 * 707 * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>, 708 * using {@link Promise#await()}, <I>and the returned result of this Browser Function may 709 * may be retrieved.</I> 710 * 711 * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B> 712 * <BR /><BR /><UL CLASS=JDUL> 713 * <LI><CODE>{@link WebAuthn.Credential} (<B>credential</B></CODE>) 714 * <BR />- 715 * </LI> 716 * </UL> */ 717 public static Script<String, JsonObject, WebAuthn.Credential> getCredential 718 (String authenticatorId, String credentialId) 719 { 720 // Exception-Check(s) to ensure that if any parameters which are not declared as 721 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 722 723 if (authenticatorId == null) BRDPC.throwNPE("authenticatorId"); 724 if (credentialId == null) BRDPC.throwNPE("credentialId"); 725 726 final int webSocketID = 44005000 + counter++; 727 final boolean[] optionals = { false, false, }; 728 729 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 730 String requestJSON = WriteJSON.get( 731 parameterTypes.get("getCredential"), 732 parameterNames.get("getCredential"), 733 optionals, webSocketID, 734 "WebAuthn.getCredential", 735 authenticatorId, credentialId 736 ); 737 738 // 'JSON Binding' ... Converts Browser Response-JSON to 'WebAuthn.Credential' 739 Function<JsonObject, WebAuthn.Credential> responseProcessor = (JsonObject jo) -> 740 ReadJSON.getObject(jo, "credential", WebAuthn.Credential.class, false, true); 741 742 // Pass the 'defaultSender' to Script-Constructor 743 // The sender that is used can be changed before executing script. 744 return new Script<>(BRDPC.defaultSender, webSocketID, requestJSON, responseProcessor); 745 } 746 747 /** 748 * Returns all the credentials stored in the given virtual authenticator. 749 * 750 * @param authenticatorId - 751 * 752 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 753 * {@link WebAuthn.Credential}[]></CODE> 754 * 755 * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using 756 * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE><JsonObject, 757 * {@link WebAuthn.Credential}[]></CODE> will be returned. 758 * 759 * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>, 760 * using {@link Promise#await()}, <I>and the returned result of this Browser Function may 761 * may be retrieved.</I> 762 * 763 * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B> 764 * <BR /><BR /><UL CLASS=JDUL> 765 * <LI><CODE>{@link WebAuthn.Credential}[] (<B>credentials</B></CODE>) 766 * <BR />- 767 * </LI> 768 * </UL> */ 769 public static Script<String, JsonObject, WebAuthn.Credential[]> getCredentials 770 (String authenticatorId) 771 { 772 // Exception-Check(s) to ensure that if any parameters which are not declared as 773 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 774 775 if (authenticatorId == null) BRDPC.throwNPE("authenticatorId"); 776 777 final int webSocketID = 44006000 + counter++; 778 final boolean[] optionals = { false, }; 779 780 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 781 String requestJSON = WriteJSON.get( 782 parameterTypes.get("getCredentials"), 783 parameterNames.get("getCredentials"), 784 optionals, webSocketID, 785 "WebAuthn.getCredentials", 786 authenticatorId 787 ); 788 789 // 'JSON Binding' ... Converts Browser Response-JSON to 'WebAuthn.Credential[]' 790 Function<JsonObject, WebAuthn.Credential[]> responseProcessor = (JsonObject jo) -> 791 (jo.getJsonArray("credentials") == null) 792 ? null 793 : ReadArrJSON.DimN.objArr(jo.getJsonArray("credentials"), null, 0, WebAuthn.Credential[].class); 794 795 // Pass the 'defaultSender' to Script-Constructor 796 // The sender that is used can be changed before executing script. 797 return new Script<>(BRDPC.defaultSender, webSocketID, requestJSON, responseProcessor); 798 } 799 800 /** 801 * Removes a credential from the authenticator. 802 * 803 * @param authenticatorId - 804 * 805 * @param credentialId - 806 * 807 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 808 * {@link Ret0}></CODE> 809 * 810 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 811 * browser receives the invocation-request. 812 * 813 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 814 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 815 * {@code >} to ensure the Browser Function has run to completion. 816 */ 817 public static Script<String, JsonObject, Ret0> removeCredential 818 (String authenticatorId, String credentialId) 819 { 820 // Exception-Check(s) to ensure that if any parameters which are not declared as 821 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 822 823 if (authenticatorId == null) BRDPC.throwNPE("authenticatorId"); 824 if (credentialId == null) BRDPC.throwNPE("credentialId"); 825 826 final int webSocketID = 44007000 + counter++; 827 final boolean[] optionals = { false, false, }; 828 829 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 830 String requestJSON = WriteJSON.get( 831 parameterTypes.get("removeCredential"), 832 parameterNames.get("removeCredential"), 833 optionals, webSocketID, 834 "WebAuthn.removeCredential", 835 authenticatorId, credentialId 836 ); 837 838 // This Remote Command does not have a Return-Value. 839 return new Script<> 840 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 841 } 842 843 /** 844 * Clears all the credentials from the specified device. 845 * 846 * @param authenticatorId - 847 * 848 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 849 * {@link Ret0}></CODE> 850 * 851 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 852 * browser receives the invocation-request. 853 * 854 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 855 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 856 * {@code >} to ensure the Browser Function has run to completion. 857 */ 858 public static Script<String, JsonObject, Ret0> clearCredentials(String authenticatorId) 859 { 860 // Exception-Check(s) to ensure that if any parameters which are not declared as 861 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 862 863 if (authenticatorId == null) BRDPC.throwNPE("authenticatorId"); 864 865 final int webSocketID = 44008000 + counter++; 866 final boolean[] optionals = { false, }; 867 868 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 869 String requestJSON = WriteJSON.get( 870 parameterTypes.get("clearCredentials"), 871 parameterNames.get("clearCredentials"), 872 optionals, webSocketID, 873 "WebAuthn.clearCredentials", 874 authenticatorId 875 ); 876 877 // This Remote Command does not have a Return-Value. 878 return new Script<> 879 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 880 } 881 882 /** 883 * Sets whether User Verification succeeds or fails for an authenticator. 884 * The default is true. 885 * 886 * @param authenticatorId - 887 * 888 * @param isUserVerified - 889 * 890 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 891 * {@link Ret0}></CODE> 892 * 893 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 894 * browser receives the invocation-request. 895 * 896 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 897 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 898 * {@code >} to ensure the Browser Function has run to completion. 899 */ 900 public static Script<String, JsonObject, Ret0> setUserVerified 901 (String authenticatorId, boolean isUserVerified) 902 { 903 // Exception-Check(s) to ensure that if any parameters which are not declared as 904 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 905 906 if (authenticatorId == null) BRDPC.throwNPE("authenticatorId"); 907 908 final int webSocketID = 44009000 + counter++; 909 final boolean[] optionals = { false, false, }; 910 911 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 912 String requestJSON = WriteJSON.get( 913 parameterTypes.get("setUserVerified"), 914 parameterNames.get("setUserVerified"), 915 optionals, webSocketID, 916 "WebAuthn.setUserVerified", 917 authenticatorId, isUserVerified 918 ); 919 920 // This Remote Command does not have a Return-Value. 921 return new Script<> 922 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 923 } 924 925 /** 926 * Sets whether tests of user presence will succeed immediately (if true) or fail to resolve (if false) for an authenticator. 927 * The default is true. 928 * 929 * @param authenticatorId - 930 * 931 * @param enabled - 932 * 933 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 934 * {@link Ret0}></CODE> 935 * 936 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 937 * browser receives the invocation-request. 938 * 939 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 940 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 941 * {@code >} to ensure the Browser Function has run to completion. 942 */ 943 public static Script<String, JsonObject, Ret0> setAutomaticPresenceSimulation 944 (String authenticatorId, boolean enabled) 945 { 946 // Exception-Check(s) to ensure that if any parameters which are not declared as 947 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 948 949 if (authenticatorId == null) BRDPC.throwNPE("authenticatorId"); 950 951 final int webSocketID = 44010000 + counter++; 952 final boolean[] optionals = { false, false, }; 953 954 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 955 String requestJSON = WriteJSON.get( 956 parameterTypes.get("setAutomaticPresenceSimulation"), 957 parameterNames.get("setAutomaticPresenceSimulation"), 958 optionals, webSocketID, 959 "WebAuthn.setAutomaticPresenceSimulation", 960 authenticatorId, enabled 961 ); 962 963 // This Remote Command does not have a Return-Value. 964 return new Script<> 965 (BRDPC.defaultSender, webSocketID, requestJSON, BRDPC.NoReturnValues); 966 } 967 968}