Skip to content

Commit

Permalink
add a password creation option for accounts that do not have password…
Browse files Browse the repository at this point in the history
… authentication enabled
  • Loading branch information
Southclaws committed Dec 10, 2023
1 parent fa32eb0 commit 0ab7ff0
Show file tree
Hide file tree
Showing 16 changed files with 795 additions and 258 deletions.
26 changes: 26 additions & 0 deletions api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,19 @@ paths:
"200": { $ref: "#/components/responses/AuthSuccessOK" }

/v1/auth/password:
post:
operationId: AuthPasswordCreate
description: |
Given the requesting account does not have a password authentication,
add a password authentication method to it with the given password.
tags: [auth]
security: []
requestBody: { $ref: "#/components/requestBodies/AuthPasswordCreate" }
responses:
default: { $ref: "#/components/responses/InternalServerError" }
"404": { $ref: "#/components/responses/NotFound" }
"401": { $ref: "#/components/responses/Unauthorised" }
"200": { $ref: "#/components/responses/AuthSuccessOK" }
patch:
operationId: AuthPasswordUpdate
description: |
Expand Down Expand Up @@ -1225,6 +1238,11 @@ components:
application/json:
schema: { $ref: "#/components/schemas/AuthPair" }

AuthPasswordCreate:
content:
application/json:
schema: { $ref: "#/components/schemas/AuthPasswordInitialProps" }

AuthPasswordUpdate:
content:
application/json:
Expand Down Expand Up @@ -2021,6 +2039,14 @@ components:
example: "password"
type: string

AuthPasswordInitialProps:
type: object
required: [password]
properties:
password:
example: "password123"
type: string

AuthPasswordMutableProps:
type: object
required: [old, new]
Expand Down
57 changes: 49 additions & 8 deletions app/services/authentication/provider/password/password.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var (
ErrAccountAlreadyExists = errors.New("account already exists")
ErrPasswordMismatch = errors.New("password mismatch")
ErrNoPassword = errors.New("password not enabled")
ErrPasswordAlreadySet = errors.New("password already enabled")
ErrPasswordTooShort = errors.New("password too short")
ErrNotFound = errors.New("account not found")
)
Expand Down Expand Up @@ -68,14 +69,8 @@ func (b *Provider) Register(ctx context.Context, identifier string, password str
return nil, fault.Wrap(err, fctx.With(ctx), fmsg.With("failed to create account"))
}

hashed, err := argon2id.CreateHash(password, argon2id.DefaultParams)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx), fmsg.With("failed to create secure password hash"))
}

_, err = b.auth.Create(ctx, account.ID, id, xid.New().String(), string(hashed), nil)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx), fmsg.With("failed to create account authentication instance"))
if err := b.addPasswordAuth(ctx, account.ID, password); err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

return account, nil
Expand Down Expand Up @@ -133,6 +128,38 @@ func (b *Provider) Login(ctx context.Context, identifier string, password string
return &a.Account, nil
}

func (b *Provider) Create(ctx context.Context, aid account.AccountID, password string) (*account.Account, error) {
if len(password) < 8 {
return nil, fault.Wrap(ErrPasswordTooShort,
fctx.With(ctx),
ftag.With(ftag.InvalidArgument),
fmsg.WithDesc("too short", "Password must be at least 8 characters."))
}

acc, err := b.ar.GetByID(ctx, aid)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx), fmsg.With("failed to get account"))
}

_, exists, err := b.auth.LookupByHandle(ctx, id, acc.Handle)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

if exists {
return nil, fault.Wrap(ErrPasswordAlreadySet,
fctx.With(ctx),
ftag.With(ftag.InvalidArgument),
fmsg.WithDesc("already has password", "The specified account already uses password authentication."))
}

if err := b.addPasswordAuth(ctx, acc.ID, password); err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

return acc, nil
}

func (b *Provider) Update(ctx context.Context, aid account.AccountID, oldpassword, newpassword string) (*account.Account, error) {
if len(newpassword) < 8 {
return nil, fault.Wrap(ErrPasswordTooShort,
Expand Down Expand Up @@ -182,3 +209,17 @@ func (b *Provider) Update(ctx context.Context, aid account.AccountID, oldpasswor

return &auth.Account, nil
}

func (b *Provider) addPasswordAuth(ctx context.Context, accountID account.AccountID, password string) error {
hashed, err := argon2id.CreateHash(password, argon2id.DefaultParams)
if err != nil {
return fault.Wrap(err, fctx.With(ctx), fmsg.With("failed to create secure password hash"))
}

_, err = b.auth.Create(ctx, accountID, id, xid.New().String(), string(hashed), nil)
if err != nil {
return fault.Wrap(err, fctx.With(ctx), fmsg.With("failed to create account authentication instance"))
}

return nil
}
21 changes: 21 additions & 0 deletions app/transports/openapi/bindings/auth_password.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,27 @@ func (i *Authentication) AuthPasswordSignup(ctx context.Context, request openapi
}, nil
}

func (i *Authentication) AuthPasswordCreate(ctx context.Context, request openapi.AuthPasswordCreateRequestObject) (openapi.AuthPasswordCreateResponseObject, error) {
id, err := session.GetAccountID(ctx)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

u, err := i.p.Create(ctx, id, request.Body.Password)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

return openapi.AuthPasswordCreate200JSONResponse{
AuthSuccessOKJSONResponse: openapi.AuthSuccessOKJSONResponse{
Body: openapi.AuthSuccessOK{Id: u.ID.String()},
Headers: openapi.AuthSuccessOKResponseHeaders{
SetCookie: i.sm.Create(u.ID.String()).String(),
},
},
}, nil
}

func (i *Authentication) AuthPasswordUpdate(ctx context.Context, request openapi.AuthPasswordUpdateRequestObject) (openapi.AuthPasswordUpdateResponseObject, error) {
id, err := session.GetAccountID(ctx)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ require (
github.com/CloudyKit/jet/v6 v6.2.0 // indirect
github.com/Joker/jade v1.1.3 // indirect
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect
github.com/a8m/enter v0.0.0-20230407172335-1834787a98fe // indirect
github.com/andybalholm/brotli v1.0.6 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
Expand Down
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ github.com/Southclaws/fault v0.7.0 h1:qT0aOp+bUpvxm8fveBIJRcU/QfrBCmR6kMaAHyAknS
github.com/Southclaws/fault v0.7.0/go.mod h1:VUVkAWutC59SL16s6FTqf3I6I2z77RmnaW5XRz4bLOE=
github.com/Southclaws/opt v0.6.0 h1:DnsHXMfeW8vV1y2oa26bpx1dn76PERw4QNw25b6U498=
github.com/Southclaws/opt v0.6.0/go.mod h1:zGjXSHmM4ScFX3TLkCr8TdVvd4KAcZq0mwWtzqoqwwQ=
github.com/a8m/enter v0.0.0-20230407172335-1834787a98fe h1:Wx1QNWtwtyIOMCJ+zQ6NkweM+TB+DbNcoz56HibaBtI=
github.com/a8m/enter v0.0.0-20230407172335-1834787a98fe/go.mod h1:oIhrOH1HOtDThKUKzKLbeF979y2PjDTiLPSTe4kmTDE=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
Expand Down Expand Up @@ -310,6 +312,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI=
github.com/mattn/go-sqlite3 v1.14.18/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
Expand Down Expand Up @@ -344,6 +348,8 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwd
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oapi-codegen/runtime v1.1.0 h1:rJpoNUawn5XTvekgfkvSZr0RqEnoYpFkyvrzfWeFKWM=
github.com/oapi-codegen/runtime v1.1.0/go.mod h1:BeSfBkWWWnAnGdyS+S/GnlbmHKzf8/hwkvelJZDeKA8=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
Expand Down Expand Up @@ -388,6 +394,10 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down Expand Up @@ -590,6 +600,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
Loading

2 comments on commit 0ab7ff0

@vercel
Copy link

@vercel vercel bot commented on 0ab7ff0 Dec 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 0ab7ff0 Dec 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.