feat: persist encrypted env
This commit is contained in:
parent
d9c40057e6
commit
e35d0cbcd6
|
@ -24,7 +24,7 @@ func deleteUserTest(s TestSetup, t *testing.T) {
|
||||||
})
|
})
|
||||||
assert.NotNil(t, err, "unauthorized")
|
assert.NotNil(t, err, "unauthorized")
|
||||||
|
|
||||||
req.Header.Add("x-authorizer-admin-secret", constants.ADMIN_SECRET)
|
req.Header.Add("x-authorizer-admin-secret", constants.EnvData.ADMIN_SECRET)
|
||||||
_, err = resolvers.DeleteUser(ctx, model.DeleteUserInput{
|
_, err = resolvers.DeleteUser(ctx, model.DeleteUserInput{
|
||||||
Email: email,
|
Email: email,
|
||||||
})
|
})
|
||||||
|
|
|
@ -8,18 +8,18 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEnvs(t *testing.T) {
|
func TestEnvs(t *testing.T) {
|
||||||
constants.ENV_PATH = "../../.env.sample"
|
constants.EnvData.ENV_PATH = "../../.env.sample"
|
||||||
|
|
||||||
assert.Equal(t, constants.ADMIN_SECRET, "admin")
|
assert.Equal(t, constants.EnvData.ADMIN_SECRET, "admin")
|
||||||
assert.Equal(t, constants.ENV, "production")
|
assert.Equal(t, constants.EnvData.ENV, "production")
|
||||||
assert.False(t, constants.DISABLE_EMAIL_VERIFICATION)
|
assert.False(t, constants.EnvData.DISABLE_EMAIL_VERIFICATION)
|
||||||
assert.False(t, constants.DISABLE_MAGIC_LINK_LOGIN)
|
assert.False(t, constants.EnvData.DISABLE_MAGIC_LINK_LOGIN)
|
||||||
assert.False(t, constants.DISABLE_BASIC_AUTHENTICATION)
|
assert.False(t, constants.EnvData.DISABLE_BASIC_AUTHENTICATION)
|
||||||
assert.Equal(t, constants.JWT_TYPE, "HS256")
|
assert.Equal(t, constants.EnvData.JWT_TYPE, "HS256")
|
||||||
assert.Equal(t, constants.JWT_SECRET, "random_string")
|
assert.Equal(t, constants.EnvData.JWT_SECRET, "random_string")
|
||||||
assert.Equal(t, constants.JWT_ROLE_CLAIM, "role")
|
assert.Equal(t, constants.EnvData.JWT_ROLE_CLAIM, "role")
|
||||||
assert.EqualValues(t, constants.ROLES, []string{"user"})
|
assert.EqualValues(t, constants.EnvData.ROLES, []string{"user"})
|
||||||
assert.EqualValues(t, constants.DEFAULT_ROLES, []string{"user"})
|
assert.EqualValues(t, constants.EnvData.DEFAULT_ROLES, []string{"user"})
|
||||||
assert.EqualValues(t, constants.PROTECTED_ROLES, []string{"admin"})
|
assert.EqualValues(t, constants.EnvData.PROTECTED_ROLES, []string{"admin"})
|
||||||
assert.EqualValues(t, constants.ALLOWED_ORIGINS, []string{"*"})
|
assert.EqualValues(t, constants.EnvData.ALLOWED_ORIGINS, []string{"*"})
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@ func TestResolvers(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for dbType, dbURL := range databases {
|
for dbType, dbURL := range databases {
|
||||||
constants.DATABASE_URL = dbURL
|
constants.EnvData.DATABASE_URL = dbURL
|
||||||
constants.DATABASE_TYPE = dbType
|
constants.EnvData.DATABASE_TYPE = dbType
|
||||||
db.InitDB()
|
db.InitDB()
|
||||||
|
|
||||||
s := testSetup()
|
s := testSetup()
|
||||||
|
|
|
@ -70,7 +70,7 @@ func testSetup() TestSetup {
|
||||||
Password: "test",
|
Password: "test",
|
||||||
}
|
}
|
||||||
|
|
||||||
constants.ENV_PATH = "../../.env.sample"
|
constants.EnvData.ENV_PATH = "../../.env.sample"
|
||||||
env.InitEnv()
|
env.InitEnv()
|
||||||
session.InitSession()
|
session.InitSession()
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ func updateUserTest(s TestSetup, t *testing.T) {
|
||||||
})
|
})
|
||||||
assert.NotNil(t, err, "unauthorized")
|
assert.NotNil(t, err, "unauthorized")
|
||||||
|
|
||||||
req.Header.Add("x-authorizer-admin-secret", constants.ADMIN_SECRET)
|
req.Header.Add("x-authorizer-admin-secret", constants.EnvData.ADMIN_SECRET)
|
||||||
_, err = resolvers.UpdateUser(ctx, model.UpdateUserInput{
|
_, err = resolvers.UpdateUser(ctx, model.UpdateUserInput{
|
||||||
ID: user.ID,
|
ID: user.ID,
|
||||||
Roles: newRoles,
|
Roles: newRoles,
|
||||||
|
|
|
@ -22,7 +22,7 @@ func usersTest(s TestSetup, t *testing.T) {
|
||||||
users, err := resolvers.Users(ctx)
|
users, err := resolvers.Users(ctx)
|
||||||
assert.NotNil(t, err, "unauthorized")
|
assert.NotNil(t, err, "unauthorized")
|
||||||
|
|
||||||
req.Header.Add("x-authorizer-admin-secret", constants.ADMIN_SECRET)
|
req.Header.Add("x-authorizer-admin-secret", constants.EnvData.ADMIN_SECRET)
|
||||||
users, err = resolvers.Users(ctx)
|
users, err = resolvers.Users(ctx)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
rLen := len(users)
|
rLen := len(users)
|
||||||
|
|
|
@ -22,7 +22,7 @@ func TestIsValidEmail(t *testing.T) {
|
||||||
func TestIsValidOrigin(t *testing.T) {
|
func TestIsValidOrigin(t *testing.T) {
|
||||||
// don't use portocal(http/https) for ALLOWED_ORIGINS while testing,
|
// don't use portocal(http/https) for ALLOWED_ORIGINS while testing,
|
||||||
// as we trim them off while running the main function
|
// as we trim them off while running the main function
|
||||||
constants.ALLOWED_ORIGINS = []string{"localhost:8080", "*.google.com", "*.google.in", "*abc.*"}
|
constants.EnvData.ALLOWED_ORIGINS = []string{"localhost:8080", "*.google.com", "*.google.in", "*abc.*"}
|
||||||
|
|
||||||
assert.False(t, utils.IsValidOrigin("http://myapp.com"), "it should be invalid origin")
|
assert.False(t, utils.IsValidOrigin("http://myapp.com"), "it should be invalid origin")
|
||||||
assert.False(t, utils.IsValidOrigin("http://appgoogle.com"), "it should be invalid origin")
|
assert.False(t, utils.IsValidOrigin("http://appgoogle.com"), "it should be invalid origin")
|
||||||
|
|
|
@ -23,7 +23,7 @@ func verificationRequestsTest(s TestSetup, t *testing.T) {
|
||||||
requests, err := resolvers.VerificationRequests(ctx)
|
requests, err := resolvers.VerificationRequests(ctx)
|
||||||
assert.NotNil(t, err, "unauthorizer")
|
assert.NotNil(t, err, "unauthorizer")
|
||||||
|
|
||||||
req.Header.Add("x-authorizer-admin-secret", constants.ADMIN_SECRET)
|
req.Header.Add("x-authorizer-admin-secret", constants.EnvData.ADMIN_SECRET)
|
||||||
requests, err = resolvers.VerificationRequests(ctx)
|
requests, err = resolvers.VerificationRequests(ctx)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
@ -1,50 +1,61 @@
|
||||||
package constants
|
package constants
|
||||||
|
|
||||||
// this constants are configured via env
|
type EnvConst struct {
|
||||||
var (
|
ADMIN_SECRET string
|
||||||
ADMIN_SECRET = ""
|
ENV string
|
||||||
ENV = ""
|
ENV_PATH string
|
||||||
ENV_PATH = ""
|
VERSION string
|
||||||
VERSION = ""
|
DATABASE_TYPE string
|
||||||
DATABASE_TYPE = ""
|
DATABASE_URL string
|
||||||
DATABASE_URL = ""
|
DATABASE_NAME string
|
||||||
DATABASE_NAME = ""
|
SMTP_HOST string
|
||||||
SMTP_HOST = ""
|
SMTP_PORT string
|
||||||
SMTP_PORT = ""
|
SENDER_EMAIL string
|
||||||
SENDER_EMAIL = ""
|
SENDER_PASSWORD string
|
||||||
SENDER_PASSWORD = ""
|
JWT_TYPE string
|
||||||
JWT_TYPE = ""
|
JWT_SECRET string
|
||||||
JWT_SECRET = ""
|
ALLOWED_ORIGINS []string
|
||||||
ALLOWED_ORIGINS = []string{}
|
AUTHORIZER_URL string
|
||||||
AUTHORIZER_URL = ""
|
APP_URL string
|
||||||
APP_URL = ""
|
PORT string
|
||||||
PORT = ""
|
REDIS_URL string
|
||||||
REDIS_URL = ""
|
COOKIE_NAME string
|
||||||
IS_PROD = false
|
ADMIN_COOKIE_NAME string
|
||||||
COOKIE_NAME = ""
|
RESET_PASSWORD_URL string
|
||||||
RESET_PASSWORD_URL = ""
|
ENCRYPTION_KEY string `json:"-"`
|
||||||
DISABLE_EMAIL_VERIFICATION = false
|
IS_PROD bool
|
||||||
DISABLE_BASIC_AUTHENTICATION = false
|
DISABLE_EMAIL_VERIFICATION bool
|
||||||
DISABLE_MAGIC_LINK_LOGIN = false
|
DISABLE_BASIC_AUTHENTICATION bool
|
||||||
DISABLE_LOGIN_PAGE = false
|
DISABLE_MAGIC_LINK_LOGIN bool
|
||||||
|
DISABLE_LOGIN_PAGE bool
|
||||||
|
|
||||||
// ROLES
|
// ROLES
|
||||||
ROLES = []string{}
|
ROLES []string
|
||||||
PROTECTED_ROLES = []string{}
|
PROTECTED_ROLES []string
|
||||||
DEFAULT_ROLES = []string{}
|
DEFAULT_ROLES []string
|
||||||
JWT_ROLE_CLAIM = "role"
|
JWT_ROLE_CLAIM string
|
||||||
|
|
||||||
// OAuth login
|
// OAuth login
|
||||||
GOOGLE_CLIENT_ID = ""
|
GOOGLE_CLIENT_ID string
|
||||||
GOOGLE_CLIENT_SECRET = ""
|
GOOGLE_CLIENT_SECRET string
|
||||||
GITHUB_CLIENT_ID = ""
|
GITHUB_CLIENT_ID string
|
||||||
GITHUB_CLIENT_SECRET = ""
|
GITHUB_CLIENT_SECRET string
|
||||||
FACEBOOK_CLIENT_ID = ""
|
FACEBOOK_CLIENT_ID string
|
||||||
FACEBOOK_CLIENT_SECRET = ""
|
FACEBOOK_CLIENT_SECRET string
|
||||||
TWITTER_CLIENT_ID = ""
|
|
||||||
TWITTER_CLIENT_SECRET = ""
|
|
||||||
|
|
||||||
// Org envs
|
// Org envs
|
||||||
ORGANIZATION_NAME = "Authorizer"
|
ORGANIZATION_NAME string
|
||||||
ORGANIZATION_LOGO = "https://authorizer.dev/images/logo.png"
|
ORGANIZATION_LOGO string
|
||||||
)
|
}
|
||||||
|
|
||||||
|
var EnvData = EnvConst{
|
||||||
|
ADMIN_COOKIE_NAME: "authorizer-admin",
|
||||||
|
JWT_ROLE_CLAIM: "role",
|
||||||
|
ORGANIZATION_NAME: "Authorizer",
|
||||||
|
ORGANIZATION_LOGO: "https://authorizer.dev/images/logo.png",
|
||||||
|
DISABLE_EMAIL_VERIFICATION: false,
|
||||||
|
DISABLE_BASIC_AUTHENTICATION: false,
|
||||||
|
DISABLE_MAGIC_LINK_LOGIN: false,
|
||||||
|
DISABLE_LOGIN_PAGE: false,
|
||||||
|
IS_PROD: false,
|
||||||
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
func initArangodb() (arangoDriver.Database, error) {
|
func initArangodb() (arangoDriver.Database, error) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
conn, err := http.NewConnection(http.ConnectionConfig{
|
conn, err := http.NewConnection(http.ConnectionConfig{
|
||||||
Endpoints: []string{constants.DATABASE_URL},
|
Endpoints: []string{constants.EnvData.DATABASE_URL},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -32,16 +32,16 @@ func initArangodb() (arangoDriver.Database, error) {
|
||||||
|
|
||||||
var arangodb driver.Database
|
var arangodb driver.Database
|
||||||
|
|
||||||
arangodb_exists, err := arangoClient.DatabaseExists(nil, constants.DATABASE_NAME)
|
arangodb_exists, err := arangoClient.DatabaseExists(nil, constants.EnvData.DATABASE_NAME)
|
||||||
|
|
||||||
if arangodb_exists {
|
if arangodb_exists {
|
||||||
log.Println(constants.DATABASE_NAME + " db exists already")
|
log.Println(constants.EnvData.DATABASE_NAME + " db exists already")
|
||||||
arangodb, err = arangoClient.Database(nil, constants.DATABASE_NAME)
|
arangodb, err = arangoClient.Database(nil, constants.EnvData.DATABASE_NAME)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
arangodb, err = arangoClient.CreateDatabase(nil, constants.DATABASE_NAME, nil)
|
arangodb, err = arangoClient.CreateDatabase(nil, constants.EnvData.DATABASE_NAME, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -100,5 +100,15 @@ func initArangodb() (arangoDriver.Database, error) {
|
||||||
Sparse: true,
|
Sparse: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
configCollectionExists, err := arangodb.CollectionExists(ctx, Collections.Config)
|
||||||
|
if configCollectionExists {
|
||||||
|
log.Println(Collections.Config + " collection exists already")
|
||||||
|
} else {
|
||||||
|
_, err = arangodb.CreateCollection(ctx, Collections.Config, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error creating collection("+Collections.Config+"):", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return arangodb, err
|
return arangodb, err
|
||||||
}
|
}
|
||||||
|
|
161
server/db/config.go
Normal file
161
server/db/config.go
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
arangoDriver "github.com/arangodb/go-driver"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Key string `json:"_key,omitempty" bson:"_key"` // for arangodb
|
||||||
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"`
|
||||||
|
Config []byte `gorm:"type:text" json:"config" bson:"config"`
|
||||||
|
Hash string `gorm:"type:hash" json:"hash" bson:"hash"`
|
||||||
|
UpdatedAt int64 `gorm:"autoUpdateTime" json:"updated_at" bson:"updated_at"`
|
||||||
|
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at" bson:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddConfig function to add config
|
||||||
|
func (mgr *manager) AddConfig(config Config) (Config, error) {
|
||||||
|
if config.ID == "" {
|
||||||
|
config.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsORMSupported {
|
||||||
|
// copy id as value for fields required for mongodb & arangodb
|
||||||
|
config.Key = config.ID
|
||||||
|
result := mgr.sqlDB.Create(&config)
|
||||||
|
|
||||||
|
if result.Error != nil {
|
||||||
|
log.Println("error adding config:", result.Error)
|
||||||
|
return config, result.Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsArangoDB {
|
||||||
|
config.CreatedAt = time.Now().Unix()
|
||||||
|
config.UpdatedAt = time.Now().Unix()
|
||||||
|
configCollection, _ := mgr.arangodb.Collection(nil, Collections.Config)
|
||||||
|
meta, err := configCollection.CreateDocument(arangoDriver.WithOverwrite(nil), config)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error adding config:", err)
|
||||||
|
return config, err
|
||||||
|
}
|
||||||
|
config.Key = meta.Key
|
||||||
|
config.ID = meta.ID.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsMongoDB {
|
||||||
|
config.CreatedAt = time.Now().Unix()
|
||||||
|
config.UpdatedAt = time.Now().Unix()
|
||||||
|
config.Key = config.ID
|
||||||
|
configCollection := mgr.mongodb.Collection(Collections.Config, options.Collection())
|
||||||
|
_, err := configCollection.InsertOne(nil, config)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error adding config:", err)
|
||||||
|
return config, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateConfig function to update config
|
||||||
|
func (mgr *manager) UpdateConfig(config Config) (Config, error) {
|
||||||
|
config.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
if IsORMSupported {
|
||||||
|
result := mgr.sqlDB.Save(&config)
|
||||||
|
|
||||||
|
if result.Error != nil {
|
||||||
|
log.Println("error updating config:", result.Error)
|
||||||
|
return config, result.Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsArangoDB {
|
||||||
|
collection, _ := mgr.arangodb.Collection(nil, Collections.Config)
|
||||||
|
meta, err := collection.UpdateDocument(nil, config.Key, config)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error updating config:", err)
|
||||||
|
return config, err
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Key = meta.Key
|
||||||
|
config.ID = meta.ID.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsMongoDB {
|
||||||
|
configCollection := mgr.mongodb.Collection(Collections.Config, options.Collection())
|
||||||
|
_, err := configCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": config.ID}}, bson.M{"$set": config}, options.MergeUpdateOptions())
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error updating config:", err)
|
||||||
|
return config, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetConfig function to get config
|
||||||
|
func (mgr *manager) GetConfig() (Config, error) {
|
||||||
|
var config Config
|
||||||
|
|
||||||
|
if IsORMSupported {
|
||||||
|
result := mgr.sqlDB.First(&config)
|
||||||
|
|
||||||
|
if result.Error != nil {
|
||||||
|
return config, result.Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsArangoDB {
|
||||||
|
query := fmt.Sprintf("FOR d in %s RETURN d", Collections.Config)
|
||||||
|
|
||||||
|
cursor, err := mgr.arangodb.Query(nil, query, nil)
|
||||||
|
if err != nil {
|
||||||
|
return config, err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
if !cursor.HasMore() {
|
||||||
|
if config.Key == "" {
|
||||||
|
return config, fmt.Errorf("config not found")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_, err := cursor.ReadDocument(nil, &config)
|
||||||
|
if err != nil {
|
||||||
|
return config, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsMongoDB {
|
||||||
|
configCollection := mgr.mongodb.Collection(Collections.Config, options.Collection())
|
||||||
|
cursor, err := configCollection.Find(nil, bson.M{}, options.Find())
|
||||||
|
if err != nil {
|
||||||
|
return config, err
|
||||||
|
}
|
||||||
|
defer cursor.Close(nil)
|
||||||
|
|
||||||
|
for cursor.Next(nil) {
|
||||||
|
err := cursor.Decode(&config)
|
||||||
|
if err != nil {
|
||||||
|
return config, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.ID == "" {
|
||||||
|
return config, fmt.Errorf("config not found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
|
@ -29,6 +29,9 @@ type Manager interface {
|
||||||
GetVerificationByEmail(email string, identifier string) (VerificationRequest, error)
|
GetVerificationByEmail(email string, identifier string) (VerificationRequest, error)
|
||||||
AddSession(session Session) error
|
AddSession(session Session) error
|
||||||
DeleteUserSession(userId string) error
|
DeleteUserSession(userId string) error
|
||||||
|
AddConfig(config Config) (Config, error)
|
||||||
|
UpdateConfig(config Config) (Config, error)
|
||||||
|
GetConfig() (Config, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type manager struct {
|
type manager struct {
|
||||||
|
@ -42,6 +45,7 @@ type CollectionList struct {
|
||||||
User string
|
User string
|
||||||
VerificationRequest string
|
VerificationRequest string
|
||||||
Session string
|
Session string
|
||||||
|
Config string
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -54,6 +58,7 @@ var (
|
||||||
User: Prefix + "users",
|
User: Prefix + "users",
|
||||||
VerificationRequest: Prefix + "verification_requests",
|
VerificationRequest: Prefix + "verification_requests",
|
||||||
Session: Prefix + "sessions",
|
Session: Prefix + "sessions",
|
||||||
|
Config: Prefix + "config",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -61,9 +66,9 @@ func InitDB() {
|
||||||
var sqlDB *gorm.DB
|
var sqlDB *gorm.DB
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
IsORMSupported = constants.DATABASE_TYPE != enum.Arangodb.String() && constants.DATABASE_TYPE != enum.Mongodb.String()
|
IsORMSupported = constants.EnvData.DATABASE_TYPE != enum.Arangodb.String() && constants.EnvData.DATABASE_TYPE != enum.Mongodb.String()
|
||||||
IsArangoDB = constants.DATABASE_TYPE == enum.Arangodb.String()
|
IsArangoDB = constants.EnvData.DATABASE_TYPE == enum.Arangodb.String()
|
||||||
IsMongoDB = constants.DATABASE_TYPE == enum.Mongodb.String()
|
IsMongoDB = constants.EnvData.DATABASE_TYPE == enum.Mongodb.String()
|
||||||
|
|
||||||
// sql db orm config
|
// sql db orm config
|
||||||
ormConfig := &gorm.Config{
|
ormConfig := &gorm.Config{
|
||||||
|
@ -72,20 +77,20 @@ func InitDB() {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("db type:", constants.DATABASE_TYPE)
|
log.Println("db type:", constants.EnvData.DATABASE_TYPE)
|
||||||
|
|
||||||
switch constants.DATABASE_TYPE {
|
switch constants.EnvData.DATABASE_TYPE {
|
||||||
case enum.Postgres.String():
|
case enum.Postgres.String():
|
||||||
sqlDB, err = gorm.Open(postgres.Open(constants.DATABASE_URL), ormConfig)
|
sqlDB, err = gorm.Open(postgres.Open(constants.EnvData.DATABASE_URL), ormConfig)
|
||||||
break
|
break
|
||||||
case enum.Sqlite.String():
|
case enum.Sqlite.String():
|
||||||
sqlDB, err = gorm.Open(sqlite.Open(constants.DATABASE_URL), ormConfig)
|
sqlDB, err = gorm.Open(sqlite.Open(constants.EnvData.DATABASE_URL), ormConfig)
|
||||||
break
|
break
|
||||||
case enum.Mysql.String():
|
case enum.Mysql.String():
|
||||||
sqlDB, err = gorm.Open(mysql.Open(constants.DATABASE_URL), ormConfig)
|
sqlDB, err = gorm.Open(mysql.Open(constants.EnvData.DATABASE_URL), ormConfig)
|
||||||
break
|
break
|
||||||
case enum.SQLServer.String():
|
case enum.SQLServer.String():
|
||||||
sqlDB, err = gorm.Open(sqlserver.Open(constants.DATABASE_URL), ormConfig)
|
sqlDB, err = gorm.Open(sqlserver.Open(constants.EnvData.DATABASE_URL), ormConfig)
|
||||||
break
|
break
|
||||||
case enum.Arangodb.String():
|
case enum.Arangodb.String():
|
||||||
arangodb, err := initArangodb()
|
arangodb, err := initArangodb()
|
||||||
|
@ -118,7 +123,7 @@ func InitDB() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Failed to init sqlDB:", err)
|
log.Fatal("Failed to init sqlDB:", err)
|
||||||
} else {
|
} else {
|
||||||
sqlDB.AutoMigrate(&User{}, &VerificationRequest{}, &Session{})
|
sqlDB.AutoMigrate(&User{}, &VerificationRequest{}, &Session{}, &Config{})
|
||||||
}
|
}
|
||||||
Mgr = &manager{
|
Mgr = &manager{
|
||||||
sqlDB: sqlDB,
|
sqlDB: sqlDB,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func initMongodb() (*mongo.Database, error) {
|
func initMongodb() (*mongo.Database, error) {
|
||||||
mongodbOptions := options.Client().ApplyURI(constants.DATABASE_URL)
|
mongodbOptions := options.Client().ApplyURI(constants.EnvData.DATABASE_URL)
|
||||||
maxWait := time.Duration(5 * time.Second)
|
maxWait := time.Duration(5 * time.Second)
|
||||||
mongodbOptions.ConnectTimeout = &maxWait
|
mongodbOptions.ConnectTimeout = &maxWait
|
||||||
mongoClient, err := mongo.NewClient(mongodbOptions)
|
mongoClient, err := mongo.NewClient(mongodbOptions)
|
||||||
|
@ -30,7 +30,7 @@ func initMongodb() (*mongo.Database, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mongodb := mongoClient.Database(constants.DATABASE_NAME, options.Database())
|
mongodb := mongoClient.Database(constants.EnvData.DATABASE_NAME, options.Database())
|
||||||
|
|
||||||
mongodb.CreateCollection(ctx, Collections.User, options.CreateCollection())
|
mongodb.CreateCollection(ctx, Collections.User, options.CreateCollection())
|
||||||
userCollection := mongodb.Collection(Collections.User, options.Collection())
|
userCollection := mongodb.Collection(Collections.User, options.Collection())
|
||||||
|
@ -73,5 +73,7 @@ func initMongodb() (*mongo.Database, error) {
|
||||||
},
|
},
|
||||||
}, options.CreateIndexes())
|
}, options.CreateIndexes())
|
||||||
|
|
||||||
|
mongodb.CreateCollection(ctx, Collections.Config, options.CreateCollection())
|
||||||
|
|
||||||
return mongodb, nil
|
return mongodb, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ func (mgr *manager) AddUser(user User) (User, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Roles == "" {
|
if user.Roles == "" {
|
||||||
user.Roles = constants.DEFAULT_ROLES[0]
|
user.Roles = constants.EnvData.DEFAULT_ROLES[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
if IsORMSupported {
|
if IsORMSupported {
|
||||||
|
|
|
@ -27,7 +27,7 @@ type Sender struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSender() Sender {
|
func NewSender() Sender {
|
||||||
return Sender{User: constants.SENDER_EMAIL, Password: constants.SENDER_PASSWORD}
|
return Sender{User: constants.EnvData.SENDER_EMAIL, Password: constants.EnvData.SENDER_PASSWORD}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sender Sender) SendMail(Dest []string, Subject, bodyMessage string) error {
|
func (sender Sender) SendMail(Dest []string, Subject, bodyMessage string) error {
|
||||||
|
@ -35,8 +35,8 @@ func (sender Sender) SendMail(Dest []string, Subject, bodyMessage string) error
|
||||||
"To: " + strings.Join(Dest, ",") + "\n" +
|
"To: " + strings.Join(Dest, ",") + "\n" +
|
||||||
"Subject: " + Subject + "\n" + bodyMessage
|
"Subject: " + Subject + "\n" + bodyMessage
|
||||||
|
|
||||||
err := smtp.SendMail(constants.SMTP_HOST+":"+constants.SMTP_PORT,
|
err := smtp.SendMail(constants.EnvData.SMTP_HOST+":"+constants.EnvData.SMTP_PORT,
|
||||||
smtp.PlainAuth("", sender.User, sender.Password, constants.SMTP_HOST),
|
smtp.PlainAuth("", sender.User, sender.Password, constants.EnvData.SMTP_HOST),
|
||||||
sender.User, Dest, []byte(msg))
|
sender.User, Dest, []byte(msg))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
|
|
225
server/env/env.go
vendored
225
server/env/env.go
vendored
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,163 +21,169 @@ var (
|
||||||
|
|
||||||
// InitEnv -> to initialize env and through error if required env are not present
|
// InitEnv -> to initialize env and through error if required env are not present
|
||||||
func InitEnv() {
|
func InitEnv() {
|
||||||
if constants.ENV_PATH == "" {
|
if constants.EnvData.ENV_PATH == "" {
|
||||||
constants.ENV_PATH = `.env`
|
constants.EnvData.ENV_PATH = `.env`
|
||||||
}
|
}
|
||||||
|
|
||||||
if ARG_ENV_FILE != nil && *ARG_ENV_FILE != "" {
|
if ARG_ENV_FILE != nil && *ARG_ENV_FILE != "" {
|
||||||
constants.ENV_PATH = *ARG_ENV_FILE
|
constants.EnvData.ENV_PATH = *ARG_ENV_FILE
|
||||||
}
|
}
|
||||||
|
|
||||||
err := godotenv.Load(constants.ENV_PATH)
|
err := godotenv.Load(constants.EnvData.ENV_PATH)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error loading %s file", constants.ENV_PATH)
|
log.Printf("error loading %s file", constants.EnvData.ENV_PATH)
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.ADMIN_SECRET == "" {
|
if constants.EnvData.ADMIN_SECRET == "" {
|
||||||
constants.ADMIN_SECRET = os.Getenv("ADMIN_SECRET")
|
constants.EnvData.ADMIN_SECRET = os.Getenv("ADMIN_SECRET")
|
||||||
if constants.ADMIN_SECRET == "" {
|
|
||||||
panic("root admin secret is required")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.ENV == "" {
|
if constants.EnvData.DATABASE_TYPE == "" {
|
||||||
constants.ENV = os.Getenv("ENV")
|
constants.EnvData.DATABASE_TYPE = os.Getenv("DATABASE_TYPE")
|
||||||
if constants.ENV == "" {
|
log.Println(constants.EnvData.DATABASE_TYPE)
|
||||||
constants.ENV = "production"
|
|
||||||
}
|
|
||||||
|
|
||||||
if constants.ENV == "production" {
|
|
||||||
constants.IS_PROD = true
|
|
||||||
os.Setenv("GIN_MODE", "release")
|
|
||||||
} else {
|
|
||||||
constants.IS_PROD = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if constants.DATABASE_TYPE == "" {
|
|
||||||
constants.DATABASE_TYPE = os.Getenv("DATABASE_TYPE")
|
|
||||||
log.Println(constants.DATABASE_TYPE)
|
|
||||||
|
|
||||||
if ARG_DB_TYPE != nil && *ARG_DB_TYPE != "" {
|
if ARG_DB_TYPE != nil && *ARG_DB_TYPE != "" {
|
||||||
constants.DATABASE_TYPE = *ARG_DB_TYPE
|
constants.EnvData.DATABASE_TYPE = *ARG_DB_TYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.DATABASE_TYPE == "" {
|
if constants.EnvData.DATABASE_TYPE == "" {
|
||||||
panic("DATABASE_TYPE is required")
|
panic("DATABASE_TYPE is required")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.DATABASE_URL == "" {
|
if constants.EnvData.DATABASE_URL == "" {
|
||||||
constants.DATABASE_URL = os.Getenv("DATABASE_URL")
|
constants.EnvData.DATABASE_URL = os.Getenv("DATABASE_URL")
|
||||||
|
|
||||||
if ARG_DB_URL != nil && *ARG_DB_URL != "" {
|
if ARG_DB_URL != nil && *ARG_DB_URL != "" {
|
||||||
constants.DATABASE_URL = *ARG_DB_URL
|
constants.EnvData.DATABASE_URL = *ARG_DB_URL
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.DATABASE_URL == "" {
|
if constants.EnvData.DATABASE_URL == "" {
|
||||||
panic("DATABASE_URL is required")
|
panic("DATABASE_URL is required")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.DATABASE_NAME == "" {
|
if constants.EnvData.DATABASE_NAME == "" {
|
||||||
constants.DATABASE_NAME = os.Getenv("DATABASE_NAME")
|
constants.EnvData.DATABASE_NAME = os.Getenv("DATABASE_NAME")
|
||||||
if constants.DATABASE_NAME == "" {
|
if constants.EnvData.DATABASE_NAME == "" {
|
||||||
constants.DATABASE_NAME = "authorizer"
|
constants.EnvData.DATABASE_NAME = "authorizer"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.SMTP_HOST == "" {
|
if constants.EnvData.ENV == "" {
|
||||||
constants.SMTP_HOST = os.Getenv("SMTP_HOST")
|
constants.EnvData.ENV = os.Getenv("ENV")
|
||||||
|
if constants.EnvData.ENV == "" {
|
||||||
|
constants.EnvData.ENV = "production"
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.SMTP_PORT == "" {
|
if constants.EnvData.ENV == "production" {
|
||||||
constants.SMTP_PORT = os.Getenv("SMTP_PORT")
|
constants.EnvData.IS_PROD = true
|
||||||
}
|
os.Setenv("GIN_MODE", "release")
|
||||||
|
} else {
|
||||||
if constants.SENDER_EMAIL == "" {
|
constants.EnvData.IS_PROD = false
|
||||||
constants.SENDER_EMAIL = os.Getenv("SENDER_EMAIL")
|
|
||||||
}
|
|
||||||
|
|
||||||
if constants.SENDER_PASSWORD == "" {
|
|
||||||
constants.SENDER_PASSWORD = os.Getenv("SENDER_PASSWORD")
|
|
||||||
}
|
|
||||||
|
|
||||||
if constants.JWT_SECRET == "" {
|
|
||||||
constants.JWT_SECRET = os.Getenv("JWT_SECRET")
|
|
||||||
}
|
|
||||||
|
|
||||||
if constants.JWT_TYPE == "" {
|
|
||||||
constants.JWT_TYPE = os.Getenv("JWT_TYPE")
|
|
||||||
}
|
|
||||||
|
|
||||||
if constants.JWT_ROLE_CLAIM == "" {
|
|
||||||
constants.JWT_ROLE_CLAIM = os.Getenv("JWT_ROLE_CLAIM")
|
|
||||||
|
|
||||||
if constants.JWT_ROLE_CLAIM == "" {
|
|
||||||
constants.JWT_ROLE_CLAIM = "role"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.AUTHORIZER_URL == "" {
|
if constants.EnvData.SMTP_HOST == "" {
|
||||||
constants.AUTHORIZER_URL = strings.TrimSuffix(os.Getenv("AUTHORIZER_URL"), "/")
|
constants.EnvData.SMTP_HOST = os.Getenv("SMTP_HOST")
|
||||||
|
}
|
||||||
|
|
||||||
|
if constants.EnvData.SMTP_PORT == "" {
|
||||||
|
constants.EnvData.SMTP_PORT = os.Getenv("SMTP_PORT")
|
||||||
|
}
|
||||||
|
|
||||||
|
if constants.EnvData.SENDER_EMAIL == "" {
|
||||||
|
constants.EnvData.SENDER_EMAIL = os.Getenv("SENDER_EMAIL")
|
||||||
|
}
|
||||||
|
|
||||||
|
if constants.EnvData.SENDER_PASSWORD == "" {
|
||||||
|
constants.EnvData.SENDER_PASSWORD = os.Getenv("SENDER_PASSWORD")
|
||||||
|
}
|
||||||
|
|
||||||
|
if constants.EnvData.JWT_SECRET == "" {
|
||||||
|
constants.EnvData.JWT_SECRET = os.Getenv("JWT_SECRET")
|
||||||
|
if constants.EnvData.JWT_SECRET == "" {
|
||||||
|
constants.EnvData.JWT_SECRET = uuid.New().String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if constants.EnvData.JWT_TYPE == "" {
|
||||||
|
constants.EnvData.JWT_TYPE = os.Getenv("JWT_TYPE")
|
||||||
|
if constants.EnvData.JWT_TYPE == "" {
|
||||||
|
constants.EnvData.JWT_TYPE = "HS256"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if constants.EnvData.JWT_ROLE_CLAIM == "" {
|
||||||
|
constants.EnvData.JWT_ROLE_CLAIM = os.Getenv("JWT_ROLE_CLAIM")
|
||||||
|
|
||||||
|
if constants.EnvData.JWT_ROLE_CLAIM == "" {
|
||||||
|
constants.EnvData.JWT_ROLE_CLAIM = "role"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if constants.EnvData.AUTHORIZER_URL == "" {
|
||||||
|
constants.EnvData.AUTHORIZER_URL = strings.TrimSuffix(os.Getenv("AUTHORIZER_URL"), "/")
|
||||||
|
|
||||||
if ARG_AUTHORIZER_URL != nil && *ARG_AUTHORIZER_URL != "" {
|
if ARG_AUTHORIZER_URL != nil && *ARG_AUTHORIZER_URL != "" {
|
||||||
constants.AUTHORIZER_URL = *ARG_AUTHORIZER_URL
|
constants.EnvData.AUTHORIZER_URL = *ARG_AUTHORIZER_URL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.PORT == "" {
|
if constants.EnvData.PORT == "" {
|
||||||
constants.PORT = os.Getenv("PORT")
|
constants.EnvData.PORT = os.Getenv("PORT")
|
||||||
if constants.PORT == "" {
|
if constants.EnvData.PORT == "" {
|
||||||
constants.PORT = "8080"
|
constants.EnvData.PORT = "8080"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.REDIS_URL == "" {
|
if constants.EnvData.REDIS_URL == "" {
|
||||||
constants.REDIS_URL = os.Getenv("REDIS_URL")
|
constants.EnvData.REDIS_URL = os.Getenv("REDIS_URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.COOKIE_NAME == "" {
|
if constants.EnvData.COOKIE_NAME == "" {
|
||||||
constants.COOKIE_NAME = os.Getenv("COOKIE_NAME")
|
constants.EnvData.COOKIE_NAME = os.Getenv("COOKIE_NAME")
|
||||||
|
if constants.EnvData.COOKIE_NAME == "" {
|
||||||
|
constants.EnvData.COOKIE_NAME = "authorizer"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.GOOGLE_CLIENT_ID == "" {
|
if constants.EnvData.GOOGLE_CLIENT_ID == "" {
|
||||||
constants.GOOGLE_CLIENT_ID = os.Getenv("GOOGLE_CLIENT_ID")
|
constants.EnvData.GOOGLE_CLIENT_ID = os.Getenv("GOOGLE_CLIENT_ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.GOOGLE_CLIENT_SECRET == "" {
|
if constants.EnvData.GOOGLE_CLIENT_SECRET == "" {
|
||||||
constants.GOOGLE_CLIENT_SECRET = os.Getenv("GOOGLE_CLIENT_SECRET")
|
constants.EnvData.GOOGLE_CLIENT_SECRET = os.Getenv("GOOGLE_CLIENT_SECRET")
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.GITHUB_CLIENT_ID == "" {
|
if constants.EnvData.GITHUB_CLIENT_ID == "" {
|
||||||
constants.GITHUB_CLIENT_ID = os.Getenv("GITHUB_CLIENT_ID")
|
constants.EnvData.GITHUB_CLIENT_ID = os.Getenv("GITHUB_CLIENT_ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.GITHUB_CLIENT_SECRET == "" {
|
if constants.EnvData.GITHUB_CLIENT_SECRET == "" {
|
||||||
constants.GITHUB_CLIENT_SECRET = os.Getenv("GITHUB_CLIENT_SECRET")
|
constants.EnvData.GITHUB_CLIENT_SECRET = os.Getenv("GITHUB_CLIENT_SECRET")
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.FACEBOOK_CLIENT_ID == "" {
|
if constants.EnvData.FACEBOOK_CLIENT_ID == "" {
|
||||||
constants.FACEBOOK_CLIENT_ID = os.Getenv("FACEBOOK_CLIENT_ID")
|
constants.EnvData.FACEBOOK_CLIENT_ID = os.Getenv("FACEBOOK_CLIENT_ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.FACEBOOK_CLIENT_SECRET == "" {
|
if constants.EnvData.FACEBOOK_CLIENT_SECRET == "" {
|
||||||
constants.FACEBOOK_CLIENT_SECRET = os.Getenv("FACEBOOK_CLIENT_SECRET")
|
constants.EnvData.FACEBOOK_CLIENT_SECRET = os.Getenv("FACEBOOK_CLIENT_SECRET")
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.RESET_PASSWORD_URL == "" {
|
if constants.EnvData.RESET_PASSWORD_URL == "" {
|
||||||
constants.RESET_PASSWORD_URL = strings.TrimPrefix(os.Getenv("RESET_PASSWORD_URL"), "/")
|
constants.EnvData.RESET_PASSWORD_URL = strings.TrimPrefix(os.Getenv("RESET_PASSWORD_URL"), "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
constants.DISABLE_BASIC_AUTHENTICATION = os.Getenv("DISABLE_BASIC_AUTHENTICATION") == "true"
|
constants.EnvData.DISABLE_BASIC_AUTHENTICATION = os.Getenv("DISABLE_BASIC_AUTHENTICATION") == "true"
|
||||||
constants.DISABLE_EMAIL_VERIFICATION = os.Getenv("DISABLE_EMAIL_VERIFICATION") == "true"
|
constants.EnvData.DISABLE_EMAIL_VERIFICATION = os.Getenv("DISABLE_EMAIL_VERIFICATION") == "true"
|
||||||
constants.DISABLE_MAGIC_LINK_LOGIN = os.Getenv("DISABLE_MAGIC_LINK_LOGIN") == "true"
|
constants.EnvData.DISABLE_MAGIC_LINK_LOGIN = os.Getenv("DISABLE_MAGIC_LINK_LOGIN") == "true"
|
||||||
constants.DISABLE_LOGIN_PAGE = os.Getenv("DISABLE_LOGIN_PAGE") == "true"
|
constants.EnvData.DISABLE_LOGIN_PAGE = os.Getenv("DISABLE_LOGIN_PAGE") == "true"
|
||||||
|
|
||||||
if constants.SMTP_HOST == "" || constants.SENDER_EMAIL == "" || constants.SENDER_PASSWORD == "" {
|
if constants.EnvData.SMTP_HOST == "" || constants.EnvData.SENDER_EMAIL == "" || constants.EnvData.SENDER_PASSWORD == "" {
|
||||||
constants.DISABLE_EMAIL_VERIFICATION = true
|
constants.EnvData.DISABLE_EMAIL_VERIFICATION = true
|
||||||
constants.DISABLE_MAGIC_LINK_LOGIN = true
|
constants.EnvData.DISABLE_MAGIC_LINK_LOGIN = true
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedOriginsSplit := strings.Split(os.Getenv("ALLOWED_ORIGINS"), ",")
|
allowedOriginsSplit := strings.Split(os.Getenv("ALLOWED_ORIGINS"), ",")
|
||||||
|
@ -205,18 +212,10 @@ func InitEnv() {
|
||||||
allowedOrigins = []string{"*"}
|
allowedOrigins = []string{"*"}
|
||||||
}
|
}
|
||||||
|
|
||||||
constants.ALLOWED_ORIGINS = allowedOrigins
|
constants.EnvData.ALLOWED_ORIGINS = allowedOrigins
|
||||||
|
|
||||||
if constants.JWT_TYPE == "" {
|
if constants.EnvData.DISABLE_EMAIL_VERIFICATION {
|
||||||
constants.JWT_TYPE = "HS256"
|
constants.EnvData.DISABLE_MAGIC_LINK_LOGIN = true
|
||||||
}
|
|
||||||
|
|
||||||
if constants.COOKIE_NAME == "" {
|
|
||||||
constants.COOKIE_NAME = "authorizer"
|
|
||||||
}
|
|
||||||
|
|
||||||
if constants.DISABLE_EMAIL_VERIFICATION {
|
|
||||||
constants.DISABLE_MAGIC_LINK_LOGIN = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rolesEnv := strings.TrimSpace(os.Getenv("ROLES"))
|
rolesEnv := strings.TrimSpace(os.Getenv("ROLES"))
|
||||||
|
@ -256,19 +255,19 @@ func InitEnv() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(roles) > 0 && len(defaultRoles) == 0 && len(defaultRoleSplit) > 0 {
|
if len(roles) > 0 && len(defaultRoles) == 0 && len(defaultRolesEnv) > 0 {
|
||||||
panic(`Invalid DEFAULT_ROLE environment variable. It can be one from give ROLES environment variable value`)
|
panic(`Invalid DEFAULT_ROLE environment variable. It can be one from give ROLES environment variable value`)
|
||||||
}
|
}
|
||||||
|
|
||||||
constants.ROLES = roles
|
constants.EnvData.ROLES = roles
|
||||||
constants.DEFAULT_ROLES = defaultRoles
|
constants.EnvData.DEFAULT_ROLES = defaultRoles
|
||||||
constants.PROTECTED_ROLES = protectedRoles
|
constants.EnvData.PROTECTED_ROLES = protectedRoles
|
||||||
|
|
||||||
if os.Getenv("ORGANIZATION_NAME") != "" {
|
if os.Getenv("ORGANIZATION_NAME") != "" {
|
||||||
constants.ORGANIZATION_NAME = os.Getenv("ORGANIZATION_NAME")
|
constants.EnvData.ORGANIZATION_NAME = os.Getenv("ORGANIZATION_NAME")
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.Getenv("ORGANIZATION_LOGO") != "" {
|
if os.Getenv("ORGANIZATION_LOGO") != "" {
|
||||||
constants.ORGANIZATION_LOGO = os.Getenv("ORGANIZATION_LOGO")
|
constants.EnvData.ORGANIZATION_LOGO = os.Getenv("ORGANIZATION_LOGO")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
155
server/env/persist_env.go
vendored
Normal file
155
server/env/persist_env.go
vendored
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
package env
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PersistEnv() error {
|
||||||
|
config, err := db.Mgr.GetConfig()
|
||||||
|
// config not found in db
|
||||||
|
if err != nil {
|
||||||
|
// AES encryption needs 32 bit key only, so we chop off last 4 characters from 36 bit uuid
|
||||||
|
hash := uuid.New().String()[:36-4]
|
||||||
|
constants.EnvData.ENCRYPTION_KEY = hash
|
||||||
|
encodedHash := utils.EncryptB64(hash)
|
||||||
|
|
||||||
|
configData, err := json.Marshal(constants.EnvData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
encryptedConfig, err := utils.EncryptAES(configData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
config = db.Config{
|
||||||
|
Hash: encodedHash,
|
||||||
|
Config: encryptedConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
db.Mgr.AddConfig(config)
|
||||||
|
} else {
|
||||||
|
// decrypt the config data from db
|
||||||
|
// decryption can be done using the hash stored in db
|
||||||
|
encryptionKey := config.Hash
|
||||||
|
decryptedEncryptionKey, err := utils.DecryptB64(encryptionKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
constants.EnvData.ENCRYPTION_KEY = decryptedEncryptionKey
|
||||||
|
decryptedConfigs, err := utils.DecryptAES(config.Config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// temp json to validate with env
|
||||||
|
var jsonData map[string]interface{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(decryptedConfigs, &jsonData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("=> persisted data:", jsonData)
|
||||||
|
|
||||||
|
// if env is changed via env file or OS env
|
||||||
|
// give that higher preference and update db, but we don't recommend it
|
||||||
|
|
||||||
|
hasChanged := false
|
||||||
|
|
||||||
|
for key, value := range jsonData {
|
||||||
|
fieldType := reflect.TypeOf(value).String()
|
||||||
|
|
||||||
|
// check only for derivative keys
|
||||||
|
// No need to check for ENCRYPTION_KEY which special key we use for encrypting config data
|
||||||
|
// as we have removed it from json
|
||||||
|
envValue := strings.TrimSpace(os.Getenv(key))
|
||||||
|
|
||||||
|
// env is not empty
|
||||||
|
if envValue != "" {
|
||||||
|
// check the type
|
||||||
|
// currently we have 3 types of env vars: string, bool, []string{}
|
||||||
|
if fieldType == "string" {
|
||||||
|
if value != envValue {
|
||||||
|
jsonData[key] = envValue
|
||||||
|
hasChanged = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if fieldType == "bool" {
|
||||||
|
newValue := envValue == "true"
|
||||||
|
if value != newValue {
|
||||||
|
jsonData[key] = newValue
|
||||||
|
hasChanged = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if fieldType == "[]interface {}" {
|
||||||
|
stringArr := []string{}
|
||||||
|
envStringArr := strings.Split(envValue, ",")
|
||||||
|
for _, v := range value.([]interface{}) {
|
||||||
|
stringArr = append(stringArr, v.(string))
|
||||||
|
}
|
||||||
|
if !utils.IsStringArrayEqual(stringArr, envStringArr) {
|
||||||
|
jsonData[key] = envStringArr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle derivative cases like disabling email verification & magic login
|
||||||
|
// in case SMTP is off but env is set to true
|
||||||
|
if jsonData["SMTP_HOST"] == "" || jsonData["SENDER_EMAIL"] == "" || jsonData["SENDER_PASSWORD"] == "" {
|
||||||
|
if !jsonData["DISABLE_EMAIL_VERIFICATION"].(bool) {
|
||||||
|
jsonData["DISABLE_EMAIL_VERIFICATION"] = true
|
||||||
|
hasChanged = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !jsonData["DISABLE_MAGIC_LINK_LOGIN"].(bool) {
|
||||||
|
jsonData["DISABLE_MAGIC_LINK_LOGIN"] = true
|
||||||
|
hasChanged = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("has changed:", hasChanged)
|
||||||
|
if hasChanged {
|
||||||
|
jsonBytes, err := json.Marshal(jsonData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(jsonBytes, &constants.EnvData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
configData, err := json.Marshal(constants.EnvData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
encryptedConfig, err := utils.EncryptAES(configData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Config = encryptedConfig
|
||||||
|
_, err = db.Mgr.UpdateConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error updating config:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -30,17 +29,17 @@ func AppHandler() gin.HandlerFunc {
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
|
||||||
stateObj.AuthorizerURL = constants.AUTHORIZER_URL
|
stateObj.AuthorizerURL = constants.EnvData.AUTHORIZER_URL
|
||||||
stateObj.RedirectURL = constants.AUTHORIZER_URL + "/app"
|
stateObj.RedirectURL = constants.EnvData.AUTHORIZER_URL + "/app"
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
decodedState, err := base64.StdEncoding.DecodeString(state)
|
decodedState, err := utils.DecryptB64(state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(400, gin.H{"error": "[unable to decode state] invalid state"})
|
c.JSON(400, gin.H{"error": "[unable to decode state] invalid state"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(decodedState, &stateObj)
|
err = json.Unmarshal([]byte(decodedState), &stateObj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(400, gin.H{"error": "[unable to parse state] invalid state"})
|
c.JSON(400, gin.H{"error": "[unable to parse state] invalid state"})
|
||||||
return
|
return
|
||||||
|
@ -60,7 +59,7 @@ func AppHandler() gin.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate host and domain of authorizer url
|
// validate host and domain of authorizer url
|
||||||
if strings.TrimSuffix(stateObj.AuthorizerURL, "/") != constants.AUTHORIZER_URL {
|
if strings.TrimSuffix(stateObj.AuthorizerURL, "/") != constants.EnvData.AUTHORIZER_URL {
|
||||||
c.JSON(400, gin.H{"error": "invalid host url"})
|
c.JSON(400, gin.H{"error": "invalid host url"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -77,8 +76,8 @@ func AppHandler() gin.HandlerFunc {
|
||||||
"data": map[string]string{
|
"data": map[string]string{
|
||||||
"authorizerURL": stateObj.AuthorizerURL,
|
"authorizerURL": stateObj.AuthorizerURL,
|
||||||
"redirectURL": stateObj.RedirectURL,
|
"redirectURL": stateObj.RedirectURL,
|
||||||
"organizationName": constants.ORGANIZATION_NAME,
|
"organizationName": constants.EnvData.ORGANIZATION_NAME,
|
||||||
"organizationLogo": constants.ORGANIZATION_LOGO,
|
"organizationLogo": constants.EnvData.ORGANIZATION_LOGO,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
func DashboardHandler() gin.HandlerFunc {
|
func DashboardHandler() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
isOnboardingCompleted := false
|
isOnboardingCompleted := false
|
||||||
if constants.ADMIN_SECRET != "" && constants.DATABASE_TYPE != "" && constants.DATABASE_URL != "" {
|
if constants.EnvData.ADMIN_SECRET != "" && constants.EnvData.DATABASE_TYPE != "" && constants.EnvData.DATABASE_URL != "" {
|
||||||
isOnboardingCompleted = true
|
isOnboardingCompleted = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -195,7 +195,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
||||||
// make sure inputRoles don't include protected roles
|
// make sure inputRoles don't include protected roles
|
||||||
hasProtectedRole := false
|
hasProtectedRole := false
|
||||||
for _, ir := range inputRoles {
|
for _, ir := range inputRoles {
|
||||||
if utils.StringSliceContains(constants.PROTECTED_ROLES, ir) {
|
if utils.StringSliceContains(constants.EnvData.PROTECTED_ROLES, ir) {
|
||||||
hasProtectedRole = true
|
hasProtectedRole = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
||||||
// check if it contains protected unassigned role
|
// check if it contains protected unassigned role
|
||||||
hasProtectedRole := false
|
hasProtectedRole := false
|
||||||
for _, ur := range unasignedRoles {
|
for _, ur := range unasignedRoles {
|
||||||
if utils.StringSliceContains(constants.PROTECTED_ROLES, ur) {
|
if utils.StringSliceContains(constants.EnvData.PROTECTED_ROLES, ur) {
|
||||||
hasProtectedRole = true
|
hasProtectedRole = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,14 +34,14 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
||||||
|
|
||||||
// use protected roles verification for admin login only.
|
// use protected roles verification for admin login only.
|
||||||
// though if not associated with user, it will be rejected from oauth_callback
|
// though if not associated with user, it will be rejected from oauth_callback
|
||||||
if !utils.IsValidRoles(append([]string{}, append(constants.ROLES, constants.PROTECTED_ROLES...)...), rolesSplit) {
|
if !utils.IsValidRoles(append([]string{}, append(constants.EnvData.ROLES, constants.EnvData.PROTECTED_ROLES...)...), rolesSplit) {
|
||||||
c.JSON(400, gin.H{
|
c.JSON(400, gin.H{
|
||||||
"error": "invalid role",
|
"error": "invalid role",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
roles = strings.Join(constants.DEFAULT_ROLES, ",")
|
roles = strings.Join(constants.EnvData.DEFAULT_ROLES, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
uuid := uuid.New()
|
uuid := uuid.New()
|
||||||
|
@ -57,7 +57,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
||||||
}
|
}
|
||||||
session.SetSocailLoginState(oauthStateString, enum.Google.String())
|
session.SetSocailLoginState(oauthStateString, enum.Google.String())
|
||||||
// during the init of OAuthProvider authorizer url might be empty
|
// during the init of OAuthProvider authorizer url might be empty
|
||||||
oauth.OAuthProviders.GoogleConfig.RedirectURL = constants.AUTHORIZER_URL + "/oauth_callback/google"
|
oauth.OAuthProviders.GoogleConfig.RedirectURL = constants.EnvData.AUTHORIZER_URL + "/oauth_callback/google"
|
||||||
url := oauth.OAuthProviders.GoogleConfig.AuthCodeURL(oauthStateString)
|
url := oauth.OAuthProviders.GoogleConfig.AuthCodeURL(oauthStateString)
|
||||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||||
case enum.Github.String():
|
case enum.Github.String():
|
||||||
|
@ -66,7 +66,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
session.SetSocailLoginState(oauthStateString, enum.Github.String())
|
session.SetSocailLoginState(oauthStateString, enum.Github.String())
|
||||||
oauth.OAuthProviders.GithubConfig.RedirectURL = constants.AUTHORIZER_URL + "/oauth_callback/github"
|
oauth.OAuthProviders.GithubConfig.RedirectURL = constants.EnvData.AUTHORIZER_URL + "/oauth_callback/github"
|
||||||
url := oauth.OAuthProviders.GithubConfig.AuthCodeURL(oauthStateString)
|
url := oauth.OAuthProviders.GithubConfig.AuthCodeURL(oauthStateString)
|
||||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||||
case enum.Facebook.String():
|
case enum.Facebook.String():
|
||||||
|
@ -75,7 +75,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
session.SetSocailLoginState(oauthStateString, enum.Facebook.String())
|
session.SetSocailLoginState(oauthStateString, enum.Facebook.String())
|
||||||
oauth.OAuthProviders.FacebookConfig.RedirectURL = constants.AUTHORIZER_URL + "/oauth_callback/facebook"
|
oauth.OAuthProviders.FacebookConfig.RedirectURL = constants.EnvData.AUTHORIZER_URL + "/oauth_callback/facebook"
|
||||||
url := oauth.OAuthProviders.FacebookConfig.AuthCodeURL(oauthStateString)
|
url := oauth.OAuthProviders.FacebookConfig.AuthCodeURL(oauthStateString)
|
||||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -22,10 +22,12 @@ func main() {
|
||||||
env.ARG_ENV_FILE = flag.String("env_file", "", "Env file path")
|
env.ARG_ENV_FILE = flag.String("env_file", "", "Env file path")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
constants.VERSION = VERSION
|
constants.EnvData.VERSION = VERSION
|
||||||
|
|
||||||
env.InitEnv()
|
env.InitEnv()
|
||||||
db.InitDB()
|
db.InitDB()
|
||||||
|
env.PersistEnv()
|
||||||
|
|
||||||
session.InitSession()
|
session.InitSession()
|
||||||
oauth.InitOAuth()
|
oauth.InitOAuth()
|
||||||
utils.InitServer()
|
utils.InitServer()
|
||||||
|
@ -35,7 +37,7 @@ func main() {
|
||||||
router.LoadHTMLGlob("templates/*")
|
router.LoadHTMLGlob("templates/*")
|
||||||
// login page app related routes.
|
// login page app related routes.
|
||||||
// if we put them in router file then tests would fail as templates or build path will be different
|
// if we put them in router file then tests would fail as templates or build path will be different
|
||||||
if !constants.DISABLE_LOGIN_PAGE {
|
if !constants.EnvData.DISABLE_LOGIN_PAGE {
|
||||||
app := router.Group("/app")
|
app := router.Group("/app")
|
||||||
{
|
{
|
||||||
app.Static("/build", "app/build")
|
app.Static("/build", "app/build")
|
||||||
|
@ -50,5 +52,5 @@ func main() {
|
||||||
app.GET("/", handlers.DashboardHandler())
|
app.GET("/", handlers.DashboardHandler())
|
||||||
}
|
}
|
||||||
|
|
||||||
router.Run(":" + constants.PORT)
|
router.Run(":" + constants.EnvData.PORT)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,10 @@ import (
|
||||||
|
|
||||||
func GinContextToContextMiddleware() gin.HandlerFunc {
|
func GinContextToContextMiddleware() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
if constants.AUTHORIZER_URL == "" {
|
if constants.EnvData.AUTHORIZER_URL == "" {
|
||||||
url := location.Get(c)
|
url := location.Get(c)
|
||||||
constants.AUTHORIZER_URL = url.Scheme + "://" + c.Request.Host
|
constants.EnvData.AUTHORIZER_URL = url.Scheme + "://" + c.Request.Host
|
||||||
log.Println("authorizer url:", constants.AUTHORIZER_URL)
|
log.Println("authorizer url:", constants.EnvData.AUTHORIZER_URL)
|
||||||
}
|
}
|
||||||
ctx := context.WithValue(c.Request.Context(), "GinContextKey", c)
|
ctx := context.WithValue(c.Request.Context(), "GinContextKey", c)
|
||||||
c.Request = c.Request.WithContext(ctx)
|
c.Request = c.Request.WithContext(ctx)
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
func CORSMiddleware() gin.HandlerFunc {
|
func CORSMiddleware() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
origin := c.Request.Header.Get("Origin")
|
origin := c.Request.Header.Get("Origin")
|
||||||
constants.APP_URL = origin
|
constants.EnvData.APP_URL = origin
|
||||||
|
|
||||||
if utils.IsValidOrigin(origin) {
|
if utils.IsValidOrigin(origin) {
|
||||||
c.Writer.Header().Set("Access-Control-Allow-Origin", origin)
|
c.Writer.Header().Set("Access-Control-Allow-Origin", origin)
|
||||||
|
|
|
@ -28,33 +28,33 @@ var (
|
||||||
|
|
||||||
func InitOAuth() {
|
func InitOAuth() {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
if constants.GOOGLE_CLIENT_ID != "" && constants.GOOGLE_CLIENT_SECRET != "" {
|
if constants.EnvData.GOOGLE_CLIENT_ID != "" && constants.EnvData.GOOGLE_CLIENT_SECRET != "" {
|
||||||
p, err := oidc.NewProvider(ctx, "https://accounts.google.com")
|
p, err := oidc.NewProvider(ctx, "https://accounts.google.com")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("error creating oidc provider for google:", err)
|
log.Fatalln("error creating oidc provider for google:", err)
|
||||||
}
|
}
|
||||||
OIDCProviders.GoogleOIDC = p
|
OIDCProviders.GoogleOIDC = p
|
||||||
OAuthProviders.GoogleConfig = &oauth2.Config{
|
OAuthProviders.GoogleConfig = &oauth2.Config{
|
||||||
ClientID: constants.GOOGLE_CLIENT_ID,
|
ClientID: constants.EnvData.GOOGLE_CLIENT_ID,
|
||||||
ClientSecret: constants.GOOGLE_CLIENT_SECRET,
|
ClientSecret: constants.EnvData.GOOGLE_CLIENT_SECRET,
|
||||||
RedirectURL: constants.AUTHORIZER_URL + "/oauth_callback/google",
|
RedirectURL: constants.EnvData.AUTHORIZER_URL + "/oauth_callback/google",
|
||||||
Endpoint: OIDCProviders.GoogleOIDC.Endpoint(),
|
Endpoint: OIDCProviders.GoogleOIDC.Endpoint(),
|
||||||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if constants.GITHUB_CLIENT_ID != "" && constants.GITHUB_CLIENT_SECRET != "" {
|
if constants.EnvData.GITHUB_CLIENT_ID != "" && constants.EnvData.GITHUB_CLIENT_SECRET != "" {
|
||||||
OAuthProviders.GithubConfig = &oauth2.Config{
|
OAuthProviders.GithubConfig = &oauth2.Config{
|
||||||
ClientID: constants.GITHUB_CLIENT_ID,
|
ClientID: constants.EnvData.GITHUB_CLIENT_ID,
|
||||||
ClientSecret: constants.GITHUB_CLIENT_SECRET,
|
ClientSecret: constants.EnvData.GITHUB_CLIENT_SECRET,
|
||||||
RedirectURL: constants.AUTHORIZER_URL + "/oauth_callback/github",
|
RedirectURL: constants.EnvData.AUTHORIZER_URL + "/oauth_callback/github",
|
||||||
Endpoint: githubOAuth2.Endpoint,
|
Endpoint: githubOAuth2.Endpoint,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if constants.FACEBOOK_CLIENT_ID != "" && constants.FACEBOOK_CLIENT_SECRET != "" {
|
if constants.EnvData.FACEBOOK_CLIENT_ID != "" && constants.EnvData.FACEBOOK_CLIENT_SECRET != "" {
|
||||||
OAuthProviders.FacebookConfig = &oauth2.Config{
|
OAuthProviders.FacebookConfig = &oauth2.Config{
|
||||||
ClientID: constants.FACEBOOK_CLIENT_ID,
|
ClientID: constants.EnvData.FACEBOOK_CLIENT_ID,
|
||||||
ClientSecret: constants.FACEBOOK_CLIENT_SECRET,
|
ClientSecret: constants.EnvData.FACEBOOK_CLIENT_SECRET,
|
||||||
RedirectURL: constants.AUTHORIZER_URL + "/oauth_callback/facebook",
|
RedirectURL: constants.EnvData.AUTHORIZER_URL + "/oauth_callback/facebook",
|
||||||
Endpoint: facebookOAuth2.Endpoint,
|
Endpoint: facebookOAuth2.Endpoint,
|
||||||
Scopes: []string{"public_profile", "email"},
|
Scopes: []string{"public_profile", "email"},
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ func AdminLoginResolver(ctx context.Context, params model.AdminLoginInput) (*mod
|
||||||
log.Println("=> error:", err)
|
log.Println("=> error:", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
if params.AdminSecret != constants.ADMIN_SECRET {
|
if params.AdminSecret != constants.EnvData.ADMIN_SECRET {
|
||||||
return nil, fmt.Errorf(`invalid admin secret`)
|
return nil, fmt.Errorf(`invalid admin secret`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ func ForgotPassword(ctx context.Context, params model.ForgotPasswordInput) (*mod
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
if constants.DISABLE_BASIC_AUTHENTICATION {
|
if constants.EnvData.DISABLE_BASIC_AUTHENTICATION {
|
||||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||||
}
|
}
|
||||||
host := gc.Request.Host
|
host := gc.Request.Host
|
||||||
|
|
|
@ -22,7 +22,7 @@ func Login(ctx context.Context, params model.LoginInput) (*model.AuthResponse, e
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.DISABLE_BASIC_AUTHENTICATION {
|
if constants.EnvData.DISABLE_BASIC_AUTHENTICATION {
|
||||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ func Login(ctx context.Context, params model.LoginInput) (*model.AuthResponse, e
|
||||||
log.Println("compare password error:", err)
|
log.Println("compare password error:", err)
|
||||||
return res, fmt.Errorf(`invalid password`)
|
return res, fmt.Errorf(`invalid password`)
|
||||||
}
|
}
|
||||||
roles := constants.DEFAULT_ROLES
|
roles := constants.EnvData.DEFAULT_ROLES
|
||||||
currentRoles := strings.Split(user.Roles, ",")
|
currentRoles := strings.Split(user.Roles, ",")
|
||||||
if len(params.Roles) > 0 {
|
if len(params.Roles) > 0 {
|
||||||
if !utils.IsValidRoles(currentRoles, params.Roles) {
|
if !utils.IsValidRoles(currentRoles, params.Roles) {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
func MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error) {
|
func MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error) {
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
|
|
||||||
if constants.DISABLE_MAGIC_LINK_LOGIN {
|
if constants.EnvData.DISABLE_MAGIC_LINK_LOGIN {
|
||||||
return res, fmt.Errorf(`magic link login is disabled for this instance`)
|
return res, fmt.Errorf(`magic link login is disabled for this instance`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,13 +41,13 @@ func MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*mod
|
||||||
// define roles for new user
|
// define roles for new user
|
||||||
if len(params.Roles) > 0 {
|
if len(params.Roles) > 0 {
|
||||||
// check if roles exists
|
// check if roles exists
|
||||||
if !utils.IsValidRoles(constants.ROLES, params.Roles) {
|
if !utils.IsValidRoles(constants.EnvData.ROLES, params.Roles) {
|
||||||
return res, fmt.Errorf(`invalid roles`)
|
return res, fmt.Errorf(`invalid roles`)
|
||||||
} else {
|
} else {
|
||||||
inputRoles = params.Roles
|
inputRoles = params.Roles
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
inputRoles = constants.DEFAULT_ROLES
|
inputRoles = constants.EnvData.DEFAULT_ROLES
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Roles = strings.Join(inputRoles, ",")
|
user.Roles = strings.Join(inputRoles, ",")
|
||||||
|
@ -72,7 +72,7 @@ func MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*mod
|
||||||
// check if it contains protected unassigned role
|
// check if it contains protected unassigned role
|
||||||
hasProtectedRole := false
|
hasProtectedRole := false
|
||||||
for _, ur := range unasignedRoles {
|
for _, ur := range unasignedRoles {
|
||||||
if utils.StringSliceContains(constants.PROTECTED_ROLES, ur) {
|
if utils.StringSliceContains(constants.EnvData.PROTECTED_ROLES, ur) {
|
||||||
hasProtectedRole = true
|
hasProtectedRole = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ func MagicLinkLogin(ctx context.Context, params model.MagicLinkLoginInput) (*mod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !constants.DISABLE_EMAIL_VERIFICATION {
|
if !constants.EnvData.DISABLE_EMAIL_VERIFICATION {
|
||||||
// insert verification request
|
// insert verification request
|
||||||
verificationType := enum.MagicLinkLogin.String()
|
verificationType := enum.MagicLinkLogin.String()
|
||||||
token, err := utils.CreateVerificationToken(params.Email, verificationType)
|
token, err := utils.CreateVerificationToken(params.Email, verificationType)
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
func ResetPassword(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error) {
|
func ResetPassword(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error) {
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
if constants.DISABLE_BASIC_AUTHENTICATION {
|
if constants.EnvData.DISABLE_BASIC_AUTHENTICATION {
|
||||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ func Session(ctx context.Context, roles []string) (*model.AuthResponse, error) {
|
||||||
expiresTimeObj := time.Unix(expiresAt, 0)
|
expiresTimeObj := time.Unix(expiresAt, 0)
|
||||||
currentTimeObj := time.Now()
|
currentTimeObj := time.Now()
|
||||||
|
|
||||||
claimRoleInterface := claim[constants.JWT_ROLE_CLAIM].([]interface{})
|
claimRoleInterface := claim[constants.EnvData.JWT_ROLE_CLAIM].([]interface{})
|
||||||
claimRoles := make([]string, len(claimRoleInterface))
|
claimRoles := make([]string, len(claimRoleInterface))
|
||||||
for i, v := range claimRoleInterface {
|
for i, v := range claimRoleInterface {
|
||||||
claimRoles[i] = v.(string)
|
claimRoles[i] = v.(string)
|
||||||
|
|
|
@ -22,7 +22,7 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse,
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.DISABLE_BASIC_AUTHENTICATION {
|
if constants.EnvData.DISABLE_BASIC_AUTHENTICATION {
|
||||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||||
}
|
}
|
||||||
if params.ConfirmPassword != params.Password {
|
if params.ConfirmPassword != params.Password {
|
||||||
|
@ -52,13 +52,13 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse,
|
||||||
|
|
||||||
if len(params.Roles) > 0 {
|
if len(params.Roles) > 0 {
|
||||||
// check if roles exists
|
// check if roles exists
|
||||||
if !utils.IsValidRoles(constants.ROLES, params.Roles) {
|
if !utils.IsValidRoles(constants.EnvData.ROLES, params.Roles) {
|
||||||
return res, fmt.Errorf(`invalid roles`)
|
return res, fmt.Errorf(`invalid roles`)
|
||||||
} else {
|
} else {
|
||||||
inputRoles = params.Roles
|
inputRoles = params.Roles
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
inputRoles = constants.DEFAULT_ROLES
|
inputRoles = constants.EnvData.DEFAULT_ROLES
|
||||||
}
|
}
|
||||||
|
|
||||||
user := db.User{
|
user := db.User{
|
||||||
|
@ -103,7 +103,7 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse,
|
||||||
}
|
}
|
||||||
|
|
||||||
user.SignupMethods = enum.BasicAuth.String()
|
user.SignupMethods = enum.BasicAuth.String()
|
||||||
if constants.DISABLE_EMAIL_VERIFICATION {
|
if constants.EnvData.DISABLE_EMAIL_VERIFICATION {
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
user.EmailVerifiedAt = &now
|
user.EmailVerifiedAt = &now
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse,
|
||||||
roles := strings.Split(user.Roles, ",")
|
roles := strings.Split(user.Roles, ",")
|
||||||
userToReturn := utils.GetResponseUserData(user)
|
userToReturn := utils.GetResponseUserData(user)
|
||||||
|
|
||||||
if !constants.DISABLE_EMAIL_VERIFICATION {
|
if !constants.EnvData.DISABLE_EMAIL_VERIFICATION {
|
||||||
// insert verification request
|
// insert verification request
|
||||||
verificationType := enum.BasicAuthSignup.String()
|
verificationType := enum.BasicAuthSignup.String()
|
||||||
token, err := utils.CreateVerificationToken(params.Email, verificationType)
|
token, err := utils.CreateVerificationToken(params.Email, verificationType)
|
||||||
|
|
|
@ -112,7 +112,7 @@ func UpdateUser(ctx context.Context, params model.UpdateUserInput) (*model.User,
|
||||||
inputRoles = append(inputRoles, *item)
|
inputRoles = append(inputRoles, *item)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !utils.IsValidRoles(append([]string{}, append(constants.ROLES, constants.PROTECTED_ROLES...)...), inputRoles) {
|
if !utils.IsValidRoles(append([]string{}, append(constants.EnvData.ROLES, constants.EnvData.PROTECTED_ROLES...)...), inputRoles) {
|
||||||
return res, fmt.Errorf("invalid list of roles")
|
return res, fmt.Errorf("invalid list of roles")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,9 +95,9 @@ func RemoveSocialLoginState(key string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitSession() {
|
func InitSession() {
|
||||||
if constants.REDIS_URL != "" {
|
if constants.EnvData.REDIS_URL != "" {
|
||||||
log.Println("using redis store to save sessions")
|
log.Println("using redis store to save sessions")
|
||||||
opt, err := redis.ParseURL(constants.REDIS_URL)
|
opt, err := redis.ParseURL(constants.EnvData.REDIS_URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Error parsing redis url:", err)
|
log.Fatalln("Error parsing redis url:", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateAuthToken(user db.User, tokenType enum.TokenType, roles []string) (string, int64, error) {
|
func CreateAuthToken(user db.User, tokenType enum.TokenType, roles []string) (string, int64, error) {
|
||||||
t := jwt.New(jwt.GetSigningMethod(constants.JWT_TYPE))
|
t := jwt.New(jwt.GetSigningMethod(constants.EnvData.JWT_TYPE))
|
||||||
expiryBound := time.Hour
|
expiryBound := time.Hour
|
||||||
if tokenType == enum.RefreshToken {
|
if tokenType == enum.RefreshToken {
|
||||||
// expires in 1 year
|
// expires in 1 year
|
||||||
|
@ -36,7 +36,7 @@ func CreateAuthToken(user db.User, tokenType enum.TokenType, roles []string) (st
|
||||||
"iat": time.Now().Unix(),
|
"iat": time.Now().Unix(),
|
||||||
"token_type": tokenType.String(),
|
"token_type": tokenType.String(),
|
||||||
"allowed_roles": strings.Split(user.Roles, ","),
|
"allowed_roles": strings.Split(user.Roles, ","),
|
||||||
constants.JWT_ROLE_CLAIM: roles,
|
constants.EnvData.JWT_ROLE_CLAIM: roles,
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range userMap {
|
for k, v := range userMap {
|
||||||
|
@ -77,7 +77,7 @@ func CreateAuthToken(user db.User, tokenType enum.TokenType, roles []string) (st
|
||||||
|
|
||||||
t.Claims = customClaims
|
t.Claims = customClaims
|
||||||
|
|
||||||
token, err := t.SignedString([]byte(constants.JWT_SECRET))
|
token, err := t.SignedString([]byte(constants.EnvData.JWT_SECRET))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", 0, err
|
return "", 0, err
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,6 @@ func GetAuthToken(gc *gin.Context) (string, error) {
|
||||||
token, err := GetCookie(gc)
|
token, err := GetCookie(gc)
|
||||||
if err != nil || token == "" {
|
if err != nil || token == "" {
|
||||||
// try to check in auth header for cookie
|
// try to check in auth header for cookie
|
||||||
log.Println("cookie not found checking headers")
|
|
||||||
auth := gc.Request.Header.Get("Authorization")
|
auth := gc.Request.Header.Get("Authorization")
|
||||||
if auth == "" {
|
if auth == "" {
|
||||||
return "", fmt.Errorf(`unauthorized`)
|
return "", fmt.Errorf(`unauthorized`)
|
||||||
|
@ -105,7 +104,7 @@ func VerifyAuthToken(token string) (map[string]interface{}, error) {
|
||||||
claims := jwt.MapClaims{}
|
claims := jwt.MapClaims{}
|
||||||
|
|
||||||
_, err := jwt.ParseWithClaims(token, claims, func(token *jwt.Token) (interface{}, error) {
|
_, err := jwt.ParseWithClaims(token, claims, func(token *jwt.Token) (interface{}, error) {
|
||||||
return []byte(constants.JWT_SECRET), nil
|
return []byte(constants.EnvData.JWT_SECRET), nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
|
@ -126,7 +125,7 @@ func VerifyAuthToken(token string) (map[string]interface{}, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateAdminAuthToken(tokenType enum.TokenType, c *gin.Context) (string, int64, error) {
|
func CreateAdminAuthToken(tokenType enum.TokenType, c *gin.Context) (string, int64, error) {
|
||||||
t := jwt.New(jwt.GetSigningMethod(constants.JWT_TYPE))
|
t := jwt.New(jwt.GetSigningMethod(constants.EnvData.JWT_TYPE))
|
||||||
expiryBound := time.Hour
|
expiryBound := time.Hour
|
||||||
if tokenType == enum.RefreshToken {
|
if tokenType == enum.RefreshToken {
|
||||||
// expires in 1 year
|
// expires in 1 year
|
||||||
|
@ -146,9 +145,23 @@ func CreateAdminAuthToken(tokenType enum.TokenType, c *gin.Context) (string, int
|
||||||
|
|
||||||
t.Claims = customClaims
|
t.Claims = customClaims
|
||||||
|
|
||||||
token, err := t.SignedString([]byte(constants.JWT_SECRET))
|
token, err := t.SignedString([]byte(constants.EnvData.JWT_SECRET))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", 0, err
|
return "", 0, err
|
||||||
}
|
}
|
||||||
return token, expiresAt, nil
|
return token, expiresAt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetAdminAuthToken(gc *gin.Context) (string, error) {
|
||||||
|
token, err := GetAdminCookie(gc)
|
||||||
|
if err != nil || token == "" {
|
||||||
|
// try to check in auth header for cookie
|
||||||
|
auth := gc.Request.Header.Get("Authorization")
|
||||||
|
if auth == "" {
|
||||||
|
return "", fmt.Errorf(`unauthorized`)
|
||||||
|
}
|
||||||
|
|
||||||
|
token = strings.TrimPrefix(auth, "Bearer ")
|
||||||
|
}
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
|
|
|
@ -10,21 +10,21 @@ import (
|
||||||
func SetCookie(gc *gin.Context, token string) {
|
func SetCookie(gc *gin.Context, token string) {
|
||||||
secure := true
|
secure := true
|
||||||
httpOnly := true
|
httpOnly := true
|
||||||
host, _ := GetHostParts(constants.AUTHORIZER_URL)
|
host, _ := GetHostParts(constants.EnvData.AUTHORIZER_URL)
|
||||||
domain := GetDomainName(constants.AUTHORIZER_URL)
|
domain := GetDomainName(constants.EnvData.AUTHORIZER_URL)
|
||||||
if domain != "localhost" {
|
if domain != "localhost" {
|
||||||
domain = "." + domain
|
domain = "." + domain
|
||||||
}
|
}
|
||||||
|
|
||||||
gc.SetSameSite(http.SameSiteNoneMode)
|
gc.SetSameSite(http.SameSiteNoneMode)
|
||||||
gc.SetCookie(constants.COOKIE_NAME, token, 3600, "/", host, secure, httpOnly)
|
gc.SetCookie(constants.EnvData.COOKIE_NAME, token, 3600, "/", host, secure, httpOnly)
|
||||||
gc.SetCookie(constants.COOKIE_NAME+"-client", token, 3600, "/", domain, secure, httpOnly)
|
gc.SetCookie(constants.EnvData.COOKIE_NAME+"-client", token, 3600, "/", domain, secure, httpOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCookie(gc *gin.Context) (string, error) {
|
func GetCookie(gc *gin.Context) (string, error) {
|
||||||
cookie, err := gc.Request.Cookie(constants.COOKIE_NAME)
|
cookie, err := gc.Request.Cookie(constants.EnvData.COOKIE_NAME)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cookie, err = gc.Request.Cookie(constants.COOKIE_NAME + "-client")
|
cookie, err = gc.Request.Cookie(constants.EnvData.COOKIE_NAME + "-client")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -37,29 +37,37 @@ func DeleteCookie(gc *gin.Context) {
|
||||||
secure := true
|
secure := true
|
||||||
httpOnly := true
|
httpOnly := true
|
||||||
|
|
||||||
host, _ := GetHostParts(constants.AUTHORIZER_URL)
|
host, _ := GetHostParts(constants.EnvData.AUTHORIZER_URL)
|
||||||
domain := GetDomainName(constants.AUTHORIZER_URL)
|
domain := GetDomainName(constants.EnvData.AUTHORIZER_URL)
|
||||||
if domain != "localhost" {
|
if domain != "localhost" {
|
||||||
domain = "." + domain
|
domain = "." + domain
|
||||||
}
|
}
|
||||||
|
|
||||||
gc.SetSameSite(http.SameSiteNoneMode)
|
gc.SetSameSite(http.SameSiteNoneMode)
|
||||||
gc.SetCookie(constants.COOKIE_NAME, "", -1, "/", host, secure, httpOnly)
|
gc.SetCookie(constants.EnvData.COOKIE_NAME, "", -1, "/", host, secure, httpOnly)
|
||||||
gc.SetCookie(constants.COOKIE_NAME+"-client", "", -1, "/", domain, secure, httpOnly)
|
gc.SetCookie(constants.EnvData.COOKIE_NAME+"-client", "", -1, "/", domain, secure, httpOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetAdminCookie(gc *gin.Context, token string) {
|
func SetAdminCookie(gc *gin.Context, token string) {
|
||||||
secure := true
|
secure := true
|
||||||
httpOnly := true
|
httpOnly := true
|
||||||
host, _ := GetHostParts(constants.AUTHORIZER_URL)
|
host, _ := GetHostParts(constants.EnvData.AUTHORIZER_URL)
|
||||||
|
|
||||||
gc.SetCookie("authorizer-admin", token, 3600, "/", host, secure, httpOnly)
|
gc.SetCookie(constants.EnvData.ADMIN_COOKIE_NAME, token, 3600, "/", host, secure, httpOnly)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAdminCookie(gc *gin.Context) (string, error) {
|
||||||
|
cookie, err := gc.Request.Cookie(constants.EnvData.ADMIN_COOKIE_NAME)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return cookie.Value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteAdminCookie(gc *gin.Context, token string) {
|
func DeleteAdminCookie(gc *gin.Context, token string) {
|
||||||
secure := true
|
secure := true
|
||||||
httpOnly := true
|
httpOnly := true
|
||||||
host, _ := GetHostParts(constants.AUTHORIZER_URL)
|
host, _ := GetHostParts(constants.EnvData.AUTHORIZER_URL)
|
||||||
|
|
||||||
gc.SetCookie("authorizer-admin", "", -1, "/", host, secure, httpOnly)
|
gc.SetCookie(constants.EnvData.ADMIN_COOKIE_NAME, "", -1, "/", host, secure, httpOnly)
|
||||||
}
|
}
|
||||||
|
|
83
server/utils/crypto.go
Normal file
83
server/utils/crypto.go
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
)
|
||||||
|
|
||||||
|
func EncryptB64(text string) string {
|
||||||
|
return base64.StdEncoding.EncodeToString([]byte(text))
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecryptB64(s string) (string, error) {
|
||||||
|
data, err := base64.StdEncoding.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(data), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncryptAES(text []byte) ([]byte, error) {
|
||||||
|
key := []byte(constants.EnvData.ENCRYPTION_KEY)
|
||||||
|
c, err := aes.NewCipher(key)
|
||||||
|
var res []byte
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// gcm or Galois/Counter Mode, is a mode of operation
|
||||||
|
// for symmetric key cryptographic block ciphers
|
||||||
|
// - https://en.wikipedia.org/wiki/Galois/Counter_Mode
|
||||||
|
gcm, err := cipher.NewGCM(c)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates a new byte array the size of the nonce
|
||||||
|
// which must be passed to Seal
|
||||||
|
nonce := make([]byte, gcm.NonceSize())
|
||||||
|
// populates our nonce with a cryptographically secure
|
||||||
|
// random sequence
|
||||||
|
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// here we encrypt our text using the Seal function
|
||||||
|
// Seal encrypts and authenticates plaintext, authenticates the
|
||||||
|
// additional data and appends the result to dst, returning the updated
|
||||||
|
// slice. The nonce must be NonceSize() bytes long and unique for all
|
||||||
|
// time, for a given key.
|
||||||
|
return gcm.Seal(nonce, nonce, text, nil), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecryptAES(ciphertext []byte) ([]byte, error) {
|
||||||
|
key := []byte(constants.EnvData.ENCRYPTION_KEY)
|
||||||
|
c, err := aes.NewCipher(key)
|
||||||
|
var res []byte
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gcm, err := cipher.NewGCM(c)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nonceSize := gcm.NonceSize()
|
||||||
|
if len(ciphertext) < nonceSize {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
|
||||||
|
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return plaintext, nil
|
||||||
|
}
|
|
@ -100,7 +100,7 @@ func SendVerificationMail(toEmail, token string) error {
|
||||||
<div style="position: absolute; left: -9999px; top: -9999px; margin: 0px;"></div>
|
<div style="position: absolute; left: -9999px; top: -9999px; margin: 0px;"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`, constants.ORGANIZATION_LOGO, constants.ORGANIZATION_NAME, constants.AUTHORIZER_URL+"/verify_email"+"?token="+token)
|
`, constants.EnvData.ORGANIZATION_LOGO, constants.EnvData.ORGANIZATION_NAME, constants.EnvData.AUTHORIZER_URL+"/verify_email"+"?token="+token)
|
||||||
bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
||||||
|
|
||||||
return sender.SendMail(Receiver, Subject, bodyMessage)
|
return sender.SendMail(Receiver, Subject, bodyMessage)
|
||||||
|
@ -108,8 +108,8 @@ func SendVerificationMail(toEmail, token string) error {
|
||||||
|
|
||||||
// SendForgotPasswordMail to send verification email
|
// SendForgotPasswordMail to send verification email
|
||||||
func SendForgotPasswordMail(toEmail, token, host string) error {
|
func SendForgotPasswordMail(toEmail, token, host string) error {
|
||||||
if constants.RESET_PASSWORD_URL == "" {
|
if constants.EnvData.RESET_PASSWORD_URL == "" {
|
||||||
constants.RESET_PASSWORD_URL = constants.AUTHORIZER_URL + "/app/reset-password"
|
constants.EnvData.RESET_PASSWORD_URL = constants.EnvData.AUTHORIZER_URL + "/app/reset-password"
|
||||||
}
|
}
|
||||||
|
|
||||||
sender := email.NewSender()
|
sender := email.NewSender()
|
||||||
|
@ -204,7 +204,7 @@ func SendForgotPasswordMail(toEmail, token, host string) error {
|
||||||
<div style="position: absolute; left: -9999px; top: -9999px; margin: 0px;"></div>
|
<div style="position: absolute; left: -9999px; top: -9999px; margin: 0px;"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`, constants.ORGANIZATION_LOGO, toEmail, constants.RESET_PASSWORD_URL+"?token="+token)
|
`, constants.EnvData.ORGANIZATION_LOGO, toEmail, constants.EnvData.RESET_PASSWORD_URL+"?token="+token)
|
||||||
|
|
||||||
bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,12 @@ import (
|
||||||
// version,
|
// version,
|
||||||
func GetMetaInfo() model.Meta {
|
func GetMetaInfo() model.Meta {
|
||||||
return model.Meta{
|
return model.Meta{
|
||||||
Version: constants.VERSION,
|
Version: constants.EnvData.VERSION,
|
||||||
IsGoogleLoginEnabled: constants.GOOGLE_CLIENT_ID != "" && constants.GOOGLE_CLIENT_SECRET != "",
|
IsGoogleLoginEnabled: constants.EnvData.GOOGLE_CLIENT_ID != "" && constants.EnvData.GOOGLE_CLIENT_SECRET != "",
|
||||||
IsGithubLoginEnabled: constants.GITHUB_CLIENT_ID != "" && constants.GOOGLE_CLIENT_SECRET != "",
|
IsGithubLoginEnabled: constants.EnvData.GITHUB_CLIENT_ID != "" && constants.EnvData.GOOGLE_CLIENT_SECRET != "",
|
||||||
IsFacebookLoginEnabled: constants.FACEBOOK_CLIENT_ID != "" && constants.FACEBOOK_CLIENT_SECRET != "",
|
IsFacebookLoginEnabled: constants.EnvData.FACEBOOK_CLIENT_ID != "" && constants.EnvData.FACEBOOK_CLIENT_SECRET != "",
|
||||||
IsBasicAuthenticationEnabled: !constants.DISABLE_BASIC_AUTHENTICATION,
|
IsBasicAuthenticationEnabled: !constants.EnvData.DISABLE_BASIC_AUTHENTICATION,
|
||||||
IsEmailVerificationEnabled: !constants.DISABLE_EMAIL_VERIFICATION,
|
IsEmailVerificationEnabled: !constants.EnvData.DISABLE_EMAIL_VERIFICATION,
|
||||||
IsMagicLinkLoginEnabled: !constants.DISABLE_MAGIC_LINK_LOGIN,
|
IsMagicLinkLoginEnabled: !constants.EnvData.DISABLE_MAGIC_LINK_LOGIN,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ func IsValidEmail(email string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsValidOrigin(url string) bool {
|
func IsValidOrigin(url string) bool {
|
||||||
if len(constants.ALLOWED_ORIGINS) == 1 && constants.ALLOWED_ORIGINS[0] == "*" {
|
if len(constants.EnvData.ALLOWED_ORIGINS) == 1 && constants.EnvData.ALLOWED_ORIGINS[0] == "*" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ func IsValidOrigin(url string) bool {
|
||||||
hostName, port := GetHostParts(url)
|
hostName, port := GetHostParts(url)
|
||||||
currentOrigin := hostName + ":" + port
|
currentOrigin := hostName + ":" + port
|
||||||
|
|
||||||
for _, origin := range constants.ALLOWED_ORIGINS {
|
for _, origin := range constants.EnvData.ALLOWED_ORIGINS {
|
||||||
replacedString := origin
|
replacedString := origin
|
||||||
// if has regex whitelisted domains
|
// if has regex whitelisted domains
|
||||||
if strings.Contains(origin, "*") {
|
if strings.Contains(origin, "*") {
|
||||||
|
@ -50,12 +50,17 @@ func IsValidOrigin(url string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsSuperAdmin(gc *gin.Context) bool {
|
func IsSuperAdmin(gc *gin.Context) bool {
|
||||||
|
token, err := GetAdminAuthToken(gc)
|
||||||
|
if err != nil {
|
||||||
secret := gc.Request.Header.Get("x-authorizer-admin-secret")
|
secret := gc.Request.Header.Get("x-authorizer-admin-secret")
|
||||||
if secret == "" {
|
if secret == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return secret == constants.ADMIN_SECRET
|
return secret == constants.EnvData.ADMIN_SECRET
|
||||||
|
}
|
||||||
|
|
||||||
|
return token != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsValidRoles(userRoles []string, roles []string) bool {
|
func IsValidRoles(userRoles []string, roles []string) bool {
|
||||||
|
|
|
@ -20,23 +20,23 @@ type CustomClaim struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateVerificationToken(email string, tokenType string) (string, error) {
|
func CreateVerificationToken(email string, tokenType string) (string, error) {
|
||||||
t := jwt.New(jwt.GetSigningMethod(constants.JWT_TYPE))
|
t := jwt.New(jwt.GetSigningMethod(constants.EnvData.JWT_TYPE))
|
||||||
|
|
||||||
t.Claims = &CustomClaim{
|
t.Claims = &CustomClaim{
|
||||||
&jwt.StandardClaims{
|
&jwt.StandardClaims{
|
||||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||||
},
|
},
|
||||||
tokenType,
|
tokenType,
|
||||||
UserInfo{Email: email, Host: constants.AUTHORIZER_URL, RedirectURL: constants.APP_URL},
|
UserInfo{Email: email, Host: constants.EnvData.AUTHORIZER_URL, RedirectURL: constants.EnvData.APP_URL},
|
||||||
}
|
}
|
||||||
|
|
||||||
return t.SignedString([]byte(constants.JWT_SECRET))
|
return t.SignedString([]byte(constants.EnvData.JWT_SECRET))
|
||||||
}
|
}
|
||||||
|
|
||||||
func VerifyVerificationToken(token string) (*CustomClaim, error) {
|
func VerifyVerificationToken(token string) (*CustomClaim, error) {
|
||||||
claims := &CustomClaim{}
|
claims := &CustomClaim{}
|
||||||
_, err := jwt.ParseWithClaims(token, claims, func(token *jwt.Token) (interface{}, error) {
|
_, err := jwt.ParseWithClaims(token, claims, func(token *jwt.Token) (interface{}, error) {
|
||||||
return []byte(constants.JWT_SECRET), nil
|
return []byte(constants.EnvData.JWT_SECRET), nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return claims, err
|
return claims, err
|
||||||
|
|
Loading…
Reference in New Issue
Block a user