diff --git a/dashboard/package.json b/dashboard/package.json index 8692ac4..3649f73 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -1,6 +1,6 @@ { "name": "oauth2-fe", - "version": "0.1.4", + "version": "0.2.0", "private": true, "scripts": { "dev": "next dev", diff --git a/oauth2/go.mod b/oauth2/go.mod index 2857044..77cf704 100644 --- a/oauth2/go.mod +++ b/oauth2/go.mod @@ -33,7 +33,7 @@ require ( github.com/go-playground/validator/v10 v10.15.5 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/golang/snappy v0.0.1 // indirect - github.com/google/uuid v1.5.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.13.6 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect diff --git a/oauth2/go.sum b/oauth2/go.sum index 8c7a3b7..6199767 100644 --- a/oauth2/go.sum +++ b/oauth2/go.sum @@ -38,8 +38,8 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= diff --git a/pkg/authapi/go.mod b/pkg/authapi/go.mod index 86488f4..7e84a99 100644 --- a/pkg/authapi/go.mod +++ b/pkg/authapi/go.mod @@ -32,7 +32,7 @@ require ( github.com/go-playground/validator/v10 v10.14.0 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/golang/snappy v0.0.1 // indirect - github.com/google/uuid v1.5.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.13.6 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect diff --git a/pkg/authapi/go.sum b/pkg/authapi/go.sum index c03fbb7..1b657a1 100644 --- a/pkg/authapi/go.sum +++ b/pkg/authapi/go.sum @@ -31,8 +31,8 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= diff --git a/pkg/authapi/oauth2.go b/pkg/authapi/oauth2.go index 9d6dac8..b05bc8c 100644 --- a/pkg/authapi/oauth2.go +++ b/pkg/authapi/oauth2.go @@ -5,6 +5,7 @@ import ( "github.com/gin-gonic/gin" "github.com/ufosc/OpenWebServices/pkg/authdb" "github.com/ufosc/OpenWebServices/pkg/authmw" + "github.com/ufosc/OpenWebServices/pkg/common" "net/http" "net/url" "time" @@ -84,6 +85,7 @@ func (cntrl *DefaultAPIController) AuthorizationRoute() gin.HandlerFunc { // Create implicit token. if client.ResponseType == "token" { token := authdb.TokenModel{ + ID: common.UUID(), ClientID: client.ID, UserID: user.ID, CreatedAt: time.Now().Unix(), @@ -109,6 +111,7 @@ func (cntrl *DefaultAPIController) AuthorizationRoute() gin.HandlerFunc { // Create authorization code. code := authdb.TokenModel{ + ID: common.UUID(), ClientID: client.ID, UserID: user.ID, CreatedAt: time.Now().Unix(), @@ -264,6 +267,7 @@ func (cntrl *DefaultAPIController) handleAuthCode(c *gin.Context) { // Create access token. atoken := authdb.TokenModel{ + ID: common.UUID(), ClientID: client.ID, UserID: codeExists.UserID, CreatedAt: time.Now().Unix(), @@ -282,6 +286,7 @@ func (cntrl *DefaultAPIController) handleAuthCode(c *gin.Context) { // Create refresh token. rtoken := authdb.TokenModel{ + ID: common.UUID(), ClientID: client.ID, UserID: codeExists.UserID, CreatedAt: time.Now().Unix(), @@ -394,6 +399,7 @@ func (cntrl *DefaultAPIController) handleRefreshToken(c *gin.Context) { // Create new access token. atoken := authdb.TokenModel{ + ID: common.UUID(), ClientID: client.ID, UserID: token.UserID, CreatedAt: time.Now().Unix(), diff --git a/pkg/authapi/session.go b/pkg/authapi/session.go index a31763c..127d7e6 100644 --- a/pkg/authapi/session.go +++ b/pkg/authapi/session.go @@ -98,6 +98,7 @@ func (cntrl *DefaultAPIController) SignUpRoute() gin.HandlerFunc { // Create pending user instance. pendingUser := authdb.PendingUserModel{ + ID: common.UUID(), Email: req.Email, User: authdb.UserModel{ ID: "", @@ -175,6 +176,7 @@ func (cntrl *DefaultAPIController) SignInRoute() gin.HandlerFunc { // Generate access token. tk, err := cntrl.db.Tokens().CreateAccess(authdb.TokenModel{ + ID: common.UUID(), ClientID: "0", UserID: userExists.ID, CreatedAt: time.Now().Unix(), diff --git a/pkg/authdb/authdb.go b/pkg/authdb/authdb.go index d942c23..84e9415 100644 --- a/pkg/authdb/authdb.go +++ b/pkg/authdb/authdb.go @@ -76,12 +76,12 @@ func NewDatabase(uri, name string) (*MongoDatabase, error) { } db.users = users - addTTL(db) + initIndices(db) return db, nil } -// Add TTL indices. -func addTTL(db *MongoDatabase) { +// initIndices initializes database indices. +func initIndices(db *MongoDatabase) { index := func(ttl int32) mongo.IndexModel { return mongo.IndexModel{ Keys: bson.M{"createdAt": 1}, @@ -126,6 +126,44 @@ func addTTL(db *MongoDatabase) { fmt.Println("unable to apply TTL to pending_users collection:", err) os.Exit(1) } + + // Create a custom identifier index for tokens and verification + // emails. Default indices are not cryptographically random. + _, err = refcol.Indexes().CreateOne(context.TODO(), mongo.IndexModel{ + Keys: bson.M{"ID": 1}, + }) + + if err != nil { + fmt.Println("cannot apply index to refresh_token collection", err) + os.Exit(1) + } + + _, err = acccol.Indexes().CreateOne(context.TODO(), mongo.IndexModel{ + Keys: bson.M{"ID": 1}, + }) + + if err != nil { + fmt.Println("cannot apply index to access_token collection", err) + os.Exit(1) + } + + _, err = autcol.Indexes().CreateOne(context.TODO(), mongo.IndexModel{ + Keys: bson.M{"ID": 1}, + }) + + if err != nil { + fmt.Println("cannot apply index to auth_token collection", err) + os.Exit(1) + } + + _, err = pencol.Indexes().CreateOne(context.TODO(), mongo.IndexModel{ + Keys: bson.M{"ID": 1}, + }) + + if err != nil { + fmt.Println("cannot apply index to pending_users collection", err) + os.Exit(1) + } } // Stop the database. diff --git a/pkg/authdb/tokens.go b/pkg/authdb/tokens.go index 1f32b9a..580690e 100644 --- a/pkg/authdb/tokens.go +++ b/pkg/authdb/tokens.go @@ -3,14 +3,14 @@ package authdb import ( "context" "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" ) // The Token schema is used for authentication codes, access tokens, and // refresh tokens. type TokenModel struct { - ID string `bson:"_id,omitempty"` + _id string `bson:"_id,omitempty"` + ID string `bson:"ID"` ClientID string `bson:"client_id"` UserID string `bson:"user_id"` CreatedAt int64 `bson:"createdAt"` @@ -73,15 +73,11 @@ func (cc *MongoTokenController) FindRefreshByID(id string) (TokenModel, error) { cc.state.Wg.Add(1) defer cc.state.Wg.Done() - // Extract primitive object ID. - objID, err := primitive.ObjectIDFromHex(id) - if err != nil { - return TokenModel{}, err - } - // Find model. var token TokenModel - err = cc.refreshColl.FindOne(context.TODO(), bson.D{{Key: "_id", Value: objID}}).Decode(&token) + err := cc.refreshColl.FindOne(context.TODO(), + bson.D{{Key: "ID", Value: id}}).Decode(&token) + if err != nil { return TokenModel{}, err } @@ -98,12 +94,12 @@ func (cc *MongoTokenController) CreateRefresh(tk TokenModel) (string, error) { defer cc.state.Wg.Done() // Insert. - res, err := cc.refreshColl.InsertOne(context.TODO(), tk) + _, err := cc.refreshColl.InsertOne(context.TODO(), tk) if err != nil { return "", err } - return res.InsertedID.(primitive.ObjectID).Hex(), nil + return tk.ID, nil } func (cc *MongoTokenController) DeleteRefreshByID(id string) error { @@ -113,14 +109,9 @@ func (cc *MongoTokenController) DeleteRefreshByID(id string) error { cc.state.Wg.Add(1) defer cc.state.Wg.Done() + _, err := cc.refreshColl.DeleteOne(context.TODO(), + bson.D{{Key: "ID", Value: id}}) - // Extract primitive object ID. - objID, err := primitive.ObjectIDFromHex(id) - if err != nil { - return err - } - - _, err = cc.refreshColl.DeleteOne(context.TODO(), bson.D{{Key: "_id", Value: objID}}) return err } @@ -132,15 +123,11 @@ func (cc *MongoTokenController) FindAccessByID(id string) (TokenModel, error) { cc.state.Wg.Add(1) defer cc.state.Wg.Done() - // Extract primitive object ID. - objID, err := primitive.ObjectIDFromHex(id) - if err != nil { - return TokenModel{}, err - } - // Find model. var token TokenModel - err = cc.accessColl.FindOne(context.TODO(), bson.D{{Key: "_id", Value: objID}}).Decode(&token) + err := cc.accessColl.FindOne(context.TODO(), + bson.D{{Key: "ID", Value: id}}).Decode(&token) + if err != nil { return TokenModel{}, err } @@ -157,12 +144,12 @@ func (cc *MongoTokenController) CreateAccess(tk TokenModel) (string, error) { defer cc.state.Wg.Done() // Insert. - res, err := cc.accessColl.InsertOne(context.TODO(), tk) + _, err := cc.accessColl.InsertOne(context.TODO(), tk) if err != nil { return "", err } - return res.InsertedID.(primitive.ObjectID).Hex(), nil + return tk.ID, nil } func (cc *MongoTokenController) DeleteAccessByID(id string) error { @@ -172,14 +159,9 @@ func (cc *MongoTokenController) DeleteAccessByID(id string) error { cc.state.Wg.Add(1) defer cc.state.Wg.Done() + _, err := cc.accessColl.DeleteOne(context.TODO(), + bson.D{{Key: "ID", Value: id}}) - // Extract primitive object ID. - objID, err := primitive.ObjectIDFromHex(id) - if err != nil { - return err - } - - _, err = cc.accessColl.DeleteOne(context.TODO(), bson.D{{Key: "_id", Value: objID}}) return err } @@ -191,15 +173,11 @@ func (cc *MongoTokenController) FindAuthByID(id string) (TokenModel, error) { cc.state.Wg.Add(1) defer cc.state.Wg.Done() - // Extract primitive object ID. - objID, err := primitive.ObjectIDFromHex(id) - if err != nil { - return TokenModel{}, err - } - // Find model. var token TokenModel - err = cc.authColl.FindOne(context.TODO(), bson.D{{Key: "_id", Value: objID}}).Decode(&token) + err := cc.authColl.FindOne(context.TODO(), + bson.D{{Key: "ID", Value: id}}).Decode(&token) + if err != nil { return TokenModel{}, err } @@ -216,12 +194,12 @@ func (cc *MongoTokenController) CreateAuth(tk TokenModel) (string, error) { defer cc.state.Wg.Done() // Insert. - res, err := cc.authColl.InsertOne(context.TODO(), tk) + _, err := cc.authColl.InsertOne(context.TODO(), tk) if err != nil { return "", err } - return res.InsertedID.(primitive.ObjectID).Hex(), nil + return tk.ID, nil } func (cc *MongoTokenController) DeleteAuthByID(id string) error { @@ -231,13 +209,8 @@ func (cc *MongoTokenController) DeleteAuthByID(id string) error { cc.state.Wg.Add(1) defer cc.state.Wg.Done() + _, err := cc.authColl.DeleteOne(context.TODO(), + bson.D{{Key: "ID", Value: id}}) - // Extract primitive object ID. - objID, err := primitive.ObjectIDFromHex(id) - if err != nil { - return err - } - - _, err = cc.authColl.DeleteOne(context.TODO(), bson.D{{Key: "_id", Value: objID}}) return err } diff --git a/pkg/authdb/users.go b/pkg/authdb/users.go index c1b9663..f1f98d5 100644 --- a/pkg/authdb/users.go +++ b/pkg/authdb/users.go @@ -22,7 +22,8 @@ type UserModel struct { // PendingUserModel is a sign up request that is awaiting email // verification. type PendingUserModel struct { - ID string `bson:"_id,omitempty"` + _id string `bson:"_id,omitempty"` + ID string `bson:"ID"` Email string `bson:"email"` User UserModel `bson:"user"` TTL int64 `bson:"expireAfterSeconds"` @@ -234,15 +235,11 @@ func (cc *MongoUserController) FindPendingByID(id string) ( cc.state.Wg.Add(1) defer cc.state.Wg.Done() - // Extract primitive object ID. - objID, err := primitive.ObjectIDFromHex(id) - if err != nil { - return PendingUserModel{}, err - } - // Find model. var user PendingUserModel - err = cc.pcoll.FindOne(context.TODO(), bson.D{{Key: "_id", Value: objID}}).Decode(&user) + err := cc.pcoll.FindOne(context.TODO(), + bson.D{{Key: "ID", Value: id}}).Decode(&user) + if err != nil { return PendingUserModel{}, err } @@ -281,12 +278,12 @@ func (cc *MongoUserController) CreatePending(usr PendingUserModel) ( defer cc.state.Wg.Done() // Insert - res, err := cc.pcoll.InsertOne(context.TODO(), usr) + _, err := cc.pcoll.InsertOne(context.TODO(), usr) if err != nil { return "", err } - return res.InsertedID.(primitive.ObjectID).Hex(), nil + return usr.ID, nil } // DeletePendingByID deletes the pending user with the given id. @@ -298,12 +295,8 @@ func (cc *MongoUserController) DeletePendingByID(id string) error { cc.state.Wg.Add(1) defer cc.state.Wg.Done() - // Extract primitive object ID. - objID, err := primitive.ObjectIDFromHex(id) - if err != nil { - return err - } + _, err := cc.pcoll.DeleteOne(context.TODO(), + bson.D{{Key: "ID", Value: id}}) - _, err = cc.pcoll.DeleteOne(context.TODO(), bson.D{{Key: "_id", Value: objID}}) return err } diff --git a/pkg/authmw/go.mod b/pkg/authmw/go.mod index 7eea619..879796d 100644 --- a/pkg/authmw/go.mod +++ b/pkg/authmw/go.mod @@ -26,6 +26,7 @@ require ( github.com/go-playground/validator/v10 v10.14.0 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/golang/snappy v0.0.1 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.13.6 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect diff --git a/pkg/authmw/go.sum b/pkg/authmw/go.sum index 8a6020f..509f045 100644 --- a/pkg/authmw/go.sum +++ b/pkg/authmw/go.sum @@ -27,6 +27,8 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= diff --git a/pkg/common/go.mod b/pkg/common/go.mod index 3d11739..499607c 100644 --- a/pkg/common/go.mod +++ b/pkg/common/go.mod @@ -9,6 +9,7 @@ replace github.com/ufosc/OpenWebServices/pkg/authdb => ../authdb replace github.com/ufosc/OpenWebServices/pkg/websmtp => ../websmtp require ( + github.com/google/uuid v1.6.0 github.com/wagslane/go-password-validator v0.3.0 golang.org/x/crypto v0.17.0 ) diff --git a/pkg/common/go.sum b/pkg/common/go.sum index 2e12a41..0126193 100644 --- a/pkg/common/go.sum +++ b/pkg/common/go.sum @@ -1,3 +1,5 @@ +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/wagslane/go-password-validator v0.3.0 h1:vfxOPzGHkz5S146HDpavl0cw1DSVP061Ry2PX0/ON6I= github.com/wagslane/go-password-validator v0.3.0/go.mod h1:TI1XJ6T5fRdRnHqHt14pvy1tNVnrwe7m3/f1f2fDphQ= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= diff --git a/pkg/common/uuid.go b/pkg/common/uuid.go new file mode 100644 index 0000000..a2b1be6 --- /dev/null +++ b/pkg/common/uuid.go @@ -0,0 +1,7 @@ +package common + +import "github.com/google/uuid" + +func UUID() string { + return uuid.New().String() +}