mirror of
https://github.com/matrix-org/dendrite.git
synced 2024-11-29 17:51:56 -06:00
refactoring user interactive auth:
- making members private as they aren't used outside of the package and in order to protect from concurrent writes - make the mutex protect the sessions only as they are written to concurrently
This commit is contained in:
parent
6cd1285ca0
commit
4954427ed7
|
@ -103,12 +103,13 @@ type userInteractiveFlow struct {
|
||||||
// the user already has a valid access token, but we want to double-check
|
// the user already has a valid access token, but we want to double-check
|
||||||
// that it isn't stolen by re-authenticating them.
|
// that it isn't stolen by re-authenticating them.
|
||||||
type UserInteractive struct {
|
type UserInteractive struct {
|
||||||
sync.RWMutex
|
flows []userInteractiveFlow
|
||||||
Flows []userInteractiveFlow
|
|
||||||
// Map of login type to implementation
|
// Map of login type to implementation
|
||||||
Types map[string]Type
|
types map[string]Type
|
||||||
// Map of session ID to completed login types, will need to be extended in future
|
// Map of session ID to completed login types, will need to be extended in future
|
||||||
Sessions map[string][]string
|
|
||||||
|
mutex sync.RWMutex
|
||||||
|
sessions map[string][]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUserInteractive(userAccountAPI api.UserLoginAPI, cfg *config.ClientAPI) *UserInteractive {
|
func NewUserInteractive(userAccountAPI api.UserLoginAPI, cfg *config.ClientAPI) *UserInteractive {
|
||||||
|
@ -117,22 +118,20 @@ func NewUserInteractive(userAccountAPI api.UserLoginAPI, cfg *config.ClientAPI)
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
}
|
}
|
||||||
return &UserInteractive{
|
return &UserInteractive{
|
||||||
Flows: []userInteractiveFlow{
|
flows: []userInteractiveFlow{
|
||||||
{
|
{
|
||||||
Stages: []string{typePassword.Name()},
|
Stages: []string{typePassword.Name()},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Types: map[string]Type{
|
types: map[string]Type{
|
||||||
typePassword.Name(): typePassword,
|
typePassword.Name(): typePassword,
|
||||||
},
|
},
|
||||||
Sessions: make(map[string][]string),
|
sessions: make(map[string][]string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInteractive) IsSingleStageFlow(authType string) bool {
|
func (u *UserInteractive) IsSingleStageFlow(authType string) bool {
|
||||||
u.RLock()
|
for _, f := range u.flows {
|
||||||
defer u.RUnlock()
|
|
||||||
for _, f := range u.Flows {
|
|
||||||
if len(f.Stages) == 1 && f.Stages[0] == authType {
|
if len(f.Stages) == 1 && f.Stages[0] == authType {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -141,10 +140,10 @@ func (u *UserInteractive) IsSingleStageFlow(authType string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInteractive) AddCompletedStage(sessionID, authType string) {
|
func (u *UserInteractive) AddCompletedStage(sessionID, authType string) {
|
||||||
u.Lock()
|
u.mutex.Lock()
|
||||||
// TODO: Handle multi-stage flows
|
// TODO: Handle multi-stage flows
|
||||||
delete(u.Sessions, sessionID)
|
delete(u.sessions, sessionID)
|
||||||
u.Unlock()
|
u.mutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
type Challenge struct {
|
type Challenge struct {
|
||||||
|
@ -157,10 +156,11 @@ type Challenge struct {
|
||||||
|
|
||||||
// Challenge returns an HTTP 401 with the supported flows for authenticating
|
// Challenge returns an HTTP 401 with the supported flows for authenticating
|
||||||
func (u *UserInteractive) challenge(sessionID string) *util.JSONResponse {
|
func (u *UserInteractive) challenge(sessionID string) *util.JSONResponse {
|
||||||
u.RLock()
|
u.mutex.RLock()
|
||||||
completed := u.Sessions[sessionID]
|
completed := u.sessions[sessionID]
|
||||||
flows := u.Flows
|
u.mutex.RUnlock()
|
||||||
u.RUnlock()
|
|
||||||
|
flows := u.flows
|
||||||
|
|
||||||
return &util.JSONResponse{
|
return &util.JSONResponse{
|
||||||
Code: 401,
|
Code: 401,
|
||||||
|
@ -183,9 +183,9 @@ func (u *UserInteractive) NewSession() *util.JSONResponse {
|
||||||
JSON: spec.InternalServerError{},
|
JSON: spec.InternalServerError{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
u.Lock()
|
u.mutex.Lock()
|
||||||
u.Sessions[sessionID] = []string{}
|
u.sessions[sessionID] = []string{}
|
||||||
u.Unlock()
|
u.mutex.Unlock()
|
||||||
return u.challenge(sessionID)
|
return u.challenge(sessionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,9 +233,7 @@ func (u *UserInteractive) Verify(ctx context.Context, bodyBytes []byte, device *
|
||||||
// extract the type so we know which login type to use
|
// extract the type so we know which login type to use
|
||||||
authType := gjson.GetBytes(bodyBytes, "auth.type").Str
|
authType := gjson.GetBytes(bodyBytes, "auth.type").Str
|
||||||
|
|
||||||
u.RLock()
|
loginType, ok := u.types[authType]
|
||||||
loginType, ok := u.Types[authType]
|
|
||||||
u.RUnlock()
|
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, &util.JSONResponse{
|
return nil, &util.JSONResponse{
|
||||||
|
@ -247,9 +245,9 @@ func (u *UserInteractive) Verify(ctx context.Context, bodyBytes []byte, device *
|
||||||
// retrieve the session
|
// retrieve the session
|
||||||
sessionID := gjson.GetBytes(bodyBytes, "auth.session").Str
|
sessionID := gjson.GetBytes(bodyBytes, "auth.session").Str
|
||||||
|
|
||||||
u.RLock()
|
u.mutex.RLock()
|
||||||
_, ok = u.Sessions[sessionID]
|
_, ok = u.sessions[sessionID]
|
||||||
u.RUnlock()
|
u.mutex.RUnlock()
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
// if the login type is part of a single stage flow then allow them to omit the session ID
|
// if the login type is part of a single stage flow then allow them to omit the session ID
|
||||||
|
|
Loading…
Reference in a new issue