main.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. 
  2. coerceToArrayBuffer = function (thing, name) {
  3. if (typeof thing === "string") {
  4. // base64url to base64
  5. thing = thing.replace(/-/g, "+").replace(/_/g, "/");
  6. // base64 to Uint8Array
  7. const str = atob(thing);
  8. const bytes = new Uint8Array(str.length);
  9. for (let i = 0; i < str.length; i++) {
  10. bytes[i] = str.charCodeAt(i);
  11. }
  12. return bytes;
  13. }
  14. };
  15. class Registration {
  16. constructor() {
  17. document.getElementById('start').addEventListener('click', this.registerAccount.bind(this));
  18. }
  19. async registerAccount(event) {
  20. event.preventDefault();
  21. const username = 'Foo! That Bar';
  22. const login = btoa(username);
  23. const response = await fetch(`/buildCredentialOptions?login=${login}`, {
  24. method: 'GET',
  25. headers: {
  26. 'Accept': 'application/json'
  27. }
  28. });
  29. const options = await response.json();
  30. if (options.status !== "ok") {
  31. console.error("Error in buildCredentialOptions");
  32. console.error(options.errorMessage);
  33. return;
  34. } else {
  35. console.log("Got options", options);
  36. }
  37. // Turn the challenge back into the accepted format of padded base64
  38. options.challenge = coerceToArrayBuffer(options.challenge);
  39. // Turn ID into a UInt8Array Buffer for some reason
  40. options.user.id = coerceToArrayBuffer(options.user.id);
  41. options.excludeCredentials = options.excludeCredentials.map((c) => {
  42. c.id = coerceToArrayBuffer(c.id);
  43. return c;
  44. });
  45. console.log("Options Formatted", options);
  46. // Create the Credential with navigator.credentials.create API
  47. let newCredential;
  48. try {
  49. newCredential = await navigator.credentials.create({
  50. publicKey: options
  51. });
  52. } catch (e) {
  53. console.error("credentials.create failed with exception", e);
  54. }
  55. console.log("PublicKeyCredential created", newCredential);
  56. // try {
  57. // register(newCredential);
  58. // } catch (e) {
  59. // console.error("Registering new credentials with the server failed with exception", e);
  60. // }
  61. }
  62. async register(newCredential) {
  63. // Move data into Arrays in case it is super long
  64. // TODO: check!
  65. let attestationObject = new Uint8Array(newCredential.response.attestationObject);
  66. let clientDataJSON = new Uint8Array(newCredential.response.clientDataJSON);
  67. let rawId = new Uint8Array(newCredential.rawId);
  68. const data = {
  69. id: newCredential.id,
  70. //rawId: coerceToBase64Url(rawId),
  71. type: newCredential.type,
  72. extensions: newCredential.getClientExtensionResults(),
  73. response: {
  74. AttestationObject: coerceToBase64Url(attestationObject),
  75. clientDataJSON: coerceToBase64Url(clientDataJSON),
  76. transports: newCredential.response.getTransports()
  77. }
  78. };
  79. let response = await fetch(`/registerCredential?login=`, {
  80. method: 'POST', // or 'PUT'
  81. body: JSON.stringify(formData), // data can be `string` or {object}!
  82. headers: {
  83. 'Accept': 'application/json',
  84. 'Content-Type': 'application/json'
  85. }
  86. });
  87. const result = await response.json();
  88. console.log("Credential Object", result);
  89. if (result.status !== "ok") {
  90. throw new Error(`Error creating credential: ${result.errorMessage}`);
  91. }
  92. }
  93. }
  94. window.registration = new Registration();