func (as SqlOAuthStore) SaveApp(app *model.OAuthApp) StoreChannel { storeChannel := make(StoreChannel) go func() { result := StoreResult{} if len(app.Id) > 0 { result.Err = model.NewLocAppError("SqlOAuthStore.SaveApp", "store.sql_oauth.save_app.existing.app_error", nil, "app_id="+app.Id) storeChannel <- result close(storeChannel) return } app.PreSave() if result.Err = app.IsValid(); result.Err != nil { storeChannel <- result close(storeChannel) return } if err := as.GetMaster().Insert(app); err != nil { result.Err = model.NewLocAppError("SqlOAuthStore.SaveApp", "store.sql_oauth.save_app.save.app_error", nil, "app_id="+app.Id+", "+err.Error()) } else { result.Data = app } storeChannel <- result close(storeChannel) }() return storeChannel }
func TestOAuthGetAuthorizedApps(t *testing.T) { Setup() a1 := model.OAuthApp{} a1.CreatorId = model.NewId() a1.Name = "TestApp" + model.NewId() a1.CallbackUrls = []string{"https://nowhere.com"} a1.Homepage = "https://nowhere.com" Must(store.OAuth().SaveApp(&a1)) // allow the app p := model.Preference{} p.UserId = a1.CreatorId p.Category = model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP p.Name = a1.Id p.Value = "true" Must(store.Preference().Save(&model.Preferences{p})) if result := <-store.OAuth().GetAuthorizedApps(a1.CreatorId); result.Err != nil { t.Fatal(result.Err) } else { apps := result.Data.([]*model.OAuthApp) if len(apps) == 0 { t.Fatal("It should have return apps") } } }
func (as SqlOAuthStore) SaveApp(app *model.OAuthApp) StoreChannel { storeChannel := make(StoreChannel) go func() { result := StoreResult{} if len(app.Id) > 0 { result.Err = model.NewAppError("SqlOAuthStore.SaveApp", "Must call update for exisiting app", "app_id="+app.Id) storeChannel <- result close(storeChannel) return } app.PreSave() if result.Err = app.IsValid(); result.Err != nil { storeChannel <- result close(storeChannel) return } if err := as.GetMaster().Insert(app); err != nil { result.Err = model.NewAppError("SqlOAuthStore.SaveApp", "We couldn't save the app.", "app_id="+app.Id+", "+err.Error()) } else { result.Data = app } storeChannel <- result close(storeChannel) }() return storeChannel }
func TestOAuthStoreUpdateApp(t *testing.T) { Setup() a1 := model.OAuthApp{} a1.CreatorId = model.NewId() a1.Name = "TestApp" + model.NewId() a1.CallbackUrls = []string{"https://nowhere.com"} a1.Homepage = "https://nowhere.com" Must(store.OAuth().SaveApp(&a1)) a1.CreateAt = 1 a1.ClientSecret = "pwd" a1.CreatorId = "12345678901234567890123456" a1.Name = "NewName" if result := <-store.OAuth().UpdateApp(&a1); result.Err != nil { t.Fatal(result.Err) } else { ua1 := (result.Data.([2]*model.OAuthApp)[0]) if ua1.Name != "NewName" { t.Fatal("name did not update") } if ua1.CreateAt == 1 { t.Fatal("create at should not have updated") } if ua1.CreatorId == "12345678901234567890123456" { t.Fatal("creator id should not have updated") } } }
func TestOAuthStoreDeleteApp(t *testing.T) { a1 := model.OAuthApp{} a1.CreatorId = model.NewId() a1.Name = "TestApp" + model.NewId() a1.CallbackUrls = []string{"https://nowhere.com"} a1.Homepage = "https://nowhere.com" Must(store.OAuth().SaveApp(&a1)) if err := (<-store.OAuth().DeleteApp(a1.Id)).Err; err != nil { t.Fatal(err) } }
func regenerateOAuthSecret(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider { c.Err = model.NewLocAppError("registerOAuthApp", "api.oauth.register_oauth_app.turn_off.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } isSystemAdmin := c.IsSystemAdmin() if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations { if !isSystemAdmin { c.Err = model.NewLocAppError("registerOAuthApp", "api.command.admin_only.app_error", nil, "") c.Err.StatusCode = http.StatusForbidden return } } params := mux.Vars(r) id := params["id"] if len(id) == 0 { c.SetInvalidParam("regenerateOAuthSecret", "id") return } var app *model.OAuthApp if result := <-Srv.Store.OAuth().GetApp(id); result.Err != nil { c.Err = model.NewLocAppError("regenerateOAuthSecret", "api.oauth.allow_oauth.database.app_error", nil, "") return } else { app = result.Data.(*model.OAuthApp) //validate that is a System Admin or the same user that registered the app if !isSystemAdmin && app.CreatorId != c.Session.UserId { c.Err = model.NewLocAppError("regenerateOAuthSecret", "api.oauth.regenerate_secret.app_error", nil, "") return } app.ClientSecret = model.NewId() if update := <-Srv.Store.OAuth().UpdateApp(app); update.Err != nil { c.Err = update.Err return } w.Write([]byte(app.ToJson())) return } }
func TestOAuthGetAccessDataByUserForApp(t *testing.T) { Setup() a1 := model.OAuthApp{} a1.CreatorId = model.NewId() a1.Name = "TestApp" + model.NewId() a1.CallbackUrls = []string{"https://nowhere.com"} a1.Homepage = "https://nowhere.com" Must(store.OAuth().SaveApp(&a1)) // allow the app p := model.Preference{} p.UserId = a1.CreatorId p.Category = model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP p.Name = a1.Id p.Value = "true" Must(store.Preference().Save(&model.Preferences{p})) if result := <-store.OAuth().GetAuthorizedApps(a1.CreatorId); result.Err != nil { t.Fatal(result.Err) } else { apps := result.Data.([]*model.OAuthApp) if len(apps) == 0 { t.Fatal("It should have return apps") } } // save the token ad1 := model.AccessData{} ad1.ClientId = a1.Id ad1.UserId = a1.CreatorId ad1.Token = model.NewId() ad1.RefreshToken = model.NewId() if err := (<-store.OAuth().SaveAccessData(&ad1)).Err; err != nil { t.Fatal(err) } if result := <-store.OAuth().GetAccessDataByUserForApp(a1.CreatorId, a1.Id); result.Err != nil { t.Fatal(result.Err) } else { accessData := result.Data.([]*model.AccessData) if len(accessData) == 0 { t.Fatal("It should have return access data") } } }
func getOAuthAppInfo(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider { c.Err = model.NewLocAppError("getOAuthAppInfo", "api.oauth.allow_oauth.turn_off.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } params := mux.Vars(r) clientId := params["client_id"] var app *model.OAuthApp if result := <-Srv.Store.OAuth().GetApp(clientId); result.Err != nil { c.Err = model.NewLocAppError("getOAuthAppInfo", "api.oauth.allow_oauth.database.app_error", nil, "") return } else { app = result.Data.(*model.OAuthApp) } app.Sanitize() w.Write([]byte(app.ToJson())) }
func regenerateOAuthSecret(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider { c.Err = model.NewLocAppError("registerOAuthApp", "api.oauth.register_oauth_app.turn_off.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } params := mux.Vars(r) id := params["id"] if len(id) == 0 { c.SetInvalidParam("regenerateOAuthSecret", "id") return } var app *model.OAuthApp if result := <-Srv.Store.OAuth().GetApp(id); result.Err != nil { c.Err = model.NewLocAppError("regenerateOAuthSecret", "api.oauth.allow_oauth.database.app_error", nil, "") return } else { app = result.Data.(*model.OAuthApp) if app.CreatorId != c.Session.UserId && !HasPermissionToContext(c, model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) { c.Err = model.NewLocAppError("registerOAuthApp", "api.command.admin_only.app_error", nil, "") c.Err.StatusCode = http.StatusForbidden return } app.ClientSecret = model.NewId() if update := <-Srv.Store.OAuth().UpdateApp(app); update.Err != nil { c.Err = update.Err return } w.Write([]byte(app.ToJson())) return } }
func (as SqlOAuthStore) UpdateApp(app *model.OAuthApp) StoreChannel { storeChannel := make(StoreChannel) go func() { result := StoreResult{} app.PreUpdate() if result.Err = app.IsValid(); result.Err != nil { storeChannel <- result close(storeChannel) return } if oldAppResult, err := as.GetMaster().Get(model.OAuthApp{}, app.Id); err != nil { result.Err = model.NewLocAppError("SqlOAuthStore.UpdateApp", "store.sql_oauth.update_app.finding.app_error", nil, "app_id="+app.Id+", "+err.Error()) } else if oldAppResult == nil { result.Err = model.NewLocAppError("SqlOAuthStore.UpdateApp", "store.sql_oauth.update_app.find.app_error", nil, "app_id="+app.Id) } else { oldApp := oldAppResult.(*model.OAuthApp) app.CreateAt = oldApp.CreateAt app.ClientSecret = oldApp.ClientSecret app.CreatorId = oldApp.CreatorId if count, err := as.GetMaster().Update(app); err != nil { result.Err = model.NewLocAppError("SqlOAuthStore.UpdateApp", "store.sql_oauth.update_app.updating.app_error", nil, "app_id="+app.Id+", "+err.Error()) } else if count != 1 { result.Err = model.NewLocAppError("SqlOAuthStore.UpdateApp", "store.sql_oauth.update_app.update.app_error", nil, "app_id="+app.Id) } else { result.Data = [2]*model.OAuthApp{app, oldApp} } } storeChannel <- result close(storeChannel) }() return storeChannel }
func (as SqlOAuthStore) UpdateApp(app *model.OAuthApp) StoreChannel { storeChannel := make(StoreChannel) go func() { result := StoreResult{} app.PreUpdate() if result.Err = app.IsValid(); result.Err != nil { storeChannel <- result close(storeChannel) return } if oldAppResult, err := as.GetMaster().Get(model.OAuthApp{}, app.Id); err != nil { result.Err = model.NewAppError("SqlOAuthStore.UpdateApp", "We encountered an error finding the app", "app_id="+app.Id+", "+err.Error()) } else if oldAppResult == nil { result.Err = model.NewAppError("SqlOAuthStore.UpdateApp", "We couldn't find the existing app to update", "app_id="+app.Id) } else { oldApp := oldAppResult.(*model.OAuthApp) app.CreateAt = oldApp.CreateAt app.ClientSecret = oldApp.ClientSecret app.CreatorId = oldApp.CreatorId if count, err := as.GetMaster().Update(app); err != nil { result.Err = model.NewAppError("SqlOAuthStore.UpdateApp", "We encountered an error updating the app", "app_id="+app.Id+", "+err.Error()) } else if count != 1 { result.Err = model.NewAppError("SqlOAuthStore.UpdateApp", "We couldn't update the app", "app_id="+app.Id) } else { result.Data = [2]*model.OAuthApp{app, oldApp} } } storeChannel <- result close(storeChannel) }() return storeChannel }
func allowOAuth(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider { c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.turn_off.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } c.LogAudit("attempt") responseData := map[string]string{} responseType := r.URL.Query().Get("response_type") if len(responseType) == 0 { c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.bad_response.app_error", nil, "") c.Err.StatusCode = http.StatusBadRequest return } clientId := r.URL.Query().Get("client_id") if len(clientId) != 26 { c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.bad_client.app_error", nil, "") c.Err.StatusCode = http.StatusBadRequest return } redirectUri := r.URL.Query().Get("redirect_uri") if len(redirectUri) == 0 { c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.bad_redirect.app_error", nil, "") c.Err.StatusCode = http.StatusBadRequest return } scope := r.URL.Query().Get("scope") state := r.URL.Query().Get("state") if len(scope) == 0 { scope = model.DEFAULT_SCOPE } var app *model.OAuthApp if result := <-Srv.Store.OAuth().GetApp(clientId); result.Err != nil { c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.database.app_error", nil, "") return } else { app = result.Data.(*model.OAuthApp) } if !app.IsValidRedirectURL(redirectUri) { c.LogAudit("fail - redirect_uri did not match registered callback") c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.redirect_callback.app_error", nil, "") c.Err.StatusCode = http.StatusBadRequest return } if responseType != model.AUTHCODE_RESPONSE_TYPE { responseData["redirect"] = redirectUri + "?error=unsupported_response_type&state=" + state w.Write([]byte(model.MapToJson(responseData))) return } authData := &model.AuthData{UserId: c.Session.UserId, ClientId: clientId, CreateAt: model.GetMillis(), RedirectUri: redirectUri, State: state, Scope: scope} authData.Code = model.HashPassword(fmt.Sprintf("%v:%v:%v:%v", clientId, redirectUri, authData.CreateAt, c.Session.UserId)) // this saves the OAuth2 app as authorized authorizedApp := model.Preference{ UserId: c.Session.UserId, Category: model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP, Name: clientId, Value: scope, } if result := <-Srv.Store.Preference().Save(&model.Preferences{authorizedApp}); result.Err != nil { responseData["redirect"] = redirectUri + "?error=server_error&state=" + state w.Write([]byte(model.MapToJson(responseData))) return } if result := <-Srv.Store.OAuth().SaveAuthData(authData); result.Err != nil { responseData["redirect"] = redirectUri + "?error=server_error&state=" + state w.Write([]byte(model.MapToJson(responseData))) return } c.LogAudit("success") responseData["redirect"] = redirectUri + "?code=" + url.QueryEscape(authData.Code) + "&state=" + url.QueryEscape(authData.State) w.Write([]byte(model.MapToJson(responseData))) }
func allowOAuth(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider { c.Err = model.NewAppError("allowOAuth", "The system admin has turned off OAuth service providing.", "") c.Err.StatusCode = http.StatusNotImplemented return } c.LogAudit("attempt") w.Header().Set("Content-Type", "application/x-www-form-urlencoded") responseData := map[string]string{} responseType := r.URL.Query().Get("response_type") if len(responseType) == 0 { c.Err = model.NewAppError("allowOAuth", "invalid_request: Bad response_type", "") return } clientId := r.URL.Query().Get("client_id") if len(clientId) != 26 { c.Err = model.NewAppError("allowOAuth", "invalid_request: Bad client_id", "") return } redirectUri := r.URL.Query().Get("redirect_uri") if len(redirectUri) == 0 { c.Err = model.NewAppError("allowOAuth", "invalid_request: Missing or bad redirect_uri", "") return } scope := r.URL.Query().Get("scope") state := r.URL.Query().Get("state") var app *model.OAuthApp if result := <-Srv.Store.OAuth().GetApp(clientId); result.Err != nil { c.Err = model.NewAppError("allowOAuth", "server_error: Error accessing the database", "") return } else { app = result.Data.(*model.OAuthApp) } if !app.IsValidRedirectURL(redirectUri) { c.LogAudit("fail - redirect_uri did not match registered callback") c.Err = model.NewAppError("allowOAuth", "invalid_request: Supplied redirect_uri did not match registered callback_url", "") return } if responseType != model.AUTHCODE_RESPONSE_TYPE { responseData["redirect"] = redirectUri + "?error=unsupported_response_type&state=" + state w.Write([]byte(model.MapToJson(responseData))) return } authData := &model.AuthData{UserId: c.Session.UserId, ClientId: clientId, CreateAt: model.GetMillis(), RedirectUri: redirectUri, State: state, Scope: scope} authData.Code = model.HashPassword(fmt.Sprintf("%v:%v:%v:%v", clientId, redirectUri, authData.CreateAt, c.Session.UserId)) if result := <-Srv.Store.OAuth().SaveAuthData(authData); result.Err != nil { responseData["redirect"] = redirectUri + "?error=server_error&state=" + state w.Write([]byte(model.MapToJson(responseData))) return } c.LogAudit("success") responseData["redirect"] = redirectUri + "?code=" + url.QueryEscape(authData.Code) + "&state=" + url.QueryEscape(authData.State) w.Write([]byte(model.MapToJson(responseData))) }