Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
U
uffd
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Luca (strifel)
uffd
Commits
4b1539b3
Commit
4b1539b3
authored
4 years ago
by
Julian
Browse files
Options
Downloads
Patches
Plain Diff
proper client-side webauthn error handling
parent
ce9f63bf
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
uffd/mfa/templates/auth.html
+21
-3
21 additions, 3 deletions
uffd/mfa/templates/auth.html
uffd/mfa/templates/setup.html
+28
-7
28 additions, 7 deletions
uffd/mfa/templates/setup.html
uffd/mfa/views.py
+4
-3
4 additions, 3 deletions
uffd/mfa/views.py
with
53 additions
and
13 deletions
uffd/mfa/templates/auth.html
+
21
−
3
View file @
4b1539b3
...
@@ -51,7 +51,7 @@ function begin_webauthn() {
...
@@ -51,7 +51,7 @@ function begin_webauthn() {
method
:
'
POST
'
,
method
:
'
POST
'
,
}).
then
(
function
(
response
)
{
}).
then
(
function
(
response
)
{
if
(
response
.
ok
)
return
response
.
arrayBuffer
();
if
(
response
.
ok
)
return
response
.
arrayBuffer
();
throw
new
Error
(
'
No credential available to authenticate!
'
);
throw
new
Error
(
'
You have not registered any U2F/FIDO2 devices for your account
'
);
}).
then
(
CBOR
.
decode
).
then
(
function
(
options
)
{
}).
then
(
CBOR
.
decode
).
then
(
function
(
options
)
{
$
(
'
#webauthn-btn-text
'
).
text
(
'
Waiting for response from your device
'
);
$
(
'
#webauthn-btn-text
'
).
text
(
'
Waiting for response from your device
'
);
return
navigator
.
credentials
.
get
(
options
);
return
navigator
.
credentials
.
get
(
options
);
...
@@ -75,8 +75,26 @@ function begin_webauthn() {
...
@@ -75,8 +75,26 @@ function begin_webauthn() {
}
else
{
}
else
{
throw
new
Error
(
'
Response from authenticator rejected
'
);
throw
new
Error
(
'
Response from authenticator rejected
'
);
}
}
},
function
(
reason
)
{
},
function
(
err
)
{
$
(
'
#webauthn-alert
'
).
text
(
'
Authentication with your FIDO token failed!
'
);
console
.
log
(
err
);
/* various webauthn errors */
if
(
err
.
name
==
'
NotAllowedError
'
)
$
(
'
#webauthn-alert
'
).
text
(
'
Authentication timed out, was aborted or not allowed
'
);
else
if
(
err
.
name
==
'
InvalidStateError
'
)
$
(
'
#webauthn-alert
'
).
text
(
'
Device is not registered for your account
'
);
else
if
(
err
.
name
==
'
AbortError
'
)
$
(
'
#webauthn-alert
'
).
text
(
'
Authentication was aborted
'
);
else
if
(
err
.
name
==
'
NotSupportedError
'
)
$
(
'
#webauthn-alert
'
).
text
(
'
U2F and FIDO2 devices are not supported by your browser
'
);
/* errors from fetch() */
else
if
(
err
.
name
==
'
TypeError
'
)
$
(
'
#webauthn-alert
'
).
text
(
'
Could not connect to server
'
);
/* our own errors */
else
if
(
err
.
name
==
'
Error
'
)
$
(
'
#webauthn-alert
'
).
text
(
err
.
message
);
/* fallback */
else
$
(
'
#webauthn-alert
'
).
text
(
'
Authentication failed (
'
+
err
+
'
)
'
);
$
(
'
#webauthn-alert
'
).
removeClass
(
'
d-none
'
);
$
(
'
#webauthn-alert
'
).
removeClass
(
'
d-none
'
);
$
(
'
#webauthn-spinner
'
).
addClass
(
'
d-none
'
);
$
(
'
#webauthn-spinner
'
).
addClass
(
'
d-none
'
);
$
(
'
#webauthn-btn-text
'
).
text
(
'
Try FIDO token again
'
);
$
(
'
#webauthn-btn-text
'
).
text
(
'
Try FIDO token again
'
);
...
...
This diff is collapsed.
Click to expand it.
uffd/mfa/templates/setup.html
+
28
−
7
View file @
4b1539b3
...
@@ -128,7 +128,7 @@ You need to setup at least one authentication method to enable two-factor authen
...
@@ -128,7 +128,7 @@ You need to setup at least one authentication method to enable two-factor authen
<form
id=
"webauthn-form"
class=
"form mb-2"
>
<form
id=
"webauthn-form"
class=
"form mb-2"
>
<div
class=
"row m-0"
>
<div
class=
"row m-0"
>
<label
class=
"sr-only"
for=
"webauthn-name"
>
Name
</label>
<label
class=
"sr-only"
for=
"webauthn-name"
>
Name
</label>
<input
type=
"text"
class=
"form-control mb-2 col-12 col-lg-auto mr-2"
style=
"width: 15em;"
id=
"webauthn-name"
placeholder=
"Name"
required
{{
'
disabled
'
if
mfa_init
}}
>
<input
type=
"text"
class=
"form-control mb-2 col-12 col-lg-auto mr-2"
style=
"width: 15em;"
id=
"webauthn-name"
placeholder=
"Name"
required
disabled
>
<button
type=
"submit"
id=
"webauthn-btn"
class=
"btn btn-primary mb-2 col"
disabled
>
<button
type=
"submit"
id=
"webauthn-btn"
class=
"btn btn-primary mb-2 col"
disabled
>
<span
id=
"webauthn-spinner"
class=
"spinner-border spinner-border-sm d-none"
role=
"status"
aria-hidden=
"true"
></span>
<span
id=
"webauthn-spinner"
class=
"spinner-border spinner-border-sm d-none"
role=
"status"
aria-hidden=
"true"
></span>
<span
id=
"webauthn-btn-text"
>
Setup new device
</span>
<span
id=
"webauthn-btn-text"
>
Setup new device
</span>
...
@@ -173,8 +173,11 @@ $('#webauthn-form').on('submit', function(e) {
...
@@ -173,8 +173,11 @@ $('#webauthn-form').on('submit', function(e) {
fetch
({{
url_for
(
'
mfa.setup_webauthn_begin
'
)
|
tojson
}},
{
fetch
({{
url_for
(
'
mfa.setup_webauthn_begin
'
)
|
tojson
}},
{
method
:
'
POST
'
,
method
:
'
POST
'
,
}).
then
(
function
(
response
)
{
}).
then
(
function
(
response
)
{
if
(
response
.
ok
)
return
response
.
arrayBuffer
();
if
(
response
.
ok
)
throw
new
Error
(
'
Error getting registration data!
'
);
return
response
.
arrayBuffer
();
if
(
response
.
status
==
403
)
throw
new
Error
(
'
You need to generate recovery codes first
'
);
throw
new
Error
(
'
Server error
'
);
}).
then
(
CBOR
.
decode
).
then
(
function
(
options
)
{
}).
then
(
CBOR
.
decode
).
then
(
function
(
options
)
{
$
(
'
#webauthn-btn-text
'
).
text
(
'
Waiting for response from your device
'
);
$
(
'
#webauthn-btn-text
'
).
text
(
'
Waiting for response from your device
'
);
return
navigator
.
credentials
.
create
(
options
);
return
navigator
.
credentials
.
create
(
options
);
...
@@ -194,10 +197,28 @@ $('#webauthn-form').on('submit', function(e) {
...
@@ -194,10 +197,28 @@ $('#webauthn-form').on('submit', function(e) {
$
(
'
#webauthn-btn-text
'
).
text
(
'
Success
'
);
$
(
'
#webauthn-btn-text
'
).
text
(
'
Success
'
);
window
.
location
=
{{
url_for
(
'
mfa.setup
'
)
|
tojson
}};
window
.
location
=
{{
url_for
(
'
mfa.setup
'
)
|
tojson
}};
}
else
{
}
else
{
throw
new
Error
(
'
Server rejected
authenticator re
sponse
'
);
throw
new
Error
(
'
Response from
authenticator re
jected
'
);
}
}
},
function
(
reason
)
{
},
function
(
err
)
{
$
(
'
#webauthn-alert
'
).
text
(
'
Registration failed!
'
);
console
.
log
(
err
);
/* various webauthn errors */
if
(
err
.
name
==
'
NotAllowedError
'
)
$
(
'
#webauthn-alert
'
).
text
(
'
Registration timed out, was aborted or not allowed
'
);
else
if
(
err
.
name
==
'
InvalidStateError
'
)
$
(
'
#webauthn-alert
'
).
text
(
'
You attempted to register a device that is already registered
'
);
else
if
(
err
.
name
==
'
AbortError
'
)
$
(
'
#webauthn-alert
'
).
text
(
'
Registration was aborted
'
);
else
if
(
err
.
name
==
'
NotSupportedError
'
)
$
(
'
#webauthn-alert
'
).
text
(
'
U2F and FIDO2 devices are not supported by your browser
'
);
/* errors from fetch() */
else
if
(
err
.
name
==
'
TypeError
'
)
$
(
'
#webauthn-alert
'
).
text
(
'
Could not connect to server
'
);
/* our own errors */
else
if
(
err
.
name
==
'
Error
'
)
$
(
'
#webauthn-alert
'
).
text
(
err
.
message
);
/* fallback */
else
$
(
'
#webauthn-alert
'
).
text
(
'
Registration failed (
'
+
err
+
'
)
'
);
$
(
'
#webauthn-alert
'
).
removeClass
(
'
d-none
'
);
$
(
'
#webauthn-alert
'
).
removeClass
(
'
d-none
'
);
$
(
'
#webauthn-spinner
'
).
addClass
(
'
d-none
'
);
$
(
'
#webauthn-spinner
'
).
addClass
(
'
d-none
'
);
$
(
'
#webauthn-btn-text
'
).
text
(
'
Retry registration
'
);
$
(
'
#webauthn-btn-text
'
).
text
(
'
Retry registration
'
);
...
@@ -212,7 +233,7 @@ if (typeof(PublicKeyCredential) != "undefined") {
...
@@ -212,7 +233,7 @@ if (typeof(PublicKeyCredential) != "undefined") {
$
(
'
#webauthn-name
'
).
prop
(
'
disabled
'
,
false
);
$
(
'
#webauthn-name
'
).
prop
(
'
disabled
'
,
false
);
{
%
endif
%
}
{
%
endif
%
}
}
else
{
}
else
{
$
(
'
#webauthn-alert
'
).
text
(
'
U2F and FIDO2 devices are not supported by your browser
!
'
);
$
(
'
#webauthn-alert
'
).
text
(
'
U2F and FIDO2 devices are not supported by your browser
'
);
$
(
'
#webauthn-alert
'
).
removeClass
(
'
d-none
'
);
$
(
'
#webauthn-alert
'
).
removeClass
(
'
d-none
'
);
}
}
...
...
This diff is collapsed.
Click to expand it.
uffd/mfa/views.py
+
4
−
3
View file @
4b1539b3
from
flask
import
Blueprint
,
render_template
,
session
,
request
,
redirect
,
url_for
,
flash
,
current_app
from
flask
import
Blueprint
,
render_template
,
session
,
request
,
redirect
,
url_for
,
flash
,
current_app
,
abort
import
urllib.parse
import
urllib.parse
from
fido2.client
import
ClientData
from
fido2.client
import
ClientData
...
@@ -117,7 +117,7 @@ def setup_webauthn_begin():
...
@@ -117,7 +117,7 @@ def setup_webauthn_begin():
server
=
get_webauthn_server
()
server
=
get_webauthn_server
()
registration_data
,
state
=
server
.
register_begin
(
registration_data
,
state
=
server
.
register_begin
(
{
{
"
id
"
:
user
.
loginname
.
encode
(),
"
id
"
:
user
.
dn
.
encode
(),
"
name
"
:
user
.
loginname
,
"
name
"
:
user
.
loginname
,
"
displayName
"
:
user
.
displayname
,
"
displayName
"
:
user
.
displayname
,
},
},
...
@@ -140,7 +140,6 @@ def setup_webauthn_complete():
...
@@ -140,7 +140,6 @@ def setup_webauthn_complete():
method
=
WebauthnMethod
(
user
,
auth_data
,
name
=
data
[
'
name
'
])
method
=
WebauthnMethod
(
user
,
auth_data
,
name
=
data
[
'
name
'
])
db
.
session
.
add
(
method
)
db
.
session
.
add
(
method
)
db
.
session
.
commit
()
db
.
session
.
commit
()
print
(
"
REGISTERED CREDENTIAL:
"
,
auth_data
.
credential_data
)
return
cbor
.
dumps
({
"
status
"
:
"
OK
"
})
return
cbor
.
dumps
({
"
status
"
:
"
OK
"
})
@bp.route
(
'
/setup/webauthn/<int:id>/delete
'
)
@bp.route
(
'
/setup/webauthn/<int:id>/delete
'
)
...
@@ -178,6 +177,8 @@ def auth_webauthn_complete():
...
@@ -178,6 +177,8 @@ def auth_webauthn_complete():
client_data
=
ClientData
(
data
[
"
clientDataJSON
"
])
client_data
=
ClientData
(
data
[
"
clientDataJSON
"
])
auth_data
=
AuthenticatorData
(
data
[
"
authenticatorData
"
])
auth_data
=
AuthenticatorData
(
data
[
"
authenticatorData
"
])
signature
=
data
[
"
signature
"
]
signature
=
data
[
"
signature
"
]
# authenticate_complete() (as of python-fido2 v0.5.0, the version in Debian Buster)
# does not check signCount, although the spec recommends it
server
.
authenticate_complete
(
server
.
authenticate_complete
(
session
.
pop
(
"
webauthn-state
"
),
session
.
pop
(
"
webauthn-state
"
),
creds
,
creds
,
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment