refactor: consolidate authentication and DID handling logic

This commit is contained in:
Prad Nukala 2024-12-09 18:19:46 -05:00
parent ce3d073abd
commit f8d362352d
23 changed files with 144 additions and 217 deletions

View File

@ -8,8 +8,7 @@ import (
"syscall/js"
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/cmd/motr/internal"
"github.com/onsonr/sonr/pkg/common/controller"
"github.com/onsonr/sonr/pkg/common/dids"
"github.com/onsonr/sonr/pkg/vault"
"github.com/onsonr/sonr/pkg/vault/types"
)
@ -48,8 +47,8 @@ func main() {
js.Global().Set("processConfig", js.FuncOf(processConfig))
e := echo.New()
e.Use(internal.WasmContextMiddleware)
e.Use(controller.Middleware(nil))
e.Use(vault.WasmContextMiddleware)
e.Use(dids.Middleware(nil))
vault.RegisterRoutes(e, config)
internal.ServeFetch(e)
vault.ServeFetch(e)
}

View File

@ -2,8 +2,6 @@ package forms
import (
"fmt"
"strconv"
"errors"
"github.com/onsonr/sonr/pkg/blocks/layout"
)
@ -17,30 +15,6 @@ func (d CreateProfileData) IsHumanLabel() string {
return fmt.Sprintf("What is %d + %d?", d.FirstNumber, d.LastNumber)
}
func ValidateCreateProfileForm(formData map[string][]string) error {
// Validate ishuman slider
ishumanValues := formData["is_human"]
if len(ishumanValues) == 0 {
return errors.New("human verification is required")
}
ishumanSum, err := strconv.Atoi(ishumanValues[0])
if err != nil {
return errors.New("invalid human verification value")
}
// Get the expected sum from the form data
firstNum, _ := strconv.Atoi(formData["first_number"][0])
lastNum, _ := strconv.Atoi(formData["last_number"][0])
expectedSum := firstNum + lastNum
if ishumanSum != expectedSum {
return errors.New("incorrect sum for human verification")
}
return nil
}
// ProfileForm is a standard form styled like a card
templ CreateProfile(action string, method string, data CreateProfileData) {
<form action={ templ.SafeURL(action) } method={ method }>
@ -61,26 +35,7 @@ templ CreateProfile(action string, method string, data CreateProfileData) {
</div>
</sl-input>
@layout.Spacer()
<sl-range
name="is_human"
label={ data.IsHumanLabel() }
help-text="Prove you are a human."
min="0"
max={ fmt.Sprint(data.FirstNumber + data.LastNumber) }
step="1"
onchange="validateSum(this)"
></sl-range>
<script>
function validateSum(slider) {
const expectedSum = { fmt.Sprint(data.FirstNumber + data.LastNumber) };
const value = parseInt(slider.value);
if (value !== expectedSum) {
slider.setCustomValidity("Please select the correct sum");
} else {
slider.setCustomValidity("");
}
}
</script>
<sl-range name="is_human" label={ data.IsHumanLabel() } help-text="Prove you are a human." min="0" max="9" step="1"></sl-range>
<div slot="footer">
<sl-button href="/" outline>
<sl-icon slot="prefix" name="arrow-left" library="sonr"></sl-icon>
@ -101,6 +56,3 @@ templ CreateProfile(action string, method string, data CreateProfileData) {
</sl-card>
</form>
}
templ isHumanSlider(targetSum string) {
}

View File

@ -126,29 +126,4 @@ func CreateProfile(action string, method string, data CreateProfileData) templ.C
})
}
func isHumanSlider(targetSum string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
if templ_7745c5c3_Var6 == nil {
templ_7745c5c3_Var6 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
return templ_7745c5c3_Err
})
}
var _ = templruntime.GeneratedTemplate

View File

