github.com/qichengzx/mattermost-server@v4.5.1-0.20180604164826-2c75247c97d0+incompatible/web/saml.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package web 5 6 import ( 7 b64 "encoding/base64" 8 "net/http" 9 "strings" 10 11 "github.com/mattermost/mattermost-server/app" 12 "github.com/mattermost/mattermost-server/mlog" 13 "github.com/mattermost/mattermost-server/model" 14 ) 15 16 func (w *Web) InitSaml() { 17 w.MainRouter.Handle("/login/sso/saml", w.NewHandler(loginWithSaml)).Methods("GET") 18 w.MainRouter.Handle("/login/sso/saml", w.NewHandler(completeSaml)).Methods("POST") 19 } 20 21 func loginWithSaml(c *Context, w http.ResponseWriter, r *http.Request) { 22 samlInterface := c.App.Saml 23 24 if samlInterface == nil { 25 c.Err = model.NewAppError("loginWithSaml", "api.user.saml.not_available.app_error", nil, "", http.StatusFound) 26 return 27 } 28 29 teamId, err := c.App.GetTeamIdFromQuery(r.URL.Query()) 30 if err != nil { 31 c.Err = err 32 return 33 } 34 action := r.URL.Query().Get("action") 35 redirectTo := r.URL.Query().Get("redirect_to") 36 relayProps := map[string]string{} 37 relayState := "" 38 39 if len(action) != 0 { 40 relayProps["team_id"] = teamId 41 relayProps["action"] = action 42 if action == model.OAUTH_ACTION_EMAIL_TO_SSO { 43 relayProps["email"] = r.URL.Query().Get("email") 44 } 45 } 46 47 if len(redirectTo) != 0 { 48 relayProps["redirect_to"] = redirectTo 49 } 50 51 if len(relayProps) > 0 { 52 relayState = b64.StdEncoding.EncodeToString([]byte(model.MapToJson(relayProps))) 53 } 54 55 if data, err := samlInterface.BuildRequest(relayState); err != nil { 56 c.Err = err 57 return 58 } else { 59 w.Header().Set("Content-Type", "application/x-www-form-urlencoded") 60 http.Redirect(w, r, data.URL, http.StatusFound) 61 } 62 } 63 64 func completeSaml(c *Context, w http.ResponseWriter, r *http.Request) { 65 samlInterface := c.App.Saml 66 67 if samlInterface == nil { 68 c.Err = model.NewAppError("completeSaml", "api.user.saml.not_available.app_error", nil, "", http.StatusFound) 69 return 70 } 71 72 //Validate that the user is with SAML and all that 73 encodedXML := r.FormValue("SAMLResponse") 74 relayState := r.FormValue("RelayState") 75 76 relayProps := make(map[string]string) 77 if len(relayState) > 0 { 78 stateStr := "" 79 if b, err := b64.StdEncoding.DecodeString(relayState); err != nil { 80 c.Err = model.NewAppError("completeSaml", "api.user.authorize_oauth_user.invalid_state.app_error", nil, err.Error(), http.StatusFound) 81 return 82 } else { 83 stateStr = string(b) 84 } 85 relayProps = model.MapFromJson(strings.NewReader(stateStr)) 86 } 87 88 action := relayProps["action"] 89 if user, err := samlInterface.DoLogin(encodedXML, relayProps); err != nil { 90 if action == model.OAUTH_ACTION_MOBILE { 91 err.Translate(c.T) 92 w.Write([]byte(err.ToJson())) 93 } else { 94 c.Err = err 95 c.Err.StatusCode = http.StatusFound 96 } 97 return 98 } else { 99 if err := c.App.CheckUserAllAuthenticationCriteria(user, ""); err != nil { 100 c.Err = err 101 c.Err.StatusCode = http.StatusFound 102 return 103 } 104 105 switch action { 106 case model.OAUTH_ACTION_SIGNUP: 107 teamId := relayProps["team_id"] 108 if len(teamId) > 0 { 109 c.App.Go(func() { 110 if err := c.App.AddUserToTeamByTeamId(teamId, user); err != nil { 111 mlog.Error(err.Error()) 112 } else { 113 c.App.AddDirectChannels(teamId, user) 114 } 115 }) 116 } 117 case model.OAUTH_ACTION_EMAIL_TO_SSO: 118 if err := c.App.RevokeAllSessions(user.Id); err != nil { 119 c.Err = err 120 return 121 } 122 c.LogAuditWithUserId(user.Id, "Revoked all sessions for user") 123 c.App.Go(func() { 124 if err := c.App.SendSignInChangeEmail(user.Email, strings.Title(model.USER_AUTH_SERVICE_SAML)+" SSO", user.Locale, c.App.GetSiteURL()); err != nil { 125 mlog.Error(err.Error()) 126 } 127 }) 128 } 129 130 session, err := c.App.DoLogin(w, r, user, "") 131 if err != nil { 132 c.Err = err 133 return 134 } 135 136 c.Session = *session 137 138 if val, ok := relayProps["redirect_to"]; ok { 139 http.Redirect(w, r, c.GetSiteURLHeader()+val, http.StatusFound) 140 return 141 } 142 143 if action == model.OAUTH_ACTION_MOBILE { 144 ReturnStatusOK(w) 145 } else { 146 http.Redirect(w, r, app.GetProtocol(r)+"://"+r.Host, http.StatusFound) 147 } 148 } 149 }