├── README.md ├── favicon.ico ├── LICENSE ├── css └── style.css ├── scss └── style.scss ├── index.html └── js └── index.js /README.md: -------------------------------------------------------------------------------- 1 | # 2FA 2 | 2FA modal for yubikey style keys 3 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kibibit/2FA/master/favicon.ico -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 kibibit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | } 4 | 5 | *, *:before, *:after { 6 | box-sizing: inherit; 7 | } 8 | 9 | html, body { 10 | padding: 0px; 11 | margin: 0px; 12 | overflow: hidden; 13 | } 14 | 15 | #particles-js, 16 | #particles-js2 { 17 | top: 0; 18 | left: 0; 19 | position: absolute; 20 | width: 100%; 21 | height: 100%; 22 | background-color: #f25757; 23 | background-image: url(""); 24 | background-repeat: no-repeat; 25 | background-size: cover; 26 | background-position: 50% 50%; 27 | } 28 | #particles-js canvas, 29 | #particles-js2 canvas { 30 | filter: url(#goo); 31 | display: block; 32 | vertical-align: bottom; 33 | } 34 | 35 | #particles-js2 { 36 | background-color: transparent; 37 | } 38 | 39 | .bg-overlay { 40 | position: absolute; 41 | } 42 | 43 | .red { 44 | color: #f25757; 45 | } 46 | 47 | .blue { 48 | color: #00A2C9; 49 | } 50 | 51 | .yellow { 52 | color: #EEB146; 53 | } 54 | 55 | h1 { 56 | font-family: 'Righteous', cursive; 57 | } 58 | 59 | .bg-overlay { 60 | width: 100vw; 61 | height: 100vh; 62 | background-color: rgba(0, 0, 0, 0.4); 63 | z-index: 2; 64 | } 65 | 66 | body { 67 | margin: 0; 68 | background-color: #F25757; 69 | width: 100vw; 70 | height: 100vh; 71 | display: flex; 72 | justify-content: center; 73 | align-items: center; 74 | font-family: roboto,arial,sans-serif; 75 | font-size: 14px; 76 | } 77 | 78 | .card { 79 | top: 0; 80 | left: 0; 81 | right: 0; 82 | bottom: 0; 83 | margin: auto; 84 | position: absolute; 85 | max-width: 360px; 86 | max-height: 460px; 87 | background-color: white; 88 | border-radius: 5px; 89 | padding: 0 40px; 90 | overflow-x: hidden; 91 | box-shadow: 0 3px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12), 0 1px 5px 0 rgba(0, 0, 0, 0.2); 92 | z-index: 3; 93 | transition: all 300ms; 94 | overflow-y: hidden; 95 | } 96 | .card.transition { 97 | border-radius: 100%; 98 | max-width: 80px; 99 | max-height: 80px; 100 | overflow: hidden; 101 | background: #EEB146; 102 | } 103 | .card.transition .loader { 104 | opacity: 1; 105 | } 106 | .card .content { 107 | transition: all 200ms; 108 | } 109 | .card #troubles { 110 | color: #4285f4; 111 | display: inline-block; 112 | padding: 10px; 113 | padding-left: 0; 114 | border-radius: 5px; 115 | cursor: pointer; 116 | } 117 | .card .splash { 118 | background-image: linear-gradient(to bottom, rgba(233, 233, 233, 0) 0%, rgba(233, 233, 233, 0) 62.22%, #e9e9e9 40.22%, rgba(233, 233, 233, 0) 100%); 119 | position: relative; 120 | left: -42px; 121 | width: 404px; 122 | } 123 | .card .splash svg { 124 | transform: scale(-1, 1); 125 | width: 50%; 126 | max-width: 90vw; 127 | } 128 | .card .splash #yubikey-identifier { 129 | animation-duration: 1s; 130 | animation-name: insert; 131 | animation-iteration-count: infinite; 132 | animation-direction: alternate; 133 | animation-timing-function: ease-in-out; 134 | } 135 | 136 | @keyframes insert { 137 | 0% { 138 | transform: translateX(-10px); 139 | } 140 | 20% { 141 | transform: translateX(-10px); 142 | } 143 | 80% { 144 | transform: translateX(0); 145 | } 146 | 100% { 147 | transform: translateX(0); 148 | } 149 | } 150 | .loader { 151 | opacity: 0; 152 | width: 80px; 153 | height: 80px; 154 | position: absolute; 155 | left: 0; 156 | top: 0; 157 | right: 0; 158 | bottom: 0; 159 | margin: auto; 160 | border: 0 solid transparent; 161 | border-radius: 50%; 162 | transition: all 450ms; 163 | background: #EEB146; 164 | } 165 | .loader:before, .loader:after { 166 | content: ''; 167 | border-radius: 50%; 168 | width: inherit; 169 | height: inherit; 170 | position: absolute; 171 | top: 0; 172 | left: 0; 173 | animation: loader-07 1s linear infinite; 174 | opacity: 0; 175 | background: #f25757; 176 | } 177 | .loader:before { 178 | animation-delay: 1s; 179 | background: #00A2C9; 180 | } 181 | .loader:after { 182 | animation-delay: .5s; 183 | } 184 | 185 | @keyframes loader-07 { 186 | 0% { 187 | transform: scale(0); 188 | opacity: 0; 189 | } 190 | 50% { 191 | opacity: 1; 192 | } 193 | 100% { 194 | transform: scale(1); 195 | opacity: 0; 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /scss/style.scss: -------------------------------------------------------------------------------- 1 | $red: #f25757; 2 | $blue: #00A2C9; 3 | $yellow: #EEB146; 4 | 5 | html { 6 | box-sizing: border-box; 7 | } 8 | 9 | *, *:before, *:after { 10 | box-sizing: inherit; 11 | } 12 | 13 | html, body { 14 | padding: 0px; 15 | margin: 0px; 16 | overflow: hidden; 17 | } 18 | 19 | #particles-js, 20 | #particles-js2 { 21 | top: 0; 22 | left: 0; 23 | position: absolute; 24 | width: 100%; 25 | height: 100%; 26 | background-color: $red; 27 | background-image: url(""); 28 | background-repeat: no-repeat; 29 | background-size: cover; 30 | background-position: 50% 50%; 31 | 32 | canvas { 33 | filter: url(#goo); 34 | display: block; 35 | vertical-align: bottom; 36 | } 37 | } 38 | 39 | #particles-js2 { 40 | background-color: transparent; 41 | } 42 | 43 | .bg-overlay { 44 | position: absolute; 45 | } 46 | 47 | .red { 48 | color: $red; 49 | } 50 | 51 | .blue { 52 | color: $blue; 53 | } 54 | 55 | .yellow { 56 | color: $yellow; 57 | } 58 | 59 | h1 { 60 | font-family: 'Righteous', cursive; 61 | } 62 | 63 | .bg-overlay { 64 | width: 100vw; 65 | height: 100vh; 66 | background-color: rgba(0, 0, 0, 0.4); 67 | z-index: 2; 68 | } 69 | 70 | body { 71 | margin: 0; 72 | background-color: #F25757; 73 | width: 100vw; 74 | height: 100vh; 75 | display: flex; 76 | justify-content: center; 77 | align-items: center; 78 | font-family: roboto,arial,sans-serif; 79 | font-size: 14px; 80 | } 81 | 82 | .card { 83 | top: 0; 84 | left: 0; 85 | right: 0; 86 | bottom: 0; 87 | margin: auto; 88 | position: absolute; 89 | max-width: 360px; 90 | max-height: 460px; 91 | background-color: white; 92 | border-radius: 5px; 93 | padding: 0 40px; 94 | overflow-x: hidden; 95 | box-shadow: 0 3px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2); 96 | z-index: 3; 97 | transition: all 300ms; 98 | 99 | // disabling y scroll for now 100 | overflow-y: hidden; 101 | 102 | &.transition { 103 | border-radius: 100%; 104 | max-width: 80px; 105 | max-height: 80px; 106 | overflow: hidden; 107 | background: $yellow; 108 | 109 | .loader { 110 | opacity: 1; 111 | } 112 | } 113 | 114 | .content { 115 | transition: all 200ms; 116 | } 117 | 118 | #troubles { 119 | color: #4285f4; 120 | display: inline-block; 121 | padding: 10px; 122 | padding-left: 0; 123 | border-radius: 5px; 124 | cursor: pointer; 125 | } 126 | 127 | .splash { 128 | background-image: linear-gradient(to bottom,rgba(233,233,233,0) 0%,rgba(233,233,233,0) 62.22%,rgba(233,233,233,1) 40.22%,rgba(233,233,233,0) 100%); 129 | position: relative; 130 | left: -42px; 131 | width: 404px; 132 | 133 | svg { 134 | transform: scale(-1,1); 135 | width: 50%; 136 | max-width: 90vw; 137 | } 138 | 139 | #yubikey-identifier { 140 | animation-duration: 1s; 141 | animation-name: insert; 142 | animation-iteration-count: infinite; 143 | animation-direction: alternate; 144 | animation-timing-function: ease-in-out; 145 | } 146 | } 147 | } 148 | 149 | @keyframes insert { 150 | 0% { transform: translateX(-10px); } 151 | 20% { transform: translateX(-10px); } 152 | 80% { transform: translateX(0); } 153 | 100% { transform: translateX(0); } 154 | } 155 | 156 | .loader { 157 | opacity: 0; 158 | width: 80px; 159 | height: 80px; 160 | position: absolute; 161 | left: 0; 162 | top: 0; 163 | right: 0; 164 | bottom: 0; 165 | margin: auto; 166 | border: 0 solid transparent; 167 | border-radius: 50%; 168 | transition: all 450ms; 169 | // transition-delay: 350ms; 170 | background: $yellow; 171 | // position: relative; 172 | &:before, 173 | &:after { 174 | content: ''; 175 | // border: .2em solid currentcolor; 176 | border-radius: 50%; 177 | width: inherit; 178 | height: inherit; 179 | position: absolute; 180 | top: 0; 181 | left: 0; 182 | animation: loader-07 1s linear infinite; 183 | opacity: 0; 184 | background: $red; 185 | } 186 | &:before { 187 | animation-delay: 1s; 188 | background: $blue; 189 | } 190 | &:after { 191 | animation-delay: .5s; 192 | } 193 | } 194 | 195 | @keyframes loader-07 { 196 | 0% { 197 | transform: scale(0); 198 | opacity: 0; 199 | } 200 | 50% { 201 | opacity: 1; 202 | } 203 | 100% { 204 | transform: scale(1); 205 | opacity: 0; 206 | } 207 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | YubiKey animation mobile friendly 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |
23 | 24 |
25 | 26 |
27 |
28 |
29 |

kibibit

36 |

2-Step Verification

37 |

This extra step shows it’s really you trying to sign in

38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 |
88 |

Use your Security Key to sign in

89 |

Insert your Security Key into your computer's USB port. If it has a button, tap it.

90 |
Having trouble?
91 |
92 |
93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /js/index.js: -------------------------------------------------------------------------------- 1 | var otp = ''; 2 | var waiting = false; 3 | 4 | $('#troubles').click(() => { 5 | $('.content').css({ 6 | opacity: 0 7 | }); 8 | $('.card').addClass('transition'); 9 | 10 | setTimeout(() => { 11 | $('.card').removeClass('transition'); 12 | $('.content').css({ 13 | opacity: 1 14 | }); 15 | }, 2000); 16 | }); 17 | 18 | document.body.addEventListener('keyup', function(e) { 19 | if(!waiting) { 20 | waiting = true; 21 | document.getElementById('tmp').innerHTML += ' Hang on...'; 22 | } 23 | 24 | if(e.keyCode == 13) { 25 | window.location = 'http://api2.yubico.com/wsapi/2.0/verify?id=1&nonce=aef3a7835277a28da831005c2ae3b919e2076a62&otp=' + otp; 26 | } 27 | 28 | otp += String.fromCharCode(e.keyCode); 29 | 30 | if(otp.length > 44) 31 | otp = otp.substr(otp.length - 44); 32 | 33 | display.innerText = otp; 34 | }); 35 | 36 | particlesJS("particles-js", { 37 | "particles": { 38 | "number": { 39 | "value": 80, 40 | "density": { 41 | "enable": true, 42 | "value_area": 800 43 | } 44 | }, 45 | "color": { 46 | "value": "#EEB146" 47 | }, 48 | "shape": { 49 | "type": "circle", 50 | "stroke": { 51 | "width": 0, 52 | "color": "#000000" 53 | }, 54 | "polygon": { 55 | "nb_sides": 5 56 | }, 57 | "image": { 58 | "src": "img/github.svg", 59 | "width": 100, 60 | "height": 100 61 | } 62 | }, 63 | "opacity": { 64 | "value": 1, 65 | "random": false, 66 | "anim": { 67 | "enable": false, 68 | "speed": 1, 69 | "opacity_min": 0.1, 70 | "sync": false 71 | } 72 | }, 73 | "size": { 74 | "value": 144.3001443001443, 75 | "random": true, 76 | "anim": { 77 | "enable": true, 78 | "speed": 40, 79 | "size_min": 0.1, 80 | "sync": false 81 | } 82 | }, 83 | "line_linked": { 84 | "enable": false, 85 | "distance": 150, 86 | "color": "#ffffff", 87 | "opacity": 0.4, 88 | "width": 1 89 | }, 90 | "move": { 91 | "enable": true, 92 | "speed": 1, 93 | "direction": "none", 94 | "random": true, 95 | "straight": false, 96 | "out_mode": "bounce", 97 | "bounce": false, 98 | "attract": { 99 | "enable": true, 100 | "rotateX": 1282.667949334616, 101 | "rotateY": 1603.3349366682698 102 | } 103 | } 104 | }, 105 | "interactivity": { 106 | "detect_on": "canvas", 107 | "events": { 108 | "onhover": { 109 | "enable": true, 110 | "mode": "repulse" 111 | }, 112 | "onclick": { 113 | "enable": true, 114 | "mode": "push" 115 | }, 116 | "resize": true 117 | }, 118 | "modes": { 119 | "grab": { 120 | "distance": 400, 121 | "line_linked": { 122 | "opacity": 1 123 | } 124 | }, 125 | "bubble": { 126 | "distance": 400, 127 | "size": 40, 128 | "duration": 2, 129 | "opacity": 8, 130 | "speed": 3 131 | }, 132 | "repulse": { 133 | "distance": 200, 134 | "duration": 0.4 135 | }, 136 | "push": { 137 | "particles_nb": 4 138 | }, 139 | "remove": { 140 | "particles_nb": 2 141 | } 142 | } 143 | }, 144 | "retina_detect": true 145 | }); 146 | 147 | particlesJS("particles-js2", { 148 | "particles": { 149 | "number": { 150 | "value": 80, 151 | "density": { 152 | "enable": true, 153 | "value_area": 800 154 | } 155 | }, 156 | "color": { 157 | "value": "#00A2C9" 158 | }, 159 | "shape": { 160 | "type": "circle", 161 | "stroke": { 162 | "width": 0, 163 | "color": "#000000" 164 | }, 165 | "polygon": { 166 | "nb_sides": 5 167 | }, 168 | "image": { 169 | "src": "img/github.svg", 170 | "width": 100, 171 | "height": 100 172 | } 173 | }, 174 | "opacity": { 175 | "value": 1, 176 | "random": false, 177 | "anim": { 178 | "enable": false, 179 | "speed": 1, 180 | "opacity_min": 0.1, 181 | "sync": false 182 | } 183 | }, 184 | "size": { 185 | "value": 100, 186 | "random": true, 187 | "anim": { 188 | "enable": true, 189 | "speed": 40, 190 | "size_min": 10, 191 | "sync": false 192 | } 193 | }, 194 | "line_linked": { 195 | "enable": false, 196 | "distance": 150, 197 | "color": "#ffffff", 198 | "opacity": 0.4, 199 | "width": 1 200 | }, 201 | "move": { 202 | "enable": true, 203 | "speed": 1, 204 | "direction": "none", 205 | "random": true, 206 | "straight": false, 207 | "out_mode": "bounce", 208 | "bounce": false, 209 | "attract": { 210 | "enable": true, 211 | "rotateX": 1282.667949334616, 212 | "rotateY": 1603.3349366682698 213 | } 214 | } 215 | }, 216 | "interactivity": { 217 | "detect_on": "canvas", 218 | "events": { 219 | "onhover": { 220 | "enable": true, 221 | "mode": "repulse" 222 | }, 223 | "onclick": { 224 | "enable": true, 225 | "mode": "push" 226 | }, 227 | "resize": true 228 | }, 229 | "modes": { 230 | "grab": { 231 | "distance": 400, 232 | "line_linked": { 233 | "opacity": 1 234 | } 235 | }, 236 | "bubble": { 237 | "distance": 400, 238 | "size": 40, 239 | "duration": 2, 240 | "opacity": 8, 241 | "speed": 3 242 | }, 243 | "repulse": { 244 | "distance": 200, 245 | "duration": 0.4 246 | }, 247 | "push": { 248 | "particles_nb": 4 249 | }, 250 | "remove": { 251 | "particles_nb": 2 252 | } 253 | } 254 | }, 255 | "retina_detect": true 256 | }); --------------------------------------------------------------------------------