@ -0,0 +1,46 @@
package forms
import "github.com/onsonr/sonr/pkg/blocks/layout"
type SetupWalletData struct {
TurnstileSiteKey string
FirstNumber int
LastNumber int
}
// SetupWallet is a standard form styled like a card
templ SetupWallet(action string, method string, data CreateProfileData) {
<form action={ templ.SafeURL(action) } method={ method }>
<sl-card class="card-form gap-4 max-w-lg">
<div slot="header">
<div class="w-full py-1">
<sl-progress-bar value="50"></sl-progress-bar>
</div>
</div>
@layout.Spacer()
<sl-input name="handle" placeholder="thoughtdiff" type="text" label="Handle" minlength="4" maxlength="12" required>
<div slot="prefix">
<sl-icon name="at-sign" library="sonr"></sl-icon>
</div>
</sl-input>
@layout.Spacer()
<div slot="footer">
<sl-button href="/" outline>
<sl-icon slot="prefix" name="arrow-left" library="sonr"></sl-icon>
Skip for now
</sl-button>
<sl-button type="submit">
Done
<sl-icon slot="suffix" name="arrow-right" library="sonr"></sl-icon>
</sl-button>
</div>
<style>
.card-form [slot='footer'] {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
</sl-card>
</form>
}

View File

@ -0,0 +1,87 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.793
package forms
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "github.com/onsonr/sonr/pkg/blocks/layout"
type SetupWalletData struct {
TurnstileSiteKey string
FirstNumber int
LastNumber int
}
// SetupWallet is a standard form styled like a card
func SetupWallet(action string, method string, data CreateProfileData) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form action=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 templ.SafeURL = templ.SafeURL(action)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var2)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" method=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(method)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/blocks/forms/setup_wallet.templ`, Line: 13, Col: 55}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><sl-card class=\"card-form gap-4 max-w-lg\"><div slot=\"header\"><div class=\"w-full py-1\"><sl-progress-bar value=\"50\"></sl-progress-bar></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = layout.Spacer().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<sl-input name=\"handle\" placeholder=\"thoughtdiff\" type=\"text\" label=\"Handle\" minlength=\"4\" maxlength=\"12\" required><div slot=\"prefix\"><sl-icon name=\"at-sign\" library=\"sonr\"></sl-icon></div></sl-input>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = layout.Spacer().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div slot=\"footer\"><sl-button href=\"/\" outline><sl-icon slot=\"prefix\" name=\"arrow-left\" library=\"sonr\"></sl-icon> Skip for now</sl-button> <sl-button type=\"submit\">Done <sl-icon slot=\"suffix\" name=\"arrow-right\" library=\"sonr\"></sl-icon></sl-button></div><style>\n \t\t.card-form [slot='footer'] {\n \t\tdisplay: flex;\n \t\tjustify-content: space-between;\n \t\talign-items: center;\n \t\t}\n\t\t</style></sl-card></form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
}
var _ = templruntime.GeneratedTemplate

View File

