-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
webauthn_controller.go
102 lines (84 loc) · 3.58 KB
/
webauthn_controller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package web
import (
"encoding/json"
"errors"
"net/http"
"github.com/gin-gonic/gin"
"github.com/smartcontractkit/chainlink/v2/core/logger"
"github.com/smartcontractkit/chainlink/v2/core/logger/audit"
"github.com/smartcontractkit/chainlink/v2/core/services/chainlink"
"github.com/smartcontractkit/chainlink/v2/core/sessions"
"github.com/smartcontractkit/chainlink/v2/core/web/auth"
"github.com/smartcontractkit/chainlink/v2/core/web/presenters"
)
// WebAuthnController manages registers new keys as well as authentication
// with those keys
type WebAuthnController struct {
App chainlink.Application
inProgressRegistrationsStore *sessions.WebAuthnSessionStore
}
func NewWebAuthnController(app chainlink.Application) WebAuthnController {
return WebAuthnController{
App: app,
inProgressRegistrationsStore: sessions.NewWebAuthnSessionStore(),
}
}
func (c *WebAuthnController) BeginRegistration(ctx *gin.Context) {
user, ok := auth.GetAuthenticatedUser(ctx)
if !ok {
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("failed to obtain current user from context"))
return
}
orm := c.App.AuthenticationProvider()
uwas, err := orm.GetUserWebAuthn(user.Email)
if err != nil {
c.App.GetLogger().Errorf("failed to obtain current user MFA tokens: error in GetUserWebAuthn: %+v", err)
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("Unable to register key"))
return
}
webAuthnConfig := c.App.GetWebAuthnConfiguration()
options, err := c.inProgressRegistrationsStore.BeginWebAuthnRegistration(*user, uwas, webAuthnConfig)
if err != nil {
c.App.GetLogger().Errorf("error in BeginWebAuthnRegistration: %s", err)
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("internal Server Error"))
return
}
optionsp := presenters.NewRegistrationSettings(*options)
jsonAPIResponse(ctx, optionsp, "settings")
}
func (c *WebAuthnController) FinishRegistration(ctx *gin.Context) {
user, ok := auth.GetAuthenticatedUser(ctx)
if !ok {
logger.Sugared(c.App.GetLogger()).AssumptionViolationf("failed to obtain current user from context")
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("Unable to register key"))
return
}
orm := c.App.AuthenticationProvider()
uwas, err := orm.GetUserWebAuthn(user.Email)
if err != nil {
c.App.GetLogger().Errorf("failed to obtain current user MFA tokens: error in GetUserWebAuthn: %s", err)
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("Unable to register key"))
return
}
webAuthnConfig := c.App.GetWebAuthnConfiguration()
credential, err := c.inProgressRegistrationsStore.FinishWebAuthnRegistration(*user, uwas, ctx.Request, webAuthnConfig)
if err != nil {
c.App.GetLogger().Errorf("error in FinishWebAuthnRegistration: %s", err)
jsonAPIError(ctx, http.StatusBadRequest, errors.New("registration was unsuccessful"))
return
}
if sessions.AddCredentialToUser(c.App.AuthenticationProvider(), user.Email, credential) != nil {
c.App.GetLogger().Errorf("Could not save WebAuthn credential to DB for user: %s", user.Email)
jsonAPIError(ctx, http.StatusInternalServerError, errors.New("internal Server Error"))
return
}
// Forward registered credentials for audit logs
credj, err := json.Marshal(credential)
if err != nil {
c.App.GetLogger().Errorf("error in Marshal credentials: %s", err)
jsonAPIError(ctx, http.StatusBadRequest, errors.New("registration was unsuccessful"))
return
}
c.App.GetAuditLogger().Audit(audit.Auth2FAEnrolled, map[string]interface{}{"email": user.Email, "credential": string(credj)})
ctx.String(http.StatusOK, "{}")
}