convertUserToOauth will convert a user from password base loginType to an oauth login type. If it fails, it will return a httpError
(ctx context.Context, r *http.Request, db database.Store, params *oauthLoginParams)
| 2062 | // convertUserToOauth will convert a user from password base loginType to |
| 2063 | // an oauth login type. If it fails, it will return a httpError |
| 2064 | func (api *API) convertUserToOauth(ctx context.Context, r *http.Request, db database.Store, params *oauthLoginParams) (database.User, error) { |
| 2065 | user := params.User |
| 2066 | |
| 2067 | // Trying to convert to OIDC, but the email does not match. |
| 2068 | // So do not make a new user, just block the request. |
| 2069 | if user.ID == uuid.Nil { |
| 2070 | return database.User{}, idpsync.HTTPError{ |
| 2071 | Code: http.StatusBadRequest, |
| 2072 | Msg: fmt.Sprintf("The oidc account with the email %q does not match the email of the account you are trying to convert. Contact your administrator to resolve this issue.", params.Email), |
| 2073 | } |
| 2074 | } |
| 2075 | |
| 2076 | jwtCookie, err := r.Cookie(OAuthConvertCookieValue) |
| 2077 | if err != nil { |
| 2078 | return database.User{}, idpsync.HTTPError{ |
| 2079 | Code: http.StatusBadRequest, |
| 2080 | Msg: fmt.Sprintf("Convert to oauth cookie not found. Missing signed jwt to authorize this action. " + |
| 2081 | "Please try again."), |
| 2082 | } |
| 2083 | } |
| 2084 | var claims OAuthConvertStateClaims |
| 2085 | |
| 2086 | err = jwtutils.Verify(ctx, api.OIDCConvertKeyCache, jwtCookie.Value, &claims) |
| 2087 | if xerrors.Is(err, cryptokeys.ErrKeyNotFound) || xerrors.Is(err, cryptokeys.ErrKeyInvalid) || xerrors.Is(err, jose.ErrCryptoFailure) || xerrors.Is(err, jwtutils.ErrMissingKeyID) { |
| 2088 | // These errors are probably because the user is mixing 2 coder deployments. |
| 2089 | return database.User{}, idpsync.HTTPError{ |
| 2090 | Code: http.StatusBadRequest, |
| 2091 | Msg: "Using an invalid jwt to authorize this action. Ensure there is only 1 coder deployment and try again.", |
| 2092 | } |
| 2093 | } |
| 2094 | if err != nil { |
| 2095 | return database.User{}, idpsync.HTTPError{ |
| 2096 | Code: http.StatusInternalServerError, |
| 2097 | Msg: fmt.Sprintf("Error parsing jwt: %v", err), |
| 2098 | } |
| 2099 | } |
| 2100 | |
| 2101 | // At this point, this request could be an attempt to convert from |
| 2102 | // password auth to oauth auth. Always log these attempts. |
| 2103 | var ( |
| 2104 | auditor = *api.Auditor.Load() |
| 2105 | oauthConvertAudit = params.initAuditRequest(&audit.RequestParams{ |
| 2106 | Audit: auditor, |
| 2107 | Log: api.Logger, |
| 2108 | Request: r, |
| 2109 | Action: database.AuditActionWrite, |
| 2110 | }) |
| 2111 | ) |
| 2112 | |
| 2113 | oauthConvertAudit.UserID = claims.UserID |
| 2114 | oauthConvertAudit.Old = user |
| 2115 | |
| 2116 | if claims.Issuer != api.DeploymentID { |
| 2117 | return database.User{}, idpsync.HTTPError{ |
| 2118 | Code: http.StatusForbidden, |
| 2119 | Msg: "Request to convert login type failed. Issuer mismatch. Found a cookie from another coder deployment, please try again.", |
| 2120 | } |
| 2121 | } |
no test coverage detected