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

Commit

Permalink
Allow login in anonymous user promotion
Browse files Browse the repository at this point in the history
ref #1470
ref #1474
  • Loading branch information
louischan-oursky committed Jun 3, 2020
2 parents edd3fc8 + a5582cb commit 9353f96
Show file tree
Hide file tree
Showing 18 changed files with 871 additions and 292 deletions.
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

0 comments on commit 9353f96

Please sign in to comment.