@ -1,4 +1,4 @@
package controller
package dids
import (
"github.com/labstack/echo/v4"

View File

@ -1,7 +1,7 @@
//go:build js && wasm
// +build js,wasm
package controller
package dids
import (
"fmt"

View File

@ -1,47 +0,0 @@
package passkeys
import (
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/protocol/webauthncose"
)
func defaultPrimaryAttestationFormats() []protocol.AttestationFormat {
return []protocol.AttestationFormat{
protocol.AttestationFormatApple,
protocol.AttestationFormatAndroidKey,
protocol.AttestationFormatAndroidSafetyNet,
protocol.AttestationFormatFIDOUniversalSecondFactor,
}
}
func defaultSecondaryAttestationFormats() []protocol.AttestationFormat {
return []protocol.AttestationFormat{
protocol.AttestationFormatPacked,
protocol.AttestationFormatTPM,
}
}
func defaultAuthenticatorSelection() protocol.AuthenticatorSelection {
return protocol.AuthenticatorSelection{
AuthenticatorAttachment: protocol.Platform,
ResidentKey: protocol.ResidentKeyRequirementRequired,
UserVerification: protocol.VerificationRequired,
}
}
func buildCredentialParameters() []protocol.CredentialParameter {
return []protocol.CredentialParameter{
{
Type: "public-key",
Algorithm: webauthncose.AlgES256,
},
{
Type: "public-key",
Algorithm: webauthncose.AlgES256K,
},
{
Type: "public-key",
Algorithm: webauthncose.AlgEdDSA,
},
}
}

View File

@ -1,59 +0,0 @@
package passkeys
import (
"github.com/go-webauthn/webauthn/protocol"
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/crypto/mpc"
"github.com/onsonr/sonr/pkg/common"
)
func Create(c echo.Context, handle string, ks mpc.Keyset) protocol.PublicKeyCredentialCreationOptions {
origin := c.Request().Host
svcName := c.Request().Host
addr := ks.Address()
return buildRegisterOptions(addr, handle, ks, origin, svcName)
}
func buildRegisterOptions(addr string, handle string, ks mpc.Keyset, origin string, svcName string) protocol.PublicKeyCredentialCreationOptions {
return protocol.PublicKeyCredentialCreationOptions{
Attestation: protocol.PreferDirectAttestation,
AttestationFormats: defaultPrimaryAttestationFormats(),
AuthenticatorSelection: defaultAuthenticatorSelection(),
RelyingParty: buildServiceEntity(origin, svcName),
Extensions: buildExtensions(ks),
Parameters: buildCredentialParameters(),
Timeout: 10000,
User: buildUserEntity(addr, handle),
}
}
func buildExtensions(ks mpc.Keyset) protocol.AuthenticationExtensions {
return protocol.AuthenticationExtensions{
"largeBlob": common.LargeBlob{
Support: "required",
Write: ks.UserJSON(),
},
"payment": common.Payment{
IsPayment: true,
},
}
}
func buildServiceEntity(name string, host string) protocol.RelyingPartyEntity {
return protocol.RelyingPartyEntity{
CredentialEntity: protocol.CredentialEntity{
Name: name,
},
ID: host,
}
}
func buildUserEntity(userAddress string, userHandle string) protocol.UserEntity {
return protocol.UserEntity{
ID: userAddress,
DisplayName: userHandle,
CredentialEntity: protocol.CredentialEntity{
Name: userAddress,
},
}
}

View File

@ -1,15 +0,0 @@
package passkeys
//
// import (
// "github.com/go-webauthn/webauthn/protocol"
// "github.com/labstack/echo/v4"
// "github.com/onsonr/sonr/crypto/mpc"
// )
//
// func Link(c echo.Context, handle string, ks mpc.Keyset) protocol.PublicKeyCredentialCreationOptions {
// origin := c.Request().Host
// svcName := c.Request().Host
// addr := ks.Address()
// return c.String(200, origin+" "+svcName+" "+addr+" "+handle)
// }

View File

@ -1 +0,0 @@
package passkeys

View File

@ -3,8 +3,8 @@ package handlers
import (
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/pkg/common/response"
"github.com/onsonr/sonr/pkg/gateway/internal/pages/index"
"github.com/onsonr/sonr/pkg/gateway/internal/session"
"github.com/onsonr/sonr/pkg/gateway/pages/index"
)
func HandleIndex(c echo.Context) error {

View File

@ -12,7 +12,7 @@ import (
"github.com/onsonr/sonr/pkg/blocks/forms"
"github.com/onsonr/sonr/pkg/common/response"
"github.com/onsonr/sonr/pkg/gateway/internal/database"
"github.com/onsonr/sonr/pkg/gateway/internal/pages/register"
"github.com/onsonr/sonr/pkg/gateway/pages/register"
)
func HandleRegisterView(c echo.Context) error {
@ -24,16 +24,6 @@ func HandleRegisterView(c echo.Context) error {
}
func HandleRegisterStart(c echo.Context) error {
// Validate the form submission
formData := make(map[string][]string)
for key, values := range c.Request().Form {
formData[key] = values
}
if err := forms.ValidateCreateProfileForm(formData); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
challenge, _ := protocol.CreateChallenge()
handle := c.FormValue("handle")
firstName := c.FormValue("first_name")

View File

@ -1,7 +1,7 @@
//go:build js && wasm
// +build js,wasm
package internal
package vault
import (
"bytes"

View File

@ -1,7 +1,7 @@
//go:build js && wasm
// +build js,wasm
package internal
package vault
import (
"encoding/base64"