|
| 1 | +package main |
| 2 | + |
| 3 | +import ( |
| 4 | + "log/slog" |
| 5 | + "net/http" |
| 6 | + "net/url" |
| 7 | + "os" |
| 8 | + "time" |
| 9 | + |
| 10 | + "github.com/andrewheberle/go-http-auth-server/pkg/sp" |
| 11 | + "github.com/spf13/pflag" |
| 12 | + "github.com/spf13/viper" |
| 13 | +) |
| 14 | + |
| 15 | +func main() { |
| 16 | + // command line flags |
| 17 | + pflag.String("cert", "", "HTTPS Certificate") |
| 18 | + pflag.String("key", "", "HTTPS Key") |
| 19 | + pflag.String("listen", "127.0.0.1:9091", "Listen address") |
| 20 | + pflag.String("sp-cert", "", "Service Provider Certificate") |
| 21 | + pflag.String("sp-key", "", "Service Provider Key") |
| 22 | + pflag.String("sp-url", "http://localhost:9091", "Service Provider URL") |
| 23 | + pflag.StringToString("sp-claim-mapping", map[string]string{"urn:oasis:names:tc:SAML:attribute:subject-id": "remote-user", "mail": "remote-email", "displayName": "remote-name", "role": "remote-groups"}, "Mapping of claims to headers") |
| 24 | + pflag.String("metadata", "", "IdP Metadata URL") |
| 25 | + pflag.Bool("debug", false, "Enable debug logging") |
| 26 | + pflag.Parse() |
| 27 | + |
| 28 | + // bind to viper |
| 29 | + viper.BindPFlags(pflag.CommandLine) |
| 30 | + |
| 31 | + // load from environment |
| 32 | + viper.SetEnvPrefix("auth") |
| 33 | + viper.AutomaticEnv() |
| 34 | + |
| 35 | + // logging setup |
| 36 | + var logLevel = new(slog.LevelVar) |
| 37 | + logHandler := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: logLevel}) |
| 38 | + slog.SetDefault(slog.New(logHandler)) |
| 39 | + if viper.GetBool("debug") { |
| 40 | + logLevel.Set(slog.LevelDebug) |
| 41 | + } |
| 42 | + |
| 43 | + // validate service provider root url |
| 44 | + root, err := url.Parse(viper.GetString("sp-url")) |
| 45 | + if err != nil { |
| 46 | + slog.Error("problem with SP URL", err) |
| 47 | + os.Exit(1) |
| 48 | + } |
| 49 | + |
| 50 | + // validate metadata url |
| 51 | + metadata, err := url.Parse(viper.GetString("metadata")) |
| 52 | + if err != nil { |
| 53 | + slog.Error("problem with IdP metadata URL", err) |
| 54 | + os.Exit(1) |
| 55 | + } |
| 56 | + |
| 57 | + // set up auth provider |
| 58 | + provider, err := sp.NewServiceProvider(viper.GetString("sp-cert"), viper.GetString("sp-key"), metadata, root, viper.GetStringMapString("sp-claim-mapping")) |
| 59 | + if err != nil { |
| 60 | + slog.Error("problem setting up SP", err) |
| 61 | + os.Exit(1) |
| 62 | + } |
| 63 | + |
| 64 | + // set up auth endpoints |
| 65 | + http.HandleFunc("/api/verify", provider.ForwardAuthHandler) |
| 66 | + http.HandleFunc("/api/authz/forward-auth", provider.ForwardAuthHandler) |
| 67 | + |
| 68 | + // set up saml endpoints |
| 69 | + http.HandleFunc(provider.AcsURL().Path, provider.ACSHandler) |
| 70 | + http.HandleFunc(provider.MetadataURL().Path, provider.MetadataHandler) |
| 71 | + http.HandleFunc(provider.LogoutUrl().Path, provider.LogoutHandler) |
| 72 | + |
| 73 | + // login endpoint |
| 74 | + http.Handle("/#", provider.RequireAccount(http.HandlerFunc((func(w http.ResponseWriter, r *http.Request) { |
| 75 | + w.Write([]byte("Logged In.")) |
| 76 | + })))) |
| 77 | + |
| 78 | + // dummy endpoint |
| 79 | + |
| 80 | + srv := &http.Server{ |
| 81 | + Addr: viper.GetString("listen"), |
| 82 | + ReadTimeout: time.Second * 3, |
| 83 | + WriteTimeout: time.Second * 3, |
| 84 | + } |
| 85 | + |
| 86 | + slog.Info("starting service", |
| 87 | + "listen", srv.Addr, |
| 88 | + "idp-metadata-url", metadata.String(), |
| 89 | + "sp-acs-url", provider.AcsURL().String(), |
| 90 | + "sp-metdata-url", provider.MetadataURL().String(), |
| 91 | + "sp-logout-url", provider.LogoutUrl().String(), |
| 92 | + ) |
| 93 | + |
| 94 | + if err := srv.ListenAndServe(); err != nil { |
| 95 | + slog.Error("problem with SP URL", err) |
| 96 | + os.Exit(1) |
| 97 | + } |
| 98 | +} |
0 commit comments