-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multi Factor Authentication #22
Comments
Sorry for the delay @eyebank. @crspeller Do you know if |
You need to use |
@eyebank Would you be open to submitting a PR to fix this? |
where can I find this |
@eyebank |
@crspeller Looking at the link you provided. Where would I put the following code for the golang bot to be able to work using mfa? Thanks! // LoginWithMFA logs a user in with a MFA token
func (c *Client4) LoginWithMFA(loginId, password, mfaToken string) (*User, *Response) {
m := make(map[string]string)
m["login_id"] = loginId
m["password"] = password
m["token"] = mfaToken
return c.login(m)
}
func (c *Client4) login(m map[string]string) (*User, *Response) {
r, err := c.DoApiPost("/users/login", MapToJson(m))
if err != nil {
return nil, BuildErrorResponse(r, err)
}
defer closeBody(r)
c.AuthToken = r.Header.Get(HEADER_TOKEN)
c.AuthType = HEADER_BEARER
return UserFromJson(r.Body), BuildResponse(r)
} |
@EbsrVlee You replace the current login function with that one. https://github.com/mattermost/mattermost-bot-sample-golang/blob/master/bot_sample.go#L99 |
@crspeller Thank you! I've replaced my current login function with the one above. When I attempt to run my golang bot I get the errors What am I missing? Thank you again for all your help! |
@EbsrVlee Would you be open on sharing the code you currently have? |
Sure. (I have removed username/password/email from for obvious reasons) package main
import (
"os"
"os/signal"
"regexp"
"strings"
"time"
"github.com/mattermost/mattermost-server/model"
)
const (
SAMPLE_NAME = "**ChatBot**"
USER_EMAIL = "[email protected]"
USER_PASSWORD = "password"
USER_NAME = "Chatbot"
USER_FIRST = "Chatbot"
USER_LAST = "Chatbot"
TEAM_NAME = "aibot"
CHANNEL_LOG_NAME = "chat"
)
var client *model.Client4
var webSocketClient *model.WebSocketClient
var botUser *model.User
var botTeam *model.Team
var debuggingChannel *model.Channel
// Documentation for the Go driver can be found
// at https://godoc.org/github.com/mattermost/platform/model#Client
func main() {
println(SAMPLE_NAME)
SetupGracefulShutdown()
client = model.NewAPIv4Client("http://localhost:8065")
// Lets test to see if the mattermost server is up and running
MakeSureServerIsRunning()
// lets attempt to login to the Mattermost server as the bot user
// This will set the token required for all future calls
// You can get this token with client.AuthToken
LoginAsTheBotUser()
// If the bot user doesn't have the correct information lets update his profile
UpdateTheBotUserIfNeeded()
// Lets find our bot team
FindBotTeam()
// This is an important step. Lets make sure we use the botTeam
// for all future web service requests that require a team.
//client.SetTeamId(botTeam.Id)
// Lets create a bot channel for logging debug messages into
CreateBotDebuggingChannelIfNeeded()
SendMsgToDebuggingChannel("_"+SAMPLE_NAME+" has **started** running_", "")
// Lets start listening to some channels via the websocket!
webSocketClient, err := model.NewWebSocketClient4("ws://localhost:8065", client.AuthToken)
if err != nil {
println("We failed to connect to the web socket")
PrintError(err)
}
webSocketClient.Listen()
go func() {
for {
select {
case resp := <-webSocketClient.EventChannel:
HandleWebSocketResponse(resp)
}
}
}()
// You can block forever with
select {}
}
func MakeSureServerIsRunning() {
if props, resp := client.GetOldClientConfig(""); resp.Error != nil {
println("There was a problem pinging the Mattermost server. Are you sure it's running?")
PrintError(resp.Error)
os.Exit(1)
} else {
println("Server detected and is running version " + props["Version"])
}
}
// LoginWithMFA logs a user in with a MFA token
func (c *Client4) LoginWithMFA(loginId, password, mfaToken string) (*User, *Response) {
m := make(map[string]string)
m["login_id"] = Chatbot
m["password"] = password
m["token"] = 123456
return c.login(m)
}
func (c *Client4) login(m map[string]string) (*User, *Response) {
r, err := c.DoApiPost("/users/login", MapToJson(m))
if err != nil {
return nil, BuildErrorResponse(r, err)
}
defer closeBody(r)
c.AuthToken = r.Header.Get(HEADER_TOKEN)
c.AuthType = HEADER_BEARER
return UserFromJson(r.Body), BuildResponse(r)
}
//func LoginAsTheBotUser() {
// if user, resp := client.Login(USER_EMAIL, USER_PASSWORD); resp.Error != nil {
// println("There was a problem logging into the Mattermost server. Are you sure ran the setup steps from the README.md?")
// PrintError(resp.Error)
// os.Exit(1)
// } else {
// botUser = user
// }
//}
func UpdateTheBotUserIfNeeded() {
if botUser.FirstName != USER_FIRST || botUser.LastName != USER_LAST || botUser.Username != USER_NAME {
botUser.FirstName = USER_FIRST
botUser.LastName = USER_LAST
botUser.Username = USER_NAME
if user, resp := client.UpdateUser(botUser); resp.Error != nil {
println("We failed to update the Sample Bot user")
PrintError(resp.Error)
os.Exit(1)
} else {
botUser = user
println("Looks like this might be the first run so we've updated the bots account settings")
}
}
}
func FindBotTeam() {
if team, resp := client.GetTeamByName(TEAM_NAME, ""); resp.Error != nil {
println("We failed to get the initial load")
println("or we do not appear to be a member of the team '" + TEAM_NAME + "'")
PrintError(resp.Error)
os.Exit(1)
} else {
botTeam = team
}
}
func CreateBotDebuggingChannelIfNeeded() {
if rchannel, resp := client.GetChannelByName(CHANNEL_LOG_NAME, botTeam.Id, ""); resp.Error != nil {
println("We failed to get the channels")
PrintError(resp.Error)
} else {
debuggingChannel = rchannel
return
}
// Looks like we need to create the logging channel
channel := &model.Channel{}
channel.Name = CHANNEL_LOG_NAME
channel.DisplayName = "Town"
channel.Purpose = "This is used as a test channel for logging bot debug messages"
channel.Type = model.CHANNEL_OPEN
channel.TeamId = botTeam.Id
if rchannel, resp := client.CreateChannel(channel); resp.Error != nil {
println("We failed to create the channel " + CHANNEL_LOG_NAME)
PrintError(resp.Error)
} else {
debuggingChannel = rchannel
println("Looks like this might be the first run so we've created the channel " + CHANNEL_LOG_NAME)
}
}
func SendMsgToDebuggingChannel(msg string, replyToId string) {
post := &model.Post{}
post.ChannelId = debuggingChannel.Id
post.Message = msg
post.RootId = replyToId
if _, resp := client.CreatePost(post); resp.Error != nil {
println("We failed to send a message to the logging channel")
PrintError(resp.Error)
}
}
func HandleWebSocketResponse(event *model.WebSocketEvent) {
HandleMsgFromDebuggingChannel(event)
}
func HandleMsgFromDebuggingChannel(event *model.WebSocketEvent) {
// If this isn't the debugging channel then lets ingore it
if event.Broadcast.ChannelId != debuggingChannel.Id {
return
}
// Lets only reponded to messaged posted events
if event.Event != model.WEBSOCKET_EVENT_POSTED {
return
}
println("responding to debugging channel msg")
post := model.PostFromJson(strings.NewReader(event.Data["post"].(string)))
if post != nil {
// ignore my events
if post.UserId == botUser.Id {
return
}
// if you see any word matching 'alive' then respond
if matched, _ := regexp.MatchString(`(?:^|\W)alive(?:$|\W)`, post.Message); matched {
SendMsgToDebuggingChannel("Yes I'm running", post.Id)
return
}
// if you see any word matching 'up' then respond
if matched, _ := regexp.MatchString(`(?:^|\W)up(?:$|\W)`, post.Message); matched {
SendMsgToDebuggingChannel("Yes I'm running", post.Id)
return
}
// if you see any word matching 'running' then respond
if matched, _ := regexp.MatchString(`(?:^|\W)running(?:$|\W)`, post.Message); matched {
SendMsgToDebuggingChannel("Yes I'm running", post.Id)
return
}
// if you see any word matching 'hello' then respond
if matched, _ := regexp.MatchString(`(?:^|\W)hello(?:$|\W)`, post.Message); matched {
SendMsgToDebuggingChannel("Hi! How are you? :smile:", post.Id)
return
}
}
SendMsgToDebuggingChannel("I did not understand you! Please try the help command.", post.Id)
}
func PrintError(err *model.AppError) {
println("\tError Details:")
println("\t\t" + err.Message)
println("\t\t" + err.Id)
println("\t\t" + err.DetailedError)
}
func SetupGracefulShutdown() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for _ = range c {
if webSocketClient != nil {
webSocketClient.Close()
}
SendMsgToDebuggingChannel("_"+SAMPLE_NAME+" has **stopped** running_", "")
os.Exit(0)
}
}()
} |
Hey @EbsrVlee, You have to explicitly select the packages you want to use. E.g. if you want to use the struct |
Hi @hanzei , thank you for the advice. I'm fairly new to golang. Could you give me an example of how to select it from model.user? Thank you again. |
I would advice to read and play through "A Tour of Go" first. This is a tutorial made by the Go team targeting new gophers. |
Server 5.6.0.
Attempting to run golang after configuring google MFA. Startup fails. Any thoughts,
The text was updated successfully, but these errors were encountered: