Skip to content

Commit

Permalink
docs: example using multiple authentication methods
Browse files Browse the repository at this point in the history
Users may prefer one authentication
(`-o PreferredAuthentications=password` for example), or the user might
not have a public key, or anything else.

This example will try 3 auth methods, usually the order is: public-key,
keyboard-interactive, password.

Closes #225

Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
  • Loading branch information
caarlos0 committed Jan 16, 2024
1 parent d47ec1a commit 91171be
Showing 1 changed file with 77 additions and 0 deletions.
77 changes: 77 additions & 0 deletions examples/multi-auth/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package main

import (
"context"
"errors"
"fmt"
"os"
"os/signal"
"syscall"
"time"

"github.com/charmbracelet/log"
"github.com/charmbracelet/ssh"
"github.com/charmbracelet/wish"
"github.com/charmbracelet/wish/logging"
gossh "golang.org/x/crypto/ssh"
)

const (
host = "localhost"
port = 23234
carlosPubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILxWe2rXKoiO6W14LYPVfJKzRfJ1f3Jhzxrgjc/D4tU7"
validPassword = "asd123"
)

func main() {
s, err := wish.NewServer(
wish.WithAddress(fmt.Sprintf("%s:%d", host, port)),
wish.WithHostKeyPath(".ssh/term_info_ed25519"),
wish.WithPublicKeyAuth(func(_ ssh.Context, key ssh.PublicKey) bool {
log.Info("public-key")
carlos, _, _, _, _ := ssh.ParseAuthorizedKey([]byte(carlosPubkey))
return ssh.KeysEqual(carlos, key)
}),
wish.WithPasswordAuth(func(_ ssh.Context, password string) bool {
log.Info("password")
return password == validPassword
}),
wish.WithKeyboardInteractiveAuth(func(_ ssh.Context, challenger gossh.KeyboardInteractiveChallenge) bool {
log.Info("keyboard-interactive")
answers, err := challenger("", "", []string{"how much is 2+3: "}, []bool{true})
if err != nil {
return false
}
return len(answers) == 1 && answers[0] == "5"
}),
wish.WithMiddleware(
logging.Middleware(),
func(h ssh.Handler) ssh.Handler {
return func(s ssh.Session) {
wish.Println(s, "authorized!")
}
},
),
)
if err != nil {
log.Error("could not start server", "error", err)
}

done := make(chan os.Signal, 1)
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
log.Info("Starting SSH server", "host", host, "port", port)
go func() {
if err = s.ListenAndServe(); err != nil && !errors.Is(err, ssh.ErrServerClosed) {
log.Error("could not start server", "error", err)
done <- nil
}
}()

<-done
log.Info("Stopping SSH server")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer func() { cancel() }()
if err := s.Shutdown(ctx); err != nil && !errors.Is(err, ssh.ErrServerClosed) {
log.Error("could not stop server", "error", err)
}
}

0 comments on commit 91171be

Please sign in to comment.