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>
This commit is contained in:
Jonas Franz 2018-05-19 16:12:37 +02:00 committed by Lauris BH
parent f933bcdfee
commit 951309f76a
34 changed files with 1599 additions and 9 deletions

View file

@ -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)

View file

@ -110,6 +110,11 @@
<td><a href="https://github.com/mozilla/pdf.js/blob/master/LICENSE">Apache-2.0-only</a></td>
<td><a href="https://github.com/mozilla/pdf.js/archive/v1.4.20.tar.gz">pdf.js-v1.4.20.tar.gz</a></td>
</tr>
<tr>
<td><a href="/vendor/plugins/u2f/">u2f-api</a></td>
<td><a href="https://github.com/go-gitea/u2f-api/blob/master/LICENSE">Expat</a></td>
<td><a href="https://github.com/go-gitea/u2f-api/archive/v1.0.8.zip">u2f-api-1.0.8.zip</a></td>
</tr>
<tr>
<td><a href="/vendor/assets/font-awesome/fonts/">font-awesome - fonts</a></td>
<td><a href="http://fontawesome.io/license/">OFL</a></td>

1
public/vendor/plugins/u2f/index.js vendored Normal file

File diff suppressed because one or more lines are too long