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) THROWS.throwNPE("protocol"); 269 if (transport == null) THROWS.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 THROWS.checkIAE("protocol", protocol, "WebAuthn.AuthenticatorProtocol", WebAuthn.AuthenticatorProtocol); 275 THROWS.checkIAE("ctap2Version", ctap2Version, "WebAuthn.Ctap2Version", WebAuthn.Ctap2Version); 276 THROWS.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 (this == other) return true; 311 if (other == null) return false; 312 if (other.getClass() != this.getClass()) return false; 313 314 VirtualAuthenticatorOptions o = (VirtualAuthenticatorOptions) other; 315 316 return 317 Objects.equals(this.protocol, o.protocol) 318 && Objects.equals(this.ctap2Version, o.ctap2Version) 319 && Objects.equals(this.transport, o.transport) 320 && Objects.equals(this.hasResidentKey, o.hasResidentKey) 321 && Objects.equals(this.hasUserVerification, o.hasUserVerification) 322 && Objects.equals(this.hasLargeBlob, o.hasLargeBlob) 323 && Objects.equals(this.hasCredBlob, o.hasCredBlob) 324 && Objects.equals(this.automaticPresenceSimulation, o.automaticPresenceSimulation) 325 && Objects.equals(this.isUserVerified, o.isUserVerified); 326 } 327 328 /** Generates a Hash-Code for {@code 'this'} instance */ 329 public int hashCode() 330 { 331 return 332 Objects.hashCode(this.protocol) 333 + Objects.hashCode(this.ctap2Version) 334 + Objects.hashCode(this.transport) 335 + Objects.hashCode(this.hasResidentKey) 336 + Objects.hashCode(this.hasUserVerification) 337 + Objects.hashCode(this.hasLargeBlob) 338 + Objects.hashCode(this.hasCredBlob) 339 + Objects.hashCode(this.automaticPresenceSimulation) 340 + Objects.hashCode(this.isUserVerified); 341 } 342 } 343 344 /** <CODE>[No Description Provided by Google]</CODE> */ 345 public static class Credential 346 extends BaseType 347 implements java.io.Serializable 348 { 349 /** For Object Serialization. java.io.Serializable */ 350 protected static final long serialVersionUID = 1; 351 352 public boolean[] optionals() 353 { return new boolean[] { false, false, true, false, true, false, true, }; } 354 355 /** <CODE>[No Description Provided by Google]</CODE> */ 356 public final String credentialId; 357 358 /** <CODE>[No Description Provided by Google]</CODE> */ 359 public final boolean isResidentCredential; 360 361 /** 362 * Relying Party ID the credential is scoped to. Must be set when adding a 363 * credential. 364 * <BR /> 365 * <BR /><B>OPTIONAL</B> 366 */ 367 public final String rpId; 368 369 /** The ECDSA P-256 private key in PKCS#8 format. (Encoded as a base64 string when passed over JSON) */ 370 public final String privateKey; 371 372 /** 373 * An opaque byte sequence with a maximum size of 64 bytes mapping the 374 * credential to a specific user. (Encoded as a base64 string when passed over JSON) 375 * <BR /> 376 * <BR /><B>OPTIONAL</B> 377 */ 378 public final String userHandle; 379 380 /** 381 * Signature counter. This is incremented by one for each successful 382 * assertion. 383 * See https://w3c.github.io/webauthn/#signature-counter 384 */ 385 public final int signCount; 386 387 /** 388 * The large blob associated with the credential. 389 * See https://w3c.github.io/webauthn/#sctn-large-blob-extension (Encoded as a base64 string when passed over JSON) 390 * <BR /> 391 * <BR /><B>OPTIONAL</B> 392 */ 393 public final String largeBlob; 394 395 /** 396 * Constructor 397 * 398 * @param credentialId - 399 * 400 * @param isResidentCredential - 401 * 402 * @param rpId 403 * Relying Party ID the credential is scoped to. Must be set when adding a 404 * credential. 405 * <BR /><B>OPTIONAL</B> 406 * 407 * @param privateKey The ECDSA P-256 private key in PKCS#8 format. (Encoded as a base64 string when passed over JSON) 408 * 409 * @param userHandle 410 * An opaque byte sequence with a maximum size of 64 bytes mapping the 411 * credential to a specific user. (Encoded as a base64 string when passed over JSON) 412 * <BR /><B>OPTIONAL</B> 413 * 414 * @param signCount 415 * Signature counter. This is incremented by one for each successful 416 * assertion. 417 * See https://w3c.github.io/webauthn/#signature-counter 418 * 419 * @param largeBlob 420 * The large blob associated with the credential. 421 * See https://w3c.github.io/webauthn/#sctn-large-blob-extension (Encoded as a base64 string when passed over JSON) 422 * <BR /><B>OPTIONAL</B> 423 */ 424 public Credential( 425 String credentialId, boolean isResidentCredential, String rpId, String privateKey, 426 String userHandle, int signCount, String largeBlob 427 ) 428 { 429 // Exception-Check(s) to ensure that if any parameters which are not declared as 430 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 431 432 if (credentialId == null) THROWS.throwNPE("credentialId"); 433 if (privateKey == null) THROWS.throwNPE("privateKey"); 434 435 this.credentialId = credentialId; 436 this.isResidentCredential = isResidentCredential; 437 this.rpId = rpId; 438 this.privateKey = privateKey; 439 this.userHandle = userHandle; 440 this.signCount = signCount; 441 this.largeBlob = largeBlob; 442 } 443 444 /** 445 * JSON Object Constructor 446 * @param jo A Json-Object having data about an instance of {@code 'Credential'}. 447 */ 448 public Credential (JsonObject jo) 449 { 450 this.credentialId = ReadJSON.getString(jo, "credentialId", false, true); 451 this.isResidentCredential = ReadPrimJSON.getBoolean(jo, "isResidentCredential"); 452 this.rpId = ReadJSON.getString(jo, "rpId", true, false); 453 this.privateKey = ReadJSON.getString(jo, "privateKey", false, true); 454 this.userHandle = ReadJSON.getString(jo, "userHandle", true, false); 455 this.signCount = ReadPrimJSON.getInt(jo, "signCount"); 456 this.largeBlob = ReadJSON.getString(jo, "largeBlob", true, false); 457 } 458 459 460 /** Checks whether {@code 'this'} equals an input Java-{@code Object} */ 461 public boolean equals(Object other) 462 { 463 if (this == other) return true; 464 if (other == null) return false; 465 if (other.getClass() != this.getClass()) return false; 466 467 Credential o = (Credential) other; 468 469 return 470 Objects.equals(this.credentialId, o.credentialId) 471 && (this.isResidentCredential == o.isResidentCredential) 472 && Objects.equals(this.rpId, o.rpId) 473 && Objects.equals(this.privateKey, o.privateKey) 474 && Objects.equals(this.userHandle, o.userHandle) 475 && (this.signCount == o.signCount) 476 && Objects.equals(this.largeBlob, o.largeBlob); 477 } 478 479 /** Generates a Hash-Code for {@code 'this'} instance */ 480 public int hashCode() 481 { 482 return 483 Objects.hashCode(this.credentialId) 484 + (this.isResidentCredential ? 1 : 0) 485 + Objects.hashCode(this.rpId) 486 + Objects.hashCode(this.privateKey) 487 + Objects.hashCode(this.userHandle) 488 + this.signCount 489 + Objects.hashCode(this.largeBlob); 490 } 491 } 492 493 494 // Counter for keeping the WebSocket Request ID's distinct. 495 private static int counter = 1; 496 497 /** 498 * Enable the WebAuthn domain and start intercepting credential storage and 499 * retrieval with a virtual authenticator. 500 * 501 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 502 * {@link Ret0}></CODE> 503 * 504 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 505 * browser receives the invocation-request. 506 * 507 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 508 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 509 * {@code >} to ensure the Browser Function has run to completion. 510 */ 511 public static Script<String, JsonObject, Ret0> enable() 512 { 513 final int webSocketID = 44000000 + counter++; 514 final boolean[] optionals = new boolean[0]; 515 516 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 517 String requestJSON = WriteJSON.get( 518 parameterTypes.get("enable"), 519 parameterNames.get("enable"), 520 optionals, webSocketID, 521 "WebAuthn.enable" 522 ); 523 524 // This Remote Command does not have a Return-Value. 525 return new Script<> 526 (webSocketID, requestJSON, VOID_RETURN.NoReturnValues); 527 } 528 529 /** 530 * Disable the WebAuthn domain. 531 * 532 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 533 * {@link Ret0}></CODE> 534 * 535 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 536 * browser receives the invocation-request. 537 * 538 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 539 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 540 * {@code >} to ensure the Browser Function has run to completion. 541 */ 542 public static Script<String, JsonObject, Ret0> disable() 543 { 544 final int webSocketID = 44001000 + counter++; 545 final boolean[] optionals = new boolean[0]; 546 547 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 548 String requestJSON = WriteJSON.get( 549 parameterTypes.get("disable"), 550 parameterNames.get("disable"), 551 optionals, webSocketID, 552 "WebAuthn.disable" 553 ); 554 555 // This Remote Command does not have a Return-Value. 556 return new Script<> 557 (webSocketID, requestJSON, VOID_RETURN.NoReturnValues); 558 } 559 560 /** 561 * Creates and adds a virtual authenticator. 562 * 563 * @param options - 564 * 565 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 566 * String></CODE> 567 * 568 * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using 569 * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE><JsonObject, 570 * String></CODE> will be returned. 571 * 572 * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>, 573 * using {@link Promise#await()}, <I>and the returned result of this Browser Function may 574 * may be retrieved.</I> 575 * 576 * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B> 577 * <BR /><BR /><UL CLASS=JDUL> 578 * <LI><CODE>String (<B>authenticatorId</B></CODE>) 579 * <BR />- 580 * </LI> 581 * </UL> */ 582 public static Script<String, JsonObject, String> addVirtualAuthenticator 583 (WebAuthn.VirtualAuthenticatorOptions options) 584 { 585 // Exception-Check(s) to ensure that if any parameters which are not declared as 586 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 587 588 if (options == null) THROWS.throwNPE("options"); 589 590 final int webSocketID = 44002000 + counter++; 591 final boolean[] optionals = { false, }; 592 593 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 594 String requestJSON = WriteJSON.get( 595 parameterTypes.get("addVirtualAuthenticator"), 596 parameterNames.get("addVirtualAuthenticator"), 597 optionals, webSocketID, 598 "WebAuthn.addVirtualAuthenticator", 599 options 600 ); 601 602 // 'JSON Binding' ... Converts Browser Response-JSON to 'String' 603 Function<JsonObject, String> responseProcessor = (JsonObject jo) -> 604 ReadJSON.getString(jo, "authenticatorId", false, true); 605 606 return new Script<>(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) THROWS.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 (webSocketID, requestJSON, VOID_RETURN.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) THROWS.throwNPE("authenticatorId"); 673 if (credential == null) THROWS.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 (webSocketID, requestJSON, VOID_RETURN.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) THROWS.throwNPE("authenticatorId"); 724 if (credentialId == null) THROWS.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 return new Script<>(webSocketID, requestJSON, responseProcessor); 743 } 744 745 /** 746 * Returns all the credentials stored in the given virtual authenticator. 747 * 748 * @param authenticatorId - 749 * 750 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 751 * {@link WebAuthn.Credential}[]></CODE> 752 * 753 * <BR /><BR />This <B>script</B> may be <B STYLE='color: red'>executed</B>, using 754 * {@link Script#exec()}, and afterwards, a {@link Promise}<CODE><JsonObject, 755 * {@link WebAuthn.Credential}[]></CODE> will be returned. 756 * 757 * <BR /><BR />Finally, the <B>{@code Promise}</B> may be <B STYLE='color: red'>awaited</B>, 758 * using {@link Promise#await()}, <I>and the returned result of this Browser Function may 759 * may be retrieved.</I> 760 * 761 * <BR /><BR />This Browser Function <B STYLE='color: red'>returns</B> 762 * <BR /><BR /><UL CLASS=JDUL> 763 * <LI><CODE>{@link WebAuthn.Credential}[] (<B>credentials</B></CODE>) 764 * <BR />- 765 * </LI> 766 * </UL> */ 767 public static Script<String, JsonObject, WebAuthn.Credential[]> getCredentials 768 (String authenticatorId) 769 { 770 // Exception-Check(s) to ensure that if any parameters which are not declared as 771 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 772 773 if (authenticatorId == null) THROWS.throwNPE("authenticatorId"); 774 775 final int webSocketID = 44006000 + counter++; 776 final boolean[] optionals = { false, }; 777 778 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 779 String requestJSON = WriteJSON.get( 780 parameterTypes.get("getCredentials"), 781 parameterNames.get("getCredentials"), 782 optionals, webSocketID, 783 "WebAuthn.getCredentials", 784 authenticatorId 785 ); 786 787 // 'JSON Binding' ... Converts Browser Response-JSON to 'WebAuthn.Credential[]' 788 Function<JsonObject, WebAuthn.Credential[]> responseProcessor = (JsonObject jo) -> 789 (jo.getJsonArray("credentials") == null) 790 ? null 791 : RJArrIntoStream.objArr(jo.getJsonArray("credentials"), null, 0, WebAuthn.Credential.class).toArray(WebAuthn.Credential[]::new); 792 793 return new Script<>(webSocketID, requestJSON, responseProcessor); 794 } 795 796 /** 797 * Removes a credential from the authenticator. 798 * 799 * @param authenticatorId - 800 * 801 * @param credentialId - 802 * 803 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 804 * {@link Ret0}></CODE> 805 * 806 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 807 * browser receives the invocation-request. 808 * 809 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 810 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 811 * {@code >} to ensure the Browser Function has run to completion. 812 */ 813 public static Script<String, JsonObject, Ret0> removeCredential 814 (String authenticatorId, String credentialId) 815 { 816 // Exception-Check(s) to ensure that if any parameters which are not declared as 817 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 818 819 if (authenticatorId == null) THROWS.throwNPE("authenticatorId"); 820 if (credentialId == null) THROWS.throwNPE("credentialId"); 821 822 final int webSocketID = 44007000 + counter++; 823 final boolean[] optionals = { false, false, }; 824 825 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 826 String requestJSON = WriteJSON.get( 827 parameterTypes.get("removeCredential"), 828 parameterNames.get("removeCredential"), 829 optionals, webSocketID, 830 "WebAuthn.removeCredential", 831 authenticatorId, credentialId 832 ); 833 834 // This Remote Command does not have a Return-Value. 835 return new Script<> 836 (webSocketID, requestJSON, VOID_RETURN.NoReturnValues); 837 } 838 839 /** 840 * Clears all the credentials from the specified device. 841 * 842 * @param authenticatorId - 843 * 844 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 845 * {@link Ret0}></CODE> 846 * 847 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 848 * browser receives the invocation-request. 849 * 850 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 851 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 852 * {@code >} to ensure the Browser Function has run to completion. 853 */ 854 public static Script<String, JsonObject, Ret0> clearCredentials(String authenticatorId) 855 { 856 // Exception-Check(s) to ensure that if any parameters which are not declared as 857 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 858 859 if (authenticatorId == null) THROWS.throwNPE("authenticatorId"); 860 861 final int webSocketID = 44008000 + counter++; 862 final boolean[] optionals = { false, }; 863 864 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 865 String requestJSON = WriteJSON.get( 866 parameterTypes.get("clearCredentials"), 867 parameterNames.get("clearCredentials"), 868 optionals, webSocketID, 869 "WebAuthn.clearCredentials", 870 authenticatorId 871 ); 872 873 // This Remote Command does not have a Return-Value. 874 return new Script<> 875 (webSocketID, requestJSON, VOID_RETURN.NoReturnValues); 876 } 877 878 /** 879 * Sets whether User Verification succeeds or fails for an authenticator. 880 * The default is true. 881 * 882 * @param authenticatorId - 883 * 884 * @param isUserVerified - 885 * 886 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 887 * {@link Ret0}></CODE> 888 * 889 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 890 * browser receives the invocation-request. 891 * 892 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 893 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 894 * {@code >} to ensure the Browser Function has run to completion. 895 */ 896 public static Script<String, JsonObject, Ret0> setUserVerified 897 (String authenticatorId, boolean isUserVerified) 898 { 899 // Exception-Check(s) to ensure that if any parameters which are not declared as 900 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 901 902 if (authenticatorId == null) THROWS.throwNPE("authenticatorId"); 903 904 final int webSocketID = 44009000 + counter++; 905 final boolean[] optionals = { false, false, }; 906 907 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 908 String requestJSON = WriteJSON.get( 909 parameterTypes.get("setUserVerified"), 910 parameterNames.get("setUserVerified"), 911 optionals, webSocketID, 912 "WebAuthn.setUserVerified", 913 authenticatorId, isUserVerified 914 ); 915 916 // This Remote Command does not have a Return-Value. 917 return new Script<> 918 (webSocketID, requestJSON, VOID_RETURN.NoReturnValues); 919 } 920 921 /** 922 * Sets whether tests of user presence will succeed immediately (if true) or fail to resolve (if false) for an authenticator. 923 * The default is true. 924 * 925 * @param authenticatorId - 926 * 927 * @param enabled - 928 * 929 * @return An instance of <CODE>{@link Script}<String, {@link JsonObject}, 930 * {@link Ret0}></CODE> 931 * 932 * <BR /><BR />This {@code Script} instance must be <B STYLE='color:red'>executed</B> before the 933 * browser receives the invocation-request. 934 * 935 * <BR /><BR />This Browser-Function <I>does not have</I> a return-value. You may choose to 936 * <B STYLE='color: red'>await</B> the {@link Promise}{@code <JsonObject,} {@link Ret0} 937 * {@code >} to ensure the Browser Function has run to completion. 938 */ 939 public static Script<String, JsonObject, Ret0> setAutomaticPresenceSimulation 940 (String authenticatorId, boolean enabled) 941 { 942 // Exception-Check(s) to ensure that if any parameters which are not declared as 943 // 'Optional', but have a 'null' value anyway, that a NullPointerException shall throw. 944 945 if (authenticatorId == null) THROWS.throwNPE("authenticatorId"); 946 947 final int webSocketID = 44010000 + counter++; 948 final boolean[] optionals = { false, false, }; 949 950 // Convert Method Parameters into JSON. Build the JSON Request-Object (as a String) 951 String requestJSON = WriteJSON.get( 952 parameterTypes.get("setAutomaticPresenceSimulation"), 953 parameterNames.get("setAutomaticPresenceSimulation"), 954 optionals, webSocketID, 955 "WebAuthn.setAutomaticPresenceSimulation", 956 authenticatorId, enabled 957 ); 958 959 // This Remote Command does not have a Return-Value. 960 return new Script<> 961 (webSocketID, requestJSON, VOID_RETURN.NoReturnValues); 962 } 963 964}