Skip to content
This repository has been archived by the owner on Dec 22, 2023. It is now read-only.

Allow logging in in anonymous user promotion flow #1472

Merged
merged 7 commits into from
Jun 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions pkg/auth/dependency/interaction/flows/anonymous.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,17 @@ type ChallengeProvider interface {
}

type AnonymousFlow struct {
Enabled IsAnonymousIdentityEnabled
Interactions InteractionProvider
Anonymous AnonymousIdentityProvider
Challenges ChallengeProvider
}

func (f *AnonymousFlow) Authenticate(requestJWT string, clientID string) (*authn.Attrs, error) {
if !f.Enabled {
return nil, ErrAnonymousDisabled
}

iden, request, err := f.Anonymous.ParseRequest(requestJWT)
if err != nil || request.Action != anonymous.RequestActionAuth {
return nil, interaction.ErrInvalidCredentials
Expand Down Expand Up @@ -101,6 +106,10 @@ func (f *AnonymousFlow) Authenticate(requestJWT string, clientID string) (*authn
}

func (f *AnonymousFlow) DecodeUserID(requestJWT string) (string, anonymous.RequestAction, error) {
if !f.Enabled {
return "", "", ErrAnonymousDisabled
}

identity, request, err := f.Anonymous.ParseRequest(requestJWT)
if err != nil || identity == nil {
return "", "", interaction.ErrInvalidCredentials
Expand Down
33 changes: 32 additions & 1 deletion pkg/auth/dependency/interaction/flows/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/skygeario/skygear-server/pkg/auth/dependency/hook"
"github.com/skygeario/skygear-server/pkg/auth/dependency/session"
"github.com/skygeario/skygear-server/pkg/core/auth/authinfo"
"github.com/skygeario/skygear-server/pkg/core/authn"
"github.com/skygeario/skygear-server/pkg/core/config"
"github.com/skygeario/skygear-server/pkg/core/time"
)
Expand All @@ -31,9 +32,39 @@ func ProvideUserController(
}
}

type IsAnonymousIdentityEnabled bool

func ProvideIsAnonymousIdentityEnabled(c *config.TenantConfiguration) IsAnonymousIdentityEnabled {
for _, i := range c.AppConfig.Authentication.Identities {
if i == string(authn.IdentityTypeAnonymous) {
return true
}
}
return false
}

func ProvideWebAppFlow(
c *config.TenantConfiguration,
idp IdentityProvider,
up UserProvider,
hp hook.Provider,
ip InteractionProvider,
uc *UserController,
) *WebAppFlow {
return &WebAppFlow{
ConflictConfig: c.AppConfig.Identity.OnConflict,
Identities: idp,
Users: up,
Hooks: hp,
Interactions: ip,
UserController: uc,
}
}

var DependencySet = wire.NewSet(
wire.Struct(new(WebAppFlow), "*"),
ProvideWebAppFlow,
wire.Struct(new(AnonymousFlow), "*"),
wire.Struct(new(PasswordFlow), "*"),
ProvideIsAnonymousIdentityEnabled,
ProvideUserController,
)
4 changes: 4 additions & 0 deletions pkg/auth/dependency/interaction/flows/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ var UnsupportedConfiguration = skyerr.Forbidden.WithReason("UnsupportedConfigura
var ErrUnsupportedConfiguration = UnsupportedConfiguration.New(
"this operation is not supported by app configuration",
)

var ErrAnonymousDisabled = UnsupportedConfiguration.New(
"anonymous user is disabled by configuration",
)
10 changes: 10 additions & 0 deletions pkg/auth/dependency/interaction/flows/identity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package flows

import (
"github.com/skygeario/skygear-server/pkg/auth/dependency/identity"
"github.com/skygeario/skygear-server/pkg/core/authn"
)

type IdentityProvider interface {
GetByClaims(typ authn.IdentityType, claims map[string]interface{}) (string, *identity.Info, error)
}
107 changes: 41 additions & 66 deletions pkg/auth/dependency/interaction/flows/webapp.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package flows

import (
"github.com/skygeario/skygear-server/pkg/auth/dependency/hook"
"github.com/skygeario/skygear-server/pkg/auth/dependency/identity"
"github.com/skygeario/skygear-server/pkg/auth/dependency/identity/loginid"
"github.com/skygeario/skygear-server/pkg/auth/dependency/interaction"
"github.com/skygeario/skygear-server/pkg/core/authn"
"github.com/skygeario/skygear-server/pkg/core/config"
)

type WebAppFlow struct {
ConflictConfig *config.IdentityConflictConfiguration
Identities IdentityProvider
Users UserProvider
Hooks hook.Provider
Interactions InteractionProvider
UserController *UserController
}
Expand All @@ -25,31 +31,11 @@ func (f *WebAppFlow) LoginWithLoginID(loginID string) (*WebAppResult, error) {
return nil, err
}

s, err := f.Interactions.GetInteractionState(i)
step, err := f.handleLogin(i)
if err != nil {
return nil, err
}

if s.CurrentStep().Step != interaction.StepAuthenticatePrimary || len(s.CurrentStep().AvailableAuthenticators) <= 0 {
panic("interaction_flow_webapp: unexpected interaction state")
}

var step WebAppStep
switch s.CurrentStep().AvailableAuthenticators[0].Type {
case authn.AuthenticatorTypeOOB:
step = WebAppStepAuthenticateOOBOTP
err = f.Interactions.PerformAction(i, interaction.StepAuthenticatePrimary, &interaction.ActionTriggerOOBAuthenticator{
Authenticator: s.CurrentStep().AvailableAuthenticators[0],
})
if err != nil {
return nil, err
}
case authn.AuthenticatorTypePassword:
step = WebAppStepAuthenticatePassword
default:
panic("interaction_flow_webapp: unexpected authenticator type")
}

token, err := f.Interactions.SaveInteraction(i)
if err != nil {
return nil, err
Expand All @@ -75,60 +61,55 @@ func (f *WebAppFlow) SignupWithLoginID(loginIDKey, loginID string) (*WebAppResul
return nil, err
}

s, err := f.Interactions.GetInteractionState(i)
step, err := f.handleSignup(i)
if err != nil {
return nil, err
}

if s.CurrentStep().Step != interaction.StepSetupPrimaryAuthenticator || len(s.CurrentStep().AvailableAuthenticators) <= 0 {
token, err := f.Interactions.SaveInteraction(i)
if err != nil {
return nil, err
}

return &WebAppResult{
Step: step,
Token: token,
}, nil
}

func (f *WebAppFlow) handleLogin(i *interaction.Interaction) (WebAppStep, error) {
s, err := f.Interactions.GetInteractionState(i)
if err != nil {
return "", err
}

if s.CurrentStep().Step != interaction.StepAuthenticatePrimary || len(s.CurrentStep().AvailableAuthenticators) <= 0 {
panic("interaction_flow_webapp: unexpected interaction state")
}

var step WebAppStep

switch s.CurrentStep().AvailableAuthenticators[0].Type {
case authn.AuthenticatorTypeOOB:
step = WebAppStepSetupOOBOTP
err = f.Interactions.PerformAction(i, interaction.StepSetupPrimaryAuthenticator, &interaction.ActionTriggerOOBAuthenticator{
step = WebAppStepAuthenticateOOBOTP
err = f.Interactions.PerformAction(i, interaction.StepAuthenticatePrimary, &interaction.ActionTriggerOOBAuthenticator{
Authenticator: s.CurrentStep().AvailableAuthenticators[0],
})
if err != nil {
return nil, err
return "", err
}
case authn.AuthenticatorTypePassword:
step = WebAppStepSetupPassword
step = WebAppStepAuthenticatePassword
default:
panic("interaction_flow_webapp: unexpected authenticator type")
}

token, err := f.Interactions.SaveInteraction(i)
if err != nil {
return nil, err
}

return &WebAppResult{
Step: step,
Token: token,
}, nil
return step, nil
}

func (f *WebAppFlow) PromoteWithLoginID(loginIDKey, loginID string, userID string) (*WebAppResult, error) {
i, err := f.Interactions.NewInteractionAddIdentity(&interaction.IntentAddIdentity{
Identity: identity.Spec{
Type: authn.IdentityTypeLoginID,
Claims: map[string]interface{}{
identity.IdentityClaimLoginIDKey: loginIDKey,
identity.IdentityClaimLoginIDValue: loginID,
},
},
}, "", userID)
if err != nil {
return nil, err
}

func (f *WebAppFlow) handleSignup(i *interaction.Interaction) (WebAppStep, error) {
s, err := f.Interactions.GetInteractionState(i)
if err != nil {
return nil, err
return "", err
}

if s.CurrentStep().Step != interaction.StepSetupPrimaryAuthenticator || len(s.CurrentStep().AvailableAuthenticators) <= 0 {
Expand All @@ -144,25 +125,15 @@ func (f *WebAppFlow) PromoteWithLoginID(loginIDKey, loginID string, userID strin
Authenticator: s.CurrentStep().AvailableAuthenticators[0],
})
if err != nil {
return nil, err
return "", err
}
case authn.AuthenticatorTypePassword:
step = WebAppStepSetupPassword
default:
panic("interaction_flow_webapp: unexpected authenticator type")
}

i.Extra[WebAppExtraStateAnonymousUserPromotion] = "true"

token, err := f.Interactions.SaveInteraction(i)
if err != nil {
return nil, err
}

return &WebAppResult{
Step: step,
Token: token,
}, nil
return step, nil
}

func (f *WebAppFlow) EnterSecret(token string, secret string) (*WebAppResult, error) {
Expand Down Expand Up @@ -253,8 +224,8 @@ func (f *WebAppFlow) SetupSecret(token string, secret string) (*WebAppResult, er
return f.afterPrimaryAuthentication(i)

case interaction.IntentTypeAddIdentity:
if i.Extra[WebAppExtraStateAnonymousUserPromotion] == "true" {
return f.afterAnonymousUserPromotion(result)
if i.Extra[WebAppExtraStateAnonymousUserPromotion] != "" {
return f.afterAnonymousUserPromotion(i, result)
}

return &WebAppResult{
Expand Down Expand Up @@ -459,6 +430,10 @@ func (f *WebAppFlow) afterPrimaryAuthentication(i *interaction.Interaction) (*We
return nil, err
}

if i.Extra[WebAppExtraStateAnonymousUserPromotion] != "" {
return f.afterAnonymousUserPromotion(i, ir)
}

result, err := f.UserController.CreateSession(i, ir)
if err != nil {
return nil, err
Expand Down
Loading