setup.blade.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. @extends('layouts.app')
  2. @section('content')
  3. <div class="container">
  4. <div class="col-12">
  5. <div class="card shadow-none border mt-5">
  6. <div class="card-body">
  7. <div class="row">
  8. <div class="col-12 p-3 p-md-5">
  9. <div class="title">
  10. <h3 class="font-weight-bold">Setup Two-Factor Authentication</h3>
  11. </div>
  12. <hr>
  13. <div class="alert alert-info font-weight-light mb-3">
  14. We only support Two-Factor Authentication via TOTP mobile apps.
  15. </div>
  16. <section class="step-one pb-5">
  17. <div class="sub-title font-weight-bold h5" data-toggle="collapse" data-target="#step1" aria-expanded="true" aria-controls="step1" data-step="1">
  18. Step 1: Install compatible 2FA mobile app <i class="float-right fas fa-chevron-down"></i>
  19. </div>
  20. <hr>
  21. <div class="collapse show" id="step1">
  22. <p>You will need to install a compatible mobile app, we recommend the following apps:</p>
  23. <ul>
  24. <li><a href="https://1password.com/downloads/" rel="nooopener nofollow">1Password</a></li>
  25. <li><a href="https://authy.com/download/" rel="nooopener nofollow">Authy</a></li>
  26. <li><a href="https://lastpass.com/auth/" rel="nooopener nofollow">LastPass Authenticator</a></li>
  27. <li>
  28. Google Authenticator
  29. <a class="small" href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en_CA" rel="nooopener nofollow">
  30. (android)
  31. </a>
  32. <a class="small" href="https://itunes.apple.com/ca/app/google-authenticator/id388497605?mt=8" rel="nooopener nofollow">
  33. (iOS)
  34. </a>
  35. </li>
  36. <li><a href="https://www.microsoft.com/en-us/account/authenticator" rel="nooopener nofollow">Microsoft Authenticator</a></li>
  37. </ul>
  38. </div>
  39. </section>
  40. <section class="step-two pb-5">
  41. <div class="sub-title font-weight-bold h5" data-toggle="collapse" data-target="#step2" aria-expanded="false" aria-controls="step2" data-step="2">
  42. Step 2: Scan QR Code and confirm <i class="float-right fas fa-chevron-down"></i>
  43. </div>
  44. <hr>
  45. <div class="collapse" id="step2">
  46. <p>Please scan the QR code and then enter the 6 digit code in the form below. Keep in mind the code changes every 30 seconds, and is only good for 1 minute.</p>
  47. <div class="card">
  48. <div class="card-body text-center">
  49. <div class="pb-3">
  50. <p class="font-weight-bold">QR Code</p>
  51. {!!$qrcode!!}
  52. </div>
  53. <div>
  54. <p class="font-weight-bold">OTP Secret</p>
  55. <input type="text" class="form-control" value="{{ $user->{'2fa_secret'} }}" disabled>
  56. </div>
  57. </div>
  58. <div class="card-body">
  59. <form id="confirm-code">
  60. <div class="form-group">
  61. <label class="font-weight-bold small">Code</label>
  62. <input type="text" name="code" id="verifyCode" class="form-control" placeholder="Code" autocomplete="off">
  63. </div>
  64. <button type="submit" class="btn btn-primary font-weight-bold">Submit</button>
  65. </form>
  66. </div>
  67. </div>
  68. </div>
  69. </section>
  70. <section class="step-three pb-5">
  71. <div class="sub-title font-weight-bold h5" data-toggle="collapse" data-target="#step3" aria-expanded="true" aria-controls="step3" data-step="3">
  72. Step 3: Download Backup Codes <i class="float-right fas fa-chevron-down"></i>
  73. </div>
  74. <hr>
  75. <div class="collapse" id="step3">
  76. <p>Please store the following codes in a safe place, each backup code can be used only once if you do not have access to your 2FA mobile app.</p>
  77. <code>
  78. @foreach($backups as $code)
  79. <p class="mb-0">{{$code}}</p>
  80. @endforeach
  81. </code>
  82. </div>
  83. </section>
  84. </div>
  85. </div>
  86. </div>
  87. </div>
  88. </div>
  89. </div>
  90. @endsection
  91. @push('scripts')
  92. <script type="text/javascript">
  93. $(document).ready(function() {
  94. $('#step3').addClass('d-none');
  95. window.twoFactor = {};
  96. window.twoFactor.validated = false;
  97. $(document).on('click', 'div[data-toggle=collapse]', function(e) {
  98. let el = $(this);
  99. let step = el.data('step');
  100. switch(step) {
  101. case 1:
  102. $('#step2').collapse('hide');
  103. $('#step3').collapse('hide');
  104. break;
  105. case 2:
  106. $('#step1').collapse('hide');
  107. $('#step3').collapse('hide');
  108. break;
  109. case 3:
  110. if(twoFactor.validated == false) {
  111. e.preventDefault();
  112. return;
  113. } else {
  114. $('#step3').removeClass('d-none');
  115. $('#step1').collapse('hide');
  116. $('#step2').collapse('hide');
  117. }
  118. break;
  119. }
  120. });
  121. $(document).on('submit', '#confirm-code', function(e) {
  122. e.preventDefault();
  123. let el = $(this);
  124. let code = $('#verifyCode').val();
  125. if(code.length < 5) {
  126. swal('Oops!', 'You need to enter a valid code', 'error');
  127. return;
  128. }
  129. axios.post(window.location.href, {
  130. code: code
  131. }).then((res) => {
  132. twoFactor.validated = true;
  133. $('#step3').removeClass('d-none');
  134. $('#step3').collapse('show');
  135. $('#step1').collapse('hide');
  136. $('#step2').collapse('hide');
  137. }).catch((res) => {
  138. swal('Oops!', 'That was an invalid code, please try again.', 'error');
  139. return;
  140. });
  141. });
  142. });
  143. </script>
  144. @endpush