summaryrefslogtreecommitdiffstats
path: root/public/js
diff options
context:
space:
mode:
authorJonas Franz <info@jonasfranz.software>2018-05-19 16:12:37 +0200
committerLauris BH <lauris@nix.lv>2018-05-19 17:12:37 +0300
commit951309f76aab22e3742e8872bf0642fcea2570ae (patch)
tree041e43fcc393d0ca07e4e274b28c1938e6604780 /public/js
parentf933bcdfeef359d8d9592dc0cf0aea244963e23c (diff)
downloadgitea-951309f76aab22e3742e8872bf0642fcea2570ae.tar.gz
gitea-951309f76aab22e3742e8872bf0642fcea2570ae.zip
Add support for FIDO U2F (#3971)
* Add support for U2F Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add vendor library Add missing translations Signed-off-by: Jonas Franz <info@jonasfranz.software> * Minor improvements Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add U2F support for Firefox, Chrome (Android) by introducing a custom JS library Add U2F error handling Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add U2F login page to OAuth Signed-off-by: Jonas Franz <info@jonasfranz.software> * Move U2F user settings to a separate file Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add unit tests for u2f model Renamed u2f table name Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix problems caused by refactoring Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add U2F documentation Signed-off-by: Jonas Franz <info@jonasfranz.software> * Remove not needed console.log-s Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add default values to app.ini.sample Add FIDO U2F to comparison Signed-off-by: Jonas Franz <info@jonasfranz.software>
Diffstat (limited to 'public/js')
-rw-r--r--public/js/index.js128
1 files changed, 127 insertions, 1 deletions
diff --git a/public/js/index.js b/public/js/index.js
index e826c2f3f3..e98a3fe6de 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -1432,6 +1432,130 @@ function initCodeView() {
}
}
+function initU2FAuth() {
+ if($('#wait-for-key').length === 0) {
+ return
+ }
+ u2fApi.ensureSupport()
+ .then(function () {
+ $.getJSON('/user/u2f/challenge').success(function(req) {
+ u2fApi.sign(req.appId, req.challenge, req.registeredKeys, 30)
+ .then(u2fSigned)
+ .catch(function (err) {
+ if(err === undefined) {
+ u2fError(1);
+ return
+ }
+ u2fError(err.metaData.code);
+ });
+ });
+ }).catch(function () {
+ // Fallback in case browser do not support U2F
+ window.location.href = "/user/two_factor"
+ })
+}
+function u2fSigned(resp) {
+ $.ajax({
+ url:'/user/u2f/sign',
+ type:"POST",
+ headers: {"X-Csrf-Token": csrf},
+ data: JSON.stringify(resp),
+ contentType:"application/json; charset=utf-8",
+ }).done(function(res){
+ window.location.replace(res);
+ }).fail(function (xhr, textStatus) {
+ u2fError(1);
+ });
+}
+
+function u2fRegistered(resp) {
+ if (checkError(resp)) {
+ return;
+ }
+ $.ajax({
+ url:'/user/settings/security/u2f/register',
+ type:"POST",
+ headers: {"X-Csrf-Token": csrf},
+ data: JSON.stringify(resp),
+ contentType:"application/json; charset=utf-8",
+ success: function(){
+ window.location.reload();
+ },
+ fail: function (xhr, textStatus) {
+ u2fError(1);
+ }
+ });
+}
+
+function checkError(resp) {
+ if (!('errorCode' in resp)) {
+ return false;
+ }
+ if (resp.errorCode === 0) {
+ return false;
+ }
+ u2fError(resp.errorCode);
+ return true;
+}
+
+
+function u2fError(errorType) {
+ var u2fErrors = {
+ 'browser': $('#unsupported-browser'),
+ 1: $('#u2f-error-1'),
+ 2: $('#u2f-error-2'),
+ 3: $('#u2f-error-3'),
+ 4: $('#u2f-error-4'),
+ 5: $('.u2f-error-5')
+ };
+ u2fErrors[errorType].removeClass('hide');
+ for(var type in u2fErrors){
+ if(type != errorType){
+ u2fErrors[type].addClass('hide');
+ }
+ }
+ $('#u2f-error').modal('show');
+}
+
+function initU2FRegister() {
+ $('#register-device').modal({allowMultiple: false});
+ $('#u2f-error').modal({allowMultiple: false});
+ $('#register-security-key').on('click', function(e) {
+ e.preventDefault();
+ u2fApi.ensureSupport()
+ .then(u2fRegisterRequest)
+ .catch(function() {
+ u2fError('browser');
+ })
+ })
+}
+
+function u2fRegisterRequest() {
+ $.post("/user/settings/security/u2f/request_register", {
+ "_csrf": csrf,
+ "name": $('#nickname').val()
+ }).success(function(req) {
+ $("#nickname").closest("div.field").removeClass("error");
+ $('#register-device').modal('show');
+ if(req.registeredKeys === null) {
+ req.registeredKeys = []
+ }
+ u2fApi.register(req.appId, req.registerRequests, req.registeredKeys, 30)
+ .then(u2fRegistered)
+ .catch(function (reason) {
+ if(reason === undefined) {
+ u2fError(1);
+ return
+ }
+ u2fError(reason.metaData.code);
+ });
+ }).fail(function(xhr, status, error) {
+ if(xhr.status === 409) {
+ $("#nickname").closest("div.field").addClass("error");
+ }
+ });
+}
+
$(document).ready(function () {
csrf = $('meta[name=_csrf]').attr("content");
suburl = $('meta[name=_suburl]').attr("content");
@@ -1643,6 +1767,8 @@ $(document).ready(function () {
initCtrlEnterSubmit();
initNavbarContentToggle();
initTopicbar();
+ initU2FAuth();
+ initU2FRegister();
// Repo clone url.
if ($('#repo-clone-url').length > 0) {
@@ -2201,7 +2327,7 @@ function initTopicbar() {
return
}
var topicArray = topics.split(",");
-
+
var last = viewDiv.children("a").last();
for (var i=0;i < topicArray.length; i++) {
$('<div class="ui green basic label topic" style="cursor:pointer;">'+topicArray[i]+'</div>').insertBefore(last)