diff --git a/openapi/response/response.go b/openapi/response/response.go index 0c25c84b..3c8643c0 100644 --- a/openapi/response/response.go +++ b/openapi/response/response.go @@ -112,6 +112,7 @@ var ( ErrInvalidClientMetadata = &ErrorResponse{Code: "invalid_client_metadata", ErrorDescription: "The client metadata is invalid or contains unsupported values."} ErrInvalidSoftwareStatement = &ErrorResponse{Code: "invalid_software_statement", ErrorDescription: "The software statement is invalid or cannot be verified."} ErrUnapprovedSoftware = &ErrorResponse{Code: "unapproved_software", ErrorDescription: "The software statement represents software that has been replaced or is otherwise invalid."} + ErrMFARequired = &ErrorResponse{Code: "mfa_required", ErrorDescription: "Multi-factor authentication is required to access this resource."} // Configuration and service errors ErrInvalidConfiguration = types.ErrInvalidConfiguration diff --git a/openapi/user/login.go b/openapi/user/login.go index 69f3d4c5..29ac5d46 100644 --- a/openapi/user/login.go +++ b/openapi/user/login.go @@ -135,6 +135,16 @@ func LoginThirdParty(providerID string, userinfo *oauthtypes.OIDCUserInfo, ip st return nil, err } + // If MFA Enabled, should return MFA required response + mfaEnabled, err := userProvider.IsMFAEnabled(ctx, userID) + if err != nil { + return nil, err + } + + if mfaEnabled { + return nil, response.ErrMFARequired + } + return LoginByUserID(userID, ip) } @@ -197,6 +207,8 @@ func LoginByUserID(userid string, ip string) (*LoginResponse, error) { mfaEnabled := toBool(user["mfa_enabled"]) return &LoginResponse{ + UserID: userid, + Subject: subject, AccessToken: accessToken, IDToken: oidcToken, RefreshToken: refreshToken, diff --git a/openapi/user/oauth.go b/openapi/user/oauth.go index 47475847..1568a9c6 100644 --- a/openapi/user/oauth.go +++ b/openapi/user/oauth.go @@ -176,6 +176,14 @@ func authback(c *gin.Context) { // LoginThirdParty(providerID, userInfo) loginResponse, err := LoginThirdParty(providerID, userInfo, userIPAddress(c)) if err != nil { + + // Redirect to MFA required page + if err == response.ErrMFARequired { + response.RespondWithError(c, response.StatusUnauthorized, response.ErrMFARequired) + return + } + + // Other errors errorResp := &response.ErrorResponse{ Code: response.ErrInvalidRequest.Code, ErrorDescription: "Failed to login: " + err.Error(), diff --git a/openapi/user/types.go b/openapi/user/types.go index bdc57abb..f9890952 100644 --- a/openapi/user/types.go +++ b/openapi/user/types.go @@ -163,6 +163,8 @@ type OIDCAddress = oauthtypes.OIDCAddress // LoginResponse represents the response for login type LoginResponse struct { + UserID string `json:"user_id,omitempty"` + Subject string `json:"subject,omitempty"` AccessToken string `json:"access_token"` IDToken string `json:"id_token,omitempty"` RefreshToken string `json:"refresh_token,omitempty"` diff --git a/openapi/user/user.go b/openapi/user/user.go index 2342bfc8..4440f3ac 100644 --- a/openapi/user/user.go +++ b/openapi/user/user.go @@ -264,22 +264,6 @@ func attachThirdParty(group *gin.RouterGroup, oauth types.OAuth) { } -// getTeamConfig returns the team configuration -func getTeamConfig(c *gin.Context) { - locale := c.Query("locale") - if locale == "" { - locale = "en" // default locale - } - - config := GetTeamConfig(locale) - if config == nil { - c.JSON(http.StatusNotFound, gin.H{"error": "Team configuration not found"}) - return - } - - c.JSON(http.StatusOK, config) -} - func placeholder(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"message": "Hello, World!"}) }