diff --git a/src/github.com/matrix-org/go-neb/api.go b/src/github.com/matrix-org/go-neb/api.go index cc419b2..084ea43 100644 --- a/src/github.com/matrix-org/go-neb/api.go +++ b/src/github.com/matrix-org/go-neb/api.go @@ -51,6 +51,23 @@ func (h *requestAuthSessionHandler) OnIncomingRequest(req *http.Request) (interf return response, nil } +type realmRedirectHandler struct { + db *database.ServiceDB +} + +func (rh *realmRedirectHandler) handle(w http.ResponseWriter, req *http.Request) { + segments := strings.Split(req.URL.Path, "/") + // last path segment is the realm ID which we will pass the incoming request to + realmID := segments[len(segments)-1] + realm, err := rh.db.LoadAuthRealm(realmID) + if err != nil { + log.WithError(err).WithField("realm_id", realmID).Print("Failed to load realm") + w.WriteHeader(404) + return + } + realm.OnReceiveRedirect(w, req) +} + type configureAuthRealmHandler struct { db *database.ServiceDB } diff --git a/src/github.com/matrix-org/go-neb/goneb.go b/src/github.com/matrix-org/go-neb/goneb.go index ca066a9..692d2e2 100644 --- a/src/github.com/matrix-org/go-neb/goneb.go +++ b/src/github.com/matrix-org/go-neb/goneb.go @@ -37,6 +37,8 @@ func main() { http.Handle("/admin/requestAuthSession", server.MakeJSONAPI(&requestAuthSessionHandler{db: db})) wh := &webhookHandler{db: db, clients: clients} http.HandleFunc("/services/hooks/", wh.handle) + rh := &realmRedirectHandler{db: db} + http.HandleFunc("/realms/redirects/", rh.handle) http.ListenAndServe(bindAddress, nil) } diff --git a/src/github.com/matrix-org/go-neb/realms/github/github.go b/src/github.com/matrix-org/go-neb/realms/github/github.go index 552e059..aaf7a67 100644 --- a/src/github.com/matrix-org/go-neb/realms/github/github.go +++ b/src/github.com/matrix-org/go-neb/realms/github/github.go @@ -1,10 +1,13 @@ package realms import ( + "crypto/rand" + "encoding/hex" "encoding/json" log "github.com/Sirupsen/logrus" "github.com/matrix-org/go-neb/database" "github.com/matrix-org/go-neb/types" + "net/http" "net/url" ) @@ -12,7 +15,7 @@ type githubRealm struct { id string ClientSecret string ClientID string - WebhookEndpoint string + RedirectBaseURI string } type githubSession struct { @@ -38,18 +41,25 @@ func (r *githubRealm) Type() string { } func (r *githubRealm) RequestAuthSession(userID string, req json.RawMessage) interface{} { + state, err := randomString(10) + if err != nil { + log.WithError(err).Print("Failed to generate state param") + return nil + } u, _ := url.Parse("https://github.com/login/oauth/authorize") q := u.Query() q.Set("client_id", r.ClientID) q.Set("client_secret", r.ClientSecret) - // TODO: state, scope + q.Set("state", state) + // TODO: Path is from goneb.go - we should probably factor it out. + q.Set("redirect_uri", r.RedirectBaseURI+"/realms/redirects/"+r.ID()) u.RawQuery = q.Encode() session := &githubSession{ - State: "TODO", + State: state, userID: userID, realmID: r.ID(), } - _, err := database.GetServiceDB().StoreAuthSession(session) + _, err = database.GetServiceDB().StoreAuthSession(session) if err != nil { log.WithError(err).Print("Failed to store new auth session") return nil @@ -60,6 +70,9 @@ func (r *githubRealm) RequestAuthSession(userID string, req json.RawMessage) int }{u.String()} } +func (r *githubRealm) OnReceiveRedirect(w http.ResponseWriter, req *http.Request) { +} + func (r *githubRealm) AuthSession(userID, realmID string) types.AuthSession { return &githubSession{ userID: userID, @@ -67,6 +80,17 @@ func (r *githubRealm) AuthSession(userID, realmID string) types.AuthSession { } } +// Generate a cryptographically secure pseudorandom string with the given number of bytes (length). +// Returns a hex string of the bytes. +func randomString(length int) (string, error) { + b := make([]byte, length) + _, err := rand.Read(b) + if err != nil { + return "", err + } + return hex.EncodeToString(b), nil +} + func init() { types.RegisterAuthRealm(func(realmID string) types.AuthRealm { return &githubRealm{id: realmID} diff --git a/src/github.com/matrix-org/go-neb/types/types.go b/src/github.com/matrix-org/go-neb/types/types.go index 47c801c..f72e110 100644 --- a/src/github.com/matrix-org/go-neb/types/types.go +++ b/src/github.com/matrix-org/go-neb/types/types.go @@ -59,6 +59,7 @@ func CreateService(serviceID, serviceType string) Service { type AuthRealm interface { ID() string Type() string + OnReceiveRedirect(w http.ResponseWriter, req *http.Request) AuthSession(userID, realmID string) AuthSession RequestAuthSession(userID string, config json.RawMessage) interface{} }