Skip to content

Commit

Permalink
fix: add option to override on user
Browse files Browse the repository at this point in the history
  • Loading branch information
J0 committed Sep 28, 2024
1 parent bee17da commit cb1ac2a
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 8 deletions.
49 changes: 46 additions & 3 deletions internal/api/mfa.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,55 @@ type UnenrollFactorResponse struct {

type WebAuthnParams struct {
RPID string `json:"rp_id,omitempty"`
// TODO: reconcile this later
// Can encode multiple origins as comma separated values like: "origin1,origin2"
RPOrigins string `json:"rp_origins,omitempty"`
AssertionResponse *wbnprotocol.CredentialAssertionResponse `json:"assertion_response,omitempty"`
CreationResponse *wbnprotocol.CredentialCreationResponse `json:"creation_response,omitempty"`
}

func (w *WebAuthnParams) GetRPOrigins() []string {
if w.RPOrigins == "" {
return nil
}
return strings.Split(w.RPOrigins, ",")
}

func (w *WebAuthnParams) ToConfig() (*webauthn.WebAuthn, error) {
if w.RPID == "" {
return nil, fmt.Errorf("WebAuthn RP ID cannot be empty")
}

origins := w.GetRPOrigins()
if len(origins) == 0 {
return nil, fmt.Errorf("WebAuthn RP Origins cannot be empty")
}

var validOrigins []string
var invalidOrigins []string

for _, origin := range origins {
parsedURL, err := url.Parse(origin)
if err != nil || (parsedURL.Scheme != "https" && parsedURL.Scheme != "http") || parsedURL.Host == "" {
invalidOrigins = append(invalidOrigins, origin)
} else {
validOrigins = append(validOrigins, origin)
}
}

if len(invalidOrigins) > 0 {
return nil, fmt.Errorf("Invalid RP origins: %s", strings.Join(invalidOrigins, ", "))
}

// TODO: Find a more sensible default
wconfig := &webauthn.Config{
RPDisplayName: w.RPID,
RPID: w.RPID,
RPOrigins: validOrigins,
}

return webauthn.New(wconfig)
}

const (
QRCodeGenerationErrorMessage = "Error generating QR Code"
)
Expand Down Expand Up @@ -525,7 +568,7 @@ func (a *API) challengeWebAuthnFactor(w http.ResponseWriter, r *http.Request) er
if params.WebAuthn == nil {
return badRequestError(ErrorCodeValidationFailed, "WebAuthn config required")
}
webAuthn, err := validateWebAuthnConfig(params.WebAuthn)
webAuthn, err := params.WebAuthn.ToConfig()
if err != nil {
return err
}
Expand Down Expand Up @@ -880,7 +923,7 @@ func (a *API) verifyWebAuthnFactor(w http.ResponseWriter, r *http.Request, param
case factor.IsUnverified() && params.WebAuthn.CreationResponse == nil:
return badRequestError(ErrorCodeValidationFailed, "WebAuthn Creation Response required to login")
default:
webAuthn, err = validateWebAuthnConfig(params.WebAuthn)
webAuthn, err = params.WebAuthn.ToConfig()
if err != nil {
return err
}
Expand Down
17 changes: 12 additions & 5 deletions internal/models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -933,19 +933,26 @@ func (u *User) FindOwnedFactorByID(tx *storage.Connection, factorID uuid.UUID) (
}
return &factor, nil
}

func (user *User) WebAuthnID() []byte {
// TODO: confirm this user ID
if webAuthnID, ok := user.UserMetaData["web_authn_id"].(string); ok && webAuthnID != "" {
return []byte(webAuthnID)
}
return []byte(user.ID.String())
}

func (user *User) WebAuthnName() string {
// TODO: Allow for overrides on this
return string(user.Email)
if webAuthnName, ok := user.UserMetaData["web_authn_name"].(string); ok && webAuthnName != "" {
return webAuthnName
}
return user.Email.String()
}

func (user *User) WebAuthnDisplayName() string {
// TODO:
return string(user.Email)
if webAuthnDisplayName, ok := user.UserMetaData["web_authn_display_name"].(string); ok && webAuthnDisplayName != "" {
return webAuthnDisplayName
}
return user.Email.String()
}

func (user *User) WebAuthnCredentials() []webauthn.Credential {
Expand Down

0 comments on commit cb1ac2a

Please sign in to comment.