Skip to content

Commit

Permalink
fix: working registration code flow
Browse files Browse the repository at this point in the history
  • Loading branch information
Benehiko committed Jul 12, 2023
1 parent ea6697e commit 9b294a3
Show file tree
Hide file tree
Showing 12 changed files with 41 additions and 10 deletions.
5 changes: 4 additions & 1 deletion embedx/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,9 @@
"oidc": {
"$ref": "#/definitions/selfServiceAfterRegistrationMethod"
},
"code": {
"$ref": "#/definitions/selfServiceAfterRegistrationMethod"
},
"hooks": {
"$ref": "#/definitions/selfServiceHooks"
}
Expand Down Expand Up @@ -2740,4 +2743,4 @@
"selfservice"
],
"additionalProperties": false
}
}
6 changes: 4 additions & 2 deletions identity/credentials_code.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

package identity

import "github.com/ory/x/sqlxx"
import (
"database/sql"
)

// CredentialsOTP represents an OTP code
//
Expand All @@ -13,5 +15,5 @@ type CredentialsCode struct {
CodeHMAC string `json:"code_hmac"`

// UsedAt indicates whether and when a recovery code was used.
UsedAt sqlxx.NullTime `json:"used_at,omitempty"`
UsedAt sql.NullTime `json:"used_at,omitempty"`
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM identity_credential_types WHERE name = 'code';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO identity_credential_types (id, name) SELECT '14f3b7e2-8725-4068-be39-8a796485fd97', 'code' WHERE NOT EXISTS ( SELECT * FROM identity_credential_types WHERE name = 'code');
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM identity_credential_types WHERE name = 'code';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO identity_credential_types (id, name) SELECT '14f3b7e2-8725-4068-be39-8a796485fd97', 'code' WHERE NOT EXISTS ( SELECT * FROM identity_credential_types WHERE name = 'code');
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM identity_credential_types WHERE name = 'code';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO identity_credential_types (id, name) SELECT '14f3b7e2-8725-4068-be39-8a796485fd97', 'code' WHERE NOT EXISTS ( SELECT * FROM identity_credential_types WHERE name = 'code');
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM identity_credential_types WHERE name = 'code';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO identity_credential_types (id, name) SELECT '14f3b7e2-8725-4068-be39-8a796485fd97', 'code' WHERE NOT EXISTS ( SELECT * FROM identity_credential_types WHERE name = 'code');
29 changes: 22 additions & 7 deletions selfservice/strategy/code/strategy_registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package code

import (
"context"
"database/sql"
"encoding/json"
"net/http"

Expand Down Expand Up @@ -81,18 +82,32 @@ func (s *Strategy) PopulateRegistrationMethod(r *http.Request, rf *registration.
return s.PopulateMethod(r, rf)
}

func (s *Strategy) handleIdentityTraits(ctx context.Context, f *registration.Flow, p *UpdateRegistrationFlowWithCodeMethod, i *identity.Identity) error {
type options func(*identity.Identity) error

func WithCredentials(code string, usedAt sql.NullTime) options {
return func(i *identity.Identity) error {
return i.SetCredentialsWithConfig(identity.CredentialsTypeCodeAuth, identity.Credentials{Type: identity.CredentialsTypePassword, Identifiers: []string{}}, &identity.CredentialsCode{CodeHMAC: code, UsedAt: usedAt})
}
}

func (s *Strategy) handleIdentityTraits(ctx context.Context, f *registration.Flow, p *UpdateRegistrationFlowWithCodeMethod, i *identity.Identity, opts ...options) error {
f.TransientPayload = p.TransientPayload
if len(p.Traits) == 0 {
p.Traits = json.RawMessage("{}")
}

// we explicitly set the Code credentials type
i.Traits = identity.Traits(p.Traits)
if err := i.SetCredentialsWithConfig(s.ID(), identity.Credentials{Type: s.ID(), Identifiers: []string{}}, &identity.CredentialsCode{CodeHMAC: ""}); err != nil {
if err := i.SetCredentialsWithConfig(s.ID(), identity.Credentials{Type: s.ID(), Identifiers: []string{}}, &identity.CredentialsCode{CodeHMAC: "", UsedAt: sql.NullTime{}}); err != nil {
return err
}

for _, opt := range opts {
if err := opt(i); err != nil {
return err
}
}

// Validate the identity
if err := s.deps.IdentityValidator().Validate(ctx, i); err != nil {
return err
Expand Down Expand Up @@ -210,19 +225,19 @@ func (s *Strategy) Register(w http.ResponseWriter, r *http.Request, f *registrat
// we are in the second submission state of the flow
// we need to check the code and update the identity

// first lets ensure the traits are still correct
if err := s.handleIdentityTraits(r.Context(), f, &p, i); err != nil {
// Step 1: Attempt to use the code
registrationCode, err := s.deps.RegistrationCodePersister().UseRegistrationCode(r.Context(), f.ID, p.Code)
if err != nil {
return s.HandleRegistrationError(w, r, f, &p, err)
}

_, err := s.deps.RegistrationCodePersister().UseRegistrationCode(r.Context(), f.ID, p.Code)
if err != nil {
// Step 2: The code was correct, populate the Identity credentials and traits
if err := s.handleIdentityTraits(r.Context(), f, &p, i, WithCredentials(registrationCode.CodeHMAC, registrationCode.UsedAt)); err != nil {
return s.HandleRegistrationError(w, r, f, &p, err)
}

// since nothing has errored yet, we can assume that the code is correct
// and we can update the registration flow

f.SetState(flow.StatePassedChallenge)

if err := s.deps.RegistrationFlowPersister().UpdateRegistrationFlow(r.Context(), f); err != nil {
Expand Down
3 changes: 3 additions & 0 deletions selfservice/strategy/code/strategy_registration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ func TestRegistrationCodeStrategy(t *testing.T) {
testhelpers.StrategyEnable(t, conf, string(identity.CredentialsTypeCodeAuth), true)
conf.MustSet(ctx, config.ViperKeySelfServiceBrowserDefaultReturnTo, "https://www.ory.sh")
conf.MustSet(ctx, config.ViperKeyURLsAllowedReturnToDomains, []string{"https://www.ory.sh"})
conf.MustSet(ctx, config.ViperKeySelfServiceRegistrationAfter+".code.hooks", []map[string]interface{}{
{"hook": "session"},
})

_ = testhelpers.NewRecoveryUIFlowEchoServer(t, reg)
_ = testhelpers.NewRegistrationUIFlowEchoServer(t, reg)
Expand Down

0 comments on commit 9b294a3

Please sign in to comment.