@@ -65,6 +65,7 @@ func (api *API) postConvertLoginType(rw http.ResponseWriter, r *http.Request) {
65
65
66
66
switch req .ToLoginType {
67
67
case codersdk .LoginTypeGithub , codersdk .LoginTypeOIDC :
68
+ // Allowed!
68
69
case codersdk .LoginTypeNone , codersdk .LoginTypePassword , codersdk .LoginTypeToken :
69
70
// These login types are not allowed to be converted to at this time.
70
71
httpapi .Write (ctx , rw , http .StatusBadRequest , codersdk.Response {
@@ -78,6 +79,7 @@ func (api *API) postConvertLoginType(rw http.ResponseWriter, r *http.Request) {
78
79
return
79
80
}
80
81
82
+ // This handles the email/pass checking.
81
83
user , _ , ok := api .loginRequest (ctx , rw , req .LoginWithPasswordRequest )
82
84
if ! ok {
83
85
return
@@ -116,11 +118,12 @@ func (api *API) postConvertLoginType(rw http.ResponseWriter, r *http.Request) {
116
118
}
117
119
118
120
mergeState , err = store .InsertUserOauthMergeState (ctx , database.InsertUserOauthMergeStateParams {
119
- UserID : user .ID ,
120
- StateString : stateString ,
121
- ToLoginType : database .LoginType (req .ToLoginType ),
122
- CreatedAt : now ,
123
- ExpiresAt : now .Add (time .Minute * 5 ),
121
+ UserID : user .ID ,
122
+ StateString : stateString ,
123
+ FromLoginType : user .LoginType ,
124
+ ToLoginType : database .LoginType (req .ToLoginType ),
125
+ CreatedAt : now ,
126
+ ExpiresAt : now .Add (time .Minute * 5 ),
124
127
})
125
128
if err != nil {
126
129
return err
@@ -175,7 +178,8 @@ func (api *API) postLogin(rw http.ResponseWriter, r *http.Request) {
175
178
}
176
179
177
180
user , roles , ok := api .loginRequest (ctx , rw , loginWithPassword )
178
- // 'user.ID' will be empty, or will be an actual value.
181
+ // 'user.ID' will be empty, or will be an actual value. Either is correct
182
+ // here.
179
183
aReq .UserID = user .ID
180
184
if ! ok {
181
185
// user failed to login
@@ -1030,9 +1034,13 @@ func (api *API) oauthLogin(r *http.Request, params oauthLoginParams) (*http.Cook
1030
1034
user .LoginType ,
1031
1035
),
1032
1036
}
1037
+ // If we do not allow converting to oauth, return an error.
1033
1038
if ! params .OauthConversionEnabled {
1034
1039
return wrongLoginTypeErr
1035
1040
}
1041
+
1042
+ // At this point, this request could be an attempt to convert from
1043
+ // password auth to oauth auth.
1036
1044
var (
1037
1045
auditor = * api .Auditor .Load ()
1038
1046
oauthConvertAudit , commitOauthConvertAudit = params .InitAuditRequest (& audit.RequestParams {
@@ -1052,7 +1060,6 @@ func (api *API) oauthLogin(r *http.Request, params oauthLoginParams) (*http.Cook
1052
1060
if xerrors .Is (err , sql .ErrNoRows ) {
1053
1061
return wrongLoginTypeErr
1054
1062
}
1055
- oauthConvertAudit .Old = mergeState
1056
1063
1057
1064
failedMsg := fmt .Sprintf ("Request to convert login type from %s to %s failed" , user .LoginType , params .LoginType )
1058
1065
if err != nil {
@@ -1061,8 +1068,11 @@ func (api *API) oauthLogin(r *http.Request, params oauthLoginParams) (*http.Cook
1061
1068
msg : failedMsg ,
1062
1069
}
1063
1070
}
1064
- if user .ID != mergeState .UserID {
1065
- // User tried to use someone else's merge state?
1071
+ oauthConvertAudit .Old = mergeState
1072
+ // Make sure the merge state generated matches this OIDC login request.
1073
+ // It needs to have the correct login type information for this
1074
+ // user.
1075
+ if user .ID != mergeState .UserID || user .LoginType != mergeState .FromLoginType || params .LoginType != mergeState .ToLoginType {
1066
1076
return httpError {
1067
1077
code : http .StatusForbidden ,
1068
1078
msg : failedMsg ,
0 commit comments