feat: cred props
parent
5be5de02d8
commit
e5cdb175b4
|
@ -87,18 +87,20 @@ func WebauthnRegistrationPUT(ctx *middlewares.AutheliaCtx) {
|
|||
}
|
||||
|
||||
var (
|
||||
opts *protocol.CredentialCreation
|
||||
creation *protocol.CredentialCreation
|
||||
)
|
||||
|
||||
opts := []webauthn.RegistrationOption{
|
||||
webauthn.WithExclusions(user.WebAuthnCredentialDescriptors()),
|
||||
webauthn.WithExtensions(map[string]any{"credProps": true}),
|
||||
webauthn.WithResidentKeyRequirement(protocol.ResidentKeyRequirementDiscouraged),
|
||||
}
|
||||
|
||||
data := session.Webauthn{
|
||||
DisplayName: bodyJSON.Description,
|
||||
Description: bodyJSON.Description,
|
||||
}
|
||||
|
||||
extensions := map[string]any{
|
||||
"credProps": true,
|
||||
}
|
||||
|
||||
if opts, data.SessionData, err = w.BeginRegistration(user, webauthn.WithExclusions(user.WebAuthnCredentialDescriptors()), webauthn.WithExtensions(extensions)); err != nil {
|
||||
if creation, data.SessionData, err = w.BeginRegistration(user, opts...); err != nil {
|
||||
ctx.Logger.Errorf("Unable to create %s registration challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
|
||||
|
||||
respondUnauthorized(ctx, messageUnableToRegisterSecurityKey)
|
||||
|
@ -116,7 +118,7 @@ func WebauthnRegistrationPUT(ctx *middlewares.AutheliaCtx) {
|
|||
return
|
||||
}
|
||||
|
||||
if err = ctx.SetJSONBody(opts); err != nil {
|
||||
if err = ctx.SetJSONBody(creation); err != nil {
|
||||
ctx.Logger.Errorf(logFmtErrWriteResponseBody, regulation.AuthTypeWebauthn, userSession.Username, err)
|
||||
|
||||
respondUnauthorized(ctx, messageUnableToRegisterSecurityKey)
|
||||
|
@ -197,34 +199,9 @@ func WebauthnRegistrationPOST(ctx *middlewares.AutheliaCtx) {
|
|||
return
|
||||
}
|
||||
|
||||
var discoverable bool
|
||||
device := model.NewWebauthnDeviceFromCredential(w.Config.RPID, userSession.Username, userSession.Webauthn.Description, credential)
|
||||
|
||||
if value, ok := response.ClientExtensionResults["credProps"]; ok {
|
||||
switch credprops := value.(type) {
|
||||
case map[string]any:
|
||||
ctx.Logger.Debug("Is type")
|
||||
|
||||
var v any
|
||||
|
||||
if v, ok = credprops["rk"]; ok {
|
||||
ctx.Logger.Debug("found rk")
|
||||
|
||||
if discoverable, ok = v.(bool); ok {
|
||||
ctx.Logger.Debug("found rk bool")
|
||||
} else {
|
||||
ctx.Logger.Debugf("not found rk bool %T", v)
|
||||
}
|
||||
} else {
|
||||
ctx.Logger.Debug("not found rk")
|
||||
}
|
||||
default:
|
||||
ctx.Logger.Debugf("type is %T", credprops)
|
||||
}
|
||||
}
|
||||
|
||||
device := model.NewWebauthnDeviceFromCredential(w.Config.RPID, userSession.Username, userSession.Webauthn.DisplayName, credential)
|
||||
|
||||
device.Discoverable = discoverable
|
||||
device.Discoverable = webauthnCredentialCreationIsDiscoverable(ctx, response)
|
||||
|
||||
if err = ctx.Providers.StorageProvider.SaveWebauthnDevice(ctx, device); err != nil {
|
||||
ctx.Logger.Errorf("Unable to save %s device registration for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
|
||||
|
|
|
@ -45,20 +45,19 @@ func WebauthnAssertionGET(ctx *middlewares.AutheliaCtx) {
|
|||
return
|
||||
}
|
||||
|
||||
var opts = []webauthn.LoginOption{
|
||||
webauthn.WithAllowedCredentials(user.WebAuthnCredentialDescriptors()),
|
||||
}
|
||||
|
||||
extensions := map[string]any{}
|
||||
|
||||
if user.HasFIDOU2F() {
|
||||
extensions["appid"] = w.Config.RPOrigins[0]
|
||||
}
|
||||
|
||||
var opts = []webauthn.LoginOption{
|
||||
webauthn.WithAllowedCredentials(user.WebAuthnCredentialDescriptors()),
|
||||
}
|
||||
|
||||
if len(extensions) != 0 {
|
||||
opts = append(opts, webauthn.WithAssertionExtensions(extensions))
|
||||
}
|
||||
|
||||
var assertion *protocol.CredentialAssertion
|
||||
|
||||
data := session.Webauthn{}
|
||||
|
|
|
@ -70,3 +70,34 @@ func newWebauthn(ctx *middlewares.AutheliaCtx) (w *webauthn.WebAuthn, err error)
|
|||
|
||||
return webauthn.New(config)
|
||||
}
|
||||
|
||||
func webauthnCredentialCreationIsDiscoverable(ctx *middlewares.AutheliaCtx, response *protocol.ParsedCredentialCreationData) (discoverable bool) {
|
||||
if value, ok := response.ClientExtensionResults["credProps"]; ok {
|
||||
switch credentialProperties := value.(type) {
|
||||
case map[string]any:
|
||||
var v any
|
||||
|
||||
if v, ok = credentialProperties["rk"]; ok {
|
||||
if discoverable, ok = v.(bool); ok {
|
||||
ctx.Logger.WithFields(map[string]any{"discoverable": discoverable}).Trace("Determined Credential Discoverability via Client Extension Results")
|
||||
|
||||
return discoverable
|
||||
} else {
|
||||
ctx.Logger.WithFields(map[string]any{"discoverable": false}).Trace("Assuming Credential Discoverability is false as the 'rk' field for the 'credProps' extension in the Client Extension Results was not a boolean")
|
||||
}
|
||||
} else {
|
||||
ctx.Logger.WithFields(map[string]any{"discoverable": false}).Trace("Assuming Credential Discoverability is false as the 'rk' field for the 'credProps' extension was missing from the Client Extension Results")
|
||||
}
|
||||
|
||||
return false
|
||||
default:
|
||||
ctx.Logger.WithFields(map[string]any{"discoverable": false}).Trace("Assuming Credential Discoverability is false as the 'credProps' extension in the Client Extension Results does not appear to be a dictionary")
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Logger.WithFields(map[string]any{"discoverable": false}).Trace("Assuming Credential Discoverability is false as the 'credProps' extension is missing from the Client Extension Results")
|
||||
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ type UserSession struct {
|
|||
// Webauthn holds the standard webauthn session data plus some extra.
|
||||
type Webauthn struct {
|
||||
*webauthn.SessionData
|
||||
DisplayName string
|
||||
Description string
|
||||
}
|
||||
|
||||
// Identity of the user who is being verified.
|
||||
|
|
Loading…
Reference in New Issue