two_factor_authentication.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import axios from 'axios';
  2. import * as WebAuthnJSON from '@github/webauthn-json';
  3. import ready from '../mastodon/ready';
  4. import 'regenerator-runtime/runtime';
  5. function getCSRFToken() {
  6. var CSRFSelector = document.querySelector('meta[name="csrf-token"]');
  7. if (CSRFSelector) {
  8. return CSRFSelector.getAttribute('content');
  9. } else {
  10. return null;
  11. }
  12. }
  13. function hideFlashMessages() {
  14. Array.from(document.getElementsByClassName('flash-message')).forEach(function(flashMessage) {
  15. flashMessage.classList.add('hidden');
  16. });
  17. }
  18. function callback(url, body) {
  19. axios.post(url, JSON.stringify(body), {
  20. headers: {
  21. 'Content-Type': 'application/json',
  22. 'Accept': 'application/json',
  23. 'X-CSRF-Token': getCSRFToken(),
  24. },
  25. credentials: 'same-origin',
  26. }).then(function(response) {
  27. window.location.replace(response.data.redirect_path);
  28. }).catch(function(error) {
  29. if (error.response.status === 422) {
  30. const errorMessage = document.getElementById('security-key-error-message');
  31. errorMessage.classList.remove('hidden');
  32. console.error(error.response.data.error);
  33. } else {
  34. console.error(error);
  35. }
  36. });
  37. }
  38. ready(() => {
  39. if (!WebAuthnJSON.supported()) {
  40. const unsupported_browser_message = document.getElementById('unsupported-browser-message');
  41. if (unsupported_browser_message) {
  42. unsupported_browser_message.classList.remove('hidden');
  43. document.querySelector('.btn.js-webauthn').disabled = true;
  44. }
  45. }
  46. const webAuthnCredentialRegistrationForm = document.getElementById('new_webauthn_credential');
  47. if (webAuthnCredentialRegistrationForm) {
  48. webAuthnCredentialRegistrationForm.addEventListener('submit', (event) => {
  49. event.preventDefault();
  50. var nickname = event.target.querySelector('input[name="new_webauthn_credential[nickname]"]');
  51. if (nickname.value) {
  52. axios.get('/settings/security_keys/options')
  53. .then((response) => {
  54. const credentialOptions = response.data;
  55. WebAuthnJSON.create({ 'publicKey': credentialOptions }).then((credential) => {
  56. var params = { 'credential': credential, 'nickname': nickname.value };
  57. callback('/settings/security_keys', params);
  58. }).catch((error) => {
  59. const errorMessage = document.getElementById('security-key-error-message');
  60. errorMessage.classList.remove('hidden');
  61. console.error(error);
  62. });
  63. }).catch((error) => {
  64. console.error(error.response.data.error);
  65. });
  66. } else {
  67. nickname.focus();
  68. }
  69. });
  70. }
  71. const webAuthnCredentialAuthenticationForm = document.getElementById('webauthn-form');
  72. if (webAuthnCredentialAuthenticationForm) {
  73. webAuthnCredentialAuthenticationForm.addEventListener('submit', (event) => {
  74. event.preventDefault();
  75. axios.get('sessions/security_key_options')
  76. .then((response) => {
  77. const credentialOptions = response.data;
  78. WebAuthnJSON.get({ 'publicKey': credentialOptions }).then((credential) => {
  79. var params = { 'user': { 'credential': credential } };
  80. callback('sign_in', params);
  81. }).catch((error) => {
  82. const errorMessage = document.getElementById('security-key-error-message');
  83. errorMessage.classList.remove('hidden');
  84. console.error(error);
  85. });
  86. }).catch((error) => {
  87. console.error(error.response.data.error);
  88. });
  89. });
  90. const otpAuthenticationForm = document.getElementById('otp-authentication-form');
  91. const linkToOtp = document.getElementById('link-to-otp');
  92. linkToOtp.addEventListener('click', () => {
  93. webAuthnCredentialAuthenticationForm.classList.add('hidden');
  94. otpAuthenticationForm.classList.remove('hidden');
  95. hideFlashMessages();
  96. });
  97. const linkToWebAuthn = document.getElementById('link-to-webauthn');
  98. linkToWebAuthn.addEventListener('click', () => {
  99. otpAuthenticationForm.classList.add('hidden');
  100. webAuthnCredentialAuthenticationForm.classList.remove('hidden');
  101. hideFlashMessages();
  102. });
  103. }
  104. });