Compare commits

...

16 Commits

Author SHA1 Message Date
Lakhan Samani
1276af43ef Add new line char 2022-02-12 19:36:29 +05:30
Lakhan Samani
66d42fc2bc Add support for public private key from admin apis 2022-02-12 19:34:22 +05:30
Lakhan Samani
1f058f954d Add test for jwt tokens 2022-02-12 19:26:37 +05:30
Lakhan Samani
8259fb515c Add support for more JWT algo methods 2022-02-12 15:54:23 +05:30
Lakhan Samani
6c2a4c3256 Add support for yugabyte
Resolves #119
2022-02-12 13:19:31 +05:30
Lakhan Samani
51532657d7 fix: input labels 2022-02-07 21:15:08 +05:30
Lakhan Samani
fd56fac353 fix: add custom access token script to env sample 2022-02-07 09:42:49 +05:30
Lakhan Samani
260f533b41 fix: resolves #115 2022-02-05 10:09:25 +05:30
Lakhan Samani
c09ca3b810 fix: improve messaging on dashboard 2022-02-05 09:15:36 +05:30
Lakhan Samani
f07fb50eff Merge branch 'main' of https://github.com/authorizerdev/authorizer 2022-02-05 09:01:22 +05:30
Lakhan Samani
ea62a20c80 fix: remove test env 2022-02-05 09:01:12 +05:30
Lakhan Samani
2bb0ded20e fix: error log and gin mode 2022-02-05 09:00:56 +05:30
Lakhan Samani
fec43f55f2 chore: update project setup info 2022-02-02 13:18:26 +05:30
Lakhan Samani
271e901398 chore: update project setup info 2022-02-02 13:17:35 +05:30
Lakhan Samani
c6f01ce839 chore: update project setup info in contributing 2022-02-02 13:15:54 +05:30
Lakhan Samani
2dd404c02c chore: update project setup info 2022-02-02 13:15:14 +05:30
29 changed files with 493 additions and 152 deletions

View File

@@ -1,2 +1,3 @@
DATABASE_URL=data.db DATABASE_URL=data.db
DATABASE_TYPE=sqlite DATABASE_TYPE=sqlite
CUSTOM_ACCESS_TOKEN_SCRIPT="function(user,tokenPayload){var data = tokenPayload;data.extra = {'x-extra-id': user.id};return data;}"

View File

@@ -43,12 +43,14 @@ Please ask as many questions as you need, either directly in the issue or on [Di
### Project Setup for Authorizer core ### Project Setup for Authorizer core
1. Fork the [authorizer](https://github.com/authorizerdev/authorizer) repository (**Skip this step if you have access to repo**) 1. Fork the [authorizer](https://github.com/authorizerdev/authorizer) repository (**Skip this step if you have access to repo**)
2. `git clone https://github.com/authorizerdev/authorizer.git` 2. Clone repo: `git clone https://github.com/authorizerdev/authorizer.git` or use the forked url from step 1
3. `cd authorizer` 3. Change directory to authorizer: `cd authorizer`
4. `cp .env.sample .env`. Check all the supported env [here](https://docs.authorizer.dev/core/env/) 5. Create Env file `cp .env.sample .env`. Check all the supported env [here](https://docs.authorizer.dev/core/env/)
5. Build the code `make clean && make` 6. Build Dashboard `make build-dashboard`
7. Build App `make build-app`
8. Build Server `make clean && make`
> Note: if you don't have [`make`](https://www.ibm.com/docs/en/aix/7.2?topic=concepts-make-command), you can `cd` into `server` dir and build using the `go build` command > Note: if you don't have [`make`](https://www.ibm.com/docs/en/aix/7.2?topic=concepts-make-command), you can `cd` into `server` dir and build using the `go build` command
6. Run binary `./build/server` 9. Run binary `./build/server`
### Testing ### Testing

View File

@@ -11,3 +11,6 @@ clean:
rm -rf build rm -rf build
test: test:
cd server && go clean --testcache && go test -v ./test cd server && go clean --testcache && go test -v ./test
generate:
cd server && go get github.com/99designs/gqlgen/cmd@v0.14.0 && go run github.com/99designs/gqlgen generate

View File

@@ -78,12 +78,14 @@ This guide helps you practice using Authorizer to evaluate it before you use it
### Project Setup ### Project Setup
1. Fork the [authorizer](https://github.com/authorizerdev/authorizer) repository (**Skip this step if you have access to repo**) 1. Fork the [authorizer](https://github.com/authorizerdev/authorizer) repository (**Skip this step if you have access to repo**)
2. `git clone https://github.com/authorizerdev/authorizer.git` 2. Clone repo: `git clone https://github.com/authorizerdev/authorizer.git` or use the forked url from step 1
3. `cd authorizer` 3. Change directory to authorizer: `cd authorizer`
4. `cp .env.sample .env`. Check all the supported env [here](https://docs.authorizer.dev/core/env/) 5. Create Env file `cp .env.sample .env`. Check all the supported env [here](https://docs.authorizer.dev/core/env/)
5. Build the code `make clean && make` 6. Build Dashboard `make build-dashboard`
7. Build App `make build-app`
8. Build Server `make clean && make`
> Note: if you don't have [`make`](https://www.ibm.com/docs/en/aix/7.2?topic=concepts-make-command), you can `cd` into `server` dir and build using the `go build` command > Note: if you don't have [`make`](https://www.ibm.com/docs/en/aix/7.2?topic=concepts-make-command), you can `cd` into `server` dir and build using the `go build` command
6. Run binary `./build/server` 9. Run binary `./build/server`
## Install using binaries ## Install using binaries

View File

@@ -40,9 +40,9 @@ interface LinkItemProps {
route: string; route: string;
} }
const LinkItems: Array<LinkItemProps> = [ const LinkItems: Array<LinkItemProps> = [
{ name: 'Home', icon: FiHome, route: '/' }, // { name: 'Home', icon: FiHome, route: '/' },
{ name: 'Environment Variables', icon: FiSettings, route: '/' },
{ name: 'Users', icon: FiUsers, route: '/users' }, { name: 'Users', icon: FiUsers, route: '/users' },
{ name: 'Environment Variables', icon: FiSettings, route: '/environment' },
]; ];
interface SidebarProps extends BoxProps { interface SidebarProps extends BoxProps {

View File

@@ -73,17 +73,25 @@ export default function Auth() {
fontWeight="bold" fontWeight="bold"
mb="2" mb="2"
> >
Hi there 👋 <br /> Hello Admin 👋 <br />
</Text> </Text>
<Text fontSize="large" textAlign="center" color="gray.500" mb="8"> <Text fontSize="large" textAlign="center" color="gray.500" mb="8">
Welcome to Authorizer Administrative Dashboard Welcome to Admin Dashboard
</Text> </Text>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<VStack spacing="5" justify="space-between"> <VStack spacing="5" justify="space-between">
<FormControl isRequired> <FormControl isRequired>
{/* <FormLabel htmlFor="admin-secret"> <FormLabel htmlFor="admin-username">Username</FormLabel>
{isLogin ? 'Enter' : 'Configure'} Admin Secret <Input
</FormLabel> */} size="lg"
id="admin-username"
placeholder="Username"
disabled
value="admin"
/>
</FormControl>
<FormControl isRequired>
<FormLabel htmlFor="admin-secret">Password</FormLabel>
<Input <Input
size="lg" size="lg"
id="admin-secret" id="admin-secret"
@@ -111,10 +119,7 @@ export default function Auth() {
</Text> </Text>
) : ( ) : (
<Text color="gray.600" fontSize="sm"> <Text color="gray.600" fontSize="sm">
<b>Note:</b> You can also configure admin secret by setting{' '} <b>Note:</b> Configure the password to start using your dashboard.
<code>ADMIN_SECRET</code> environment variable. For more
information, please refer to the{' '}
<a href="https://docs.authorizer.dev/core/env/">documentation</a>.
</Text> </Text>
)} )}
</VStack> </VStack>

View File

@@ -457,7 +457,7 @@ export default function Environment() {
</Flex> </Flex>
<Flex> <Flex>
<Flex w="30%" justifyContent="start" alignItems="center"> <Flex w="30%" justifyContent="start" alignItems="center">
<Text fontSize="sm">Port:</Text> <Text fontSize="sm">SMTP Port:</Text>
</Flex> </Flex>
<Center w="70%"> <Center w="70%">
<InputField <InputField
@@ -469,7 +469,7 @@ export default function Environment() {
</Flex> </Flex>
<Flex> <Flex>
<Flex w="30%" justifyContent="start" alignItems="center"> <Flex w="30%" justifyContent="start" alignItems="center">
<Text fontSize="sm">Username:</Text> <Text fontSize="sm">SMTP Username:</Text>
</Flex> </Flex>
<Center w="70%"> <Center w="70%">
<InputField <InputField
@@ -481,7 +481,7 @@ export default function Environment() {
</Flex> </Flex>
<Flex> <Flex>
<Flex w="30%" justifyContent="start" alignItems="center"> <Flex w="30%" justifyContent="start" alignItems="center">
<Text fontSize="sm">Password:</Text> <Text fontSize="sm">SMTP Password:</Text>
</Flex> </Flex>
<Center w="70%"> <Center w="70%">
<InputField <InputField
@@ -556,7 +556,7 @@ export default function Environment() {
</Stack> </Stack>
<Divider marginTop="2%" marginBottom="2%" /> <Divider marginTop="2%" marginBottom="2%" />
<Text fontSize="md" paddingTop="2%" fontWeight="bold"> <Text fontSize="md" paddingTop="2%" fontWeight="bold">
Custom Scripts Custom Access Token Scripts
</Text> </Text>
<Stack spacing={6} padding="2% 0%"> <Stack spacing={6} padding="2% 0%">
<Flex> <Flex>

View File

@@ -23,7 +23,7 @@ export const AppRoutes = () => {
</DashboardLayout> </DashboardLayout>
} }
> >
<Route path="/" element={<Home />} /> <Route path="/" element={<Environment />} />
<Route path="users" element={<Users />} /> <Route path="users" element={<Users />} />
<Route path="environment" element={<Environment />} /> <Route path="environment" element={<Environment />} />
<Route path="*" element={<Home />} /> <Route path="*" element={<Home />} />

View File

@@ -13,4 +13,6 @@ const (
DbTypeArangodb = "arangodb" DbTypeArangodb = "arangodb"
// DbTypeMongodb is the mongodb database type // DbTypeMongodb is the mongodb database type
DbTypeMongodb = "mongodb" DbTypeMongodb = "mongodb"
// DbTypeYugabyte is the yugabyte database type
DbTypeYugabyte = "yugabyte"
) )

View File

@@ -43,6 +43,10 @@ const (
EnvKeyJwtType = "JWT_TYPE" EnvKeyJwtType = "JWT_TYPE"
// EnvKeyJwtSecret key for env variable JWT_SECRET // EnvKeyJwtSecret key for env variable JWT_SECRET
EnvKeyJwtSecret = "JWT_SECRET" EnvKeyJwtSecret = "JWT_SECRET"
// EnvKeyJwtPrivateKey key for env variable JWT_PRIVATE_KEY
EnvKeyJwtPrivateKey = "JWT_PRIVATE_KEY"
// EnvKeyJwtPublicKey key for env variable JWT_PUBLIC_KEY
EnvKeyJwtPublicKey = "JWT_PUBLIC_KEY"
// EnvKeyAllowedOrigins key for env variable ALLOWED_ORIGINS // EnvKeyAllowedOrigins key for env variable ALLOWED_ORIGINS
EnvKeyAllowedOrigins = "ALLOWED_ORIGINS" EnvKeyAllowedOrigins = "ALLOWED_ORIGINS"
// EnvKeyAppURL key for env variable APP_URL // EnvKeyAppURL key for env variable APP_URL

View File

@@ -1,6 +1,10 @@
package sql package sql
import ( import (
"log"
"os"
"time"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/envstore" "github.com/authorizerdev/authorizer/server/envstore"
@@ -9,6 +13,7 @@ import (
"gorm.io/driver/sqlite" "gorm.io/driver/sqlite"
"gorm.io/driver/sqlserver" "gorm.io/driver/sqlserver"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/gorm/schema" "gorm.io/gorm/schema"
) )
@@ -20,15 +25,24 @@ type provider struct {
func NewProvider() (*provider, error) { func NewProvider() (*provider, error) {
var sqlDB *gorm.DB var sqlDB *gorm.DB
var err error var err error
customLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // Slow SQL threshold
LogLevel: logger.Silent, // Log level
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
Colorful: false, // Disable color
},
)
ormConfig := &gorm.Config{ ormConfig := &gorm.Config{
Logger: customLogger,
NamingStrategy: schema.NamingStrategy{ NamingStrategy: schema.NamingStrategy{
TablePrefix: models.Prefix, TablePrefix: models.Prefix,
}, },
} }
switch envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) { switch envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) {
case constants.DbTypePostgres: case constants.DbTypePostgres, constants.DbTypeYugabyte:
sqlDB, err = gorm.Open(postgres.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig) sqlDB, err = gorm.Open(postgres.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
break break
case constants.DbTypeSqlite: case constants.DbTypeSqlite:

83
server/env/env.go vendored
View File

@@ -8,6 +8,7 @@ import (
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/envstore" "github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/utils" "github.com/authorizerdev/authorizer/server/utils"
"github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/joho/godotenv" "github.com/joho/godotenv"
) )
@@ -18,14 +19,14 @@ func InitEnv() {
envData := envstore.EnvInMemoryStoreObj.GetEnvStoreClone() envData := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
if envData.StringEnv[constants.EnvKeyEnv] == "" { if envData.StringEnv[constants.EnvKeyEnv] == "" {
envData.StringEnv[constants.EnvKeyEnv] = os.Getenv("ENV") envData.StringEnv[constants.EnvKeyEnv] = os.Getenv(constants.EnvKeyEnv)
if envData.StringEnv[constants.EnvKeyEnv] == "" { if envData.StringEnv[constants.EnvKeyEnv] == "" {
envData.StringEnv[constants.EnvKeyEnv] = "production" envData.StringEnv[constants.EnvKeyEnv] = "production"
} }
if envData.StringEnv[constants.EnvKeyEnv] == "production" { if envData.StringEnv[constants.EnvKeyEnv] == "production" {
envData.BoolEnv[constants.EnvKeyIsProd] = true envData.BoolEnv[constants.EnvKeyIsProd] = true
os.Setenv("GIN_MODE", "release") gin.SetMode(gin.ReleaseMode)
} else { } else {
envData.BoolEnv[constants.EnvKeyIsProd] = false envData.BoolEnv[constants.EnvKeyIsProd] = false
} }
@@ -45,22 +46,22 @@ func InitEnv() {
err := godotenv.Load(envData.StringEnv[constants.EnvKeyEnvPath]) err := godotenv.Load(envData.StringEnv[constants.EnvKeyEnvPath])
if err != nil { if err != nil {
log.Printf("error loading %s file", envData.StringEnv[constants.EnvKeyEnvPath]) log.Printf("using OS env instead of %s file", envData.StringEnv[constants.EnvKeyEnvPath])
} }
if envData.StringEnv[constants.EnvKeyPort] == "" { if envData.StringEnv[constants.EnvKeyPort] == "" {
envData.StringEnv[constants.EnvKeyPort] = os.Getenv("PORT") envData.StringEnv[constants.EnvKeyPort] = os.Getenv(constants.EnvKeyPort)
if envData.StringEnv[constants.EnvKeyPort] == "" { if envData.StringEnv[constants.EnvKeyPort] == "" {
envData.StringEnv[constants.EnvKeyPort] = "8080" envData.StringEnv[constants.EnvKeyPort] = "8080"
} }
} }
if envData.StringEnv[constants.EnvKeyAdminSecret] == "" { if envData.StringEnv[constants.EnvKeyAdminSecret] == "" {
envData.StringEnv[constants.EnvKeyAdminSecret] = os.Getenv("ADMIN_SECRET") envData.StringEnv[constants.EnvKeyAdminSecret] = os.Getenv(constants.EnvKeyAdminSecret)
} }
if envData.StringEnv[constants.EnvKeyDatabaseType] == "" { if envData.StringEnv[constants.EnvKeyDatabaseType] == "" {
envData.StringEnv[constants.EnvKeyDatabaseType] = os.Getenv("DATABASE_TYPE") envData.StringEnv[constants.EnvKeyDatabaseType] = os.Getenv(constants.EnvKeyDatabaseType)
if envstore.ARG_DB_TYPE != nil && *envstore.ARG_DB_TYPE != "" { if envstore.ARG_DB_TYPE != nil && *envstore.ARG_DB_TYPE != "" {
envData.StringEnv[constants.EnvKeyDatabaseType] = *envstore.ARG_DB_TYPE envData.StringEnv[constants.EnvKeyDatabaseType] = *envstore.ARG_DB_TYPE
@@ -72,7 +73,7 @@ func InitEnv() {
} }
if envData.StringEnv[constants.EnvKeyDatabaseURL] == "" { if envData.StringEnv[constants.EnvKeyDatabaseURL] == "" {
envData.StringEnv[constants.EnvKeyDatabaseURL] = os.Getenv("DATABASE_URL") envData.StringEnv[constants.EnvKeyDatabaseURL] = os.Getenv(constants.EnvKeyDatabaseURL)
if envstore.ARG_DB_URL != nil && *envstore.ARG_DB_URL != "" { if envstore.ARG_DB_URL != nil && *envstore.ARG_DB_URL != "" {
envData.StringEnv[constants.EnvKeyDatabaseURL] = *envstore.ARG_DB_URL envData.StringEnv[constants.EnvKeyDatabaseURL] = *envstore.ARG_DB_URL
@@ -84,48 +85,56 @@ func InitEnv() {
} }
if envData.StringEnv[constants.EnvKeyDatabaseName] == "" { if envData.StringEnv[constants.EnvKeyDatabaseName] == "" {
envData.StringEnv[constants.EnvKeyDatabaseName] = os.Getenv("DATABASE_NAME") envData.StringEnv[constants.EnvKeyDatabaseName] = os.Getenv(constants.EnvKeyDatabaseName)
if envData.StringEnv[constants.EnvKeyDatabaseName] == "" { if envData.StringEnv[constants.EnvKeyDatabaseName] == "" {
envData.StringEnv[constants.EnvKeyDatabaseName] = "authorizer" envData.StringEnv[constants.EnvKeyDatabaseName] = "authorizer"
} }
} }
if envData.StringEnv[constants.EnvKeySmtpHost] == "" { if envData.StringEnv[constants.EnvKeySmtpHost] == "" {
envData.StringEnv[constants.EnvKeySmtpHost] = os.Getenv("SMTP_HOST") envData.StringEnv[constants.EnvKeySmtpHost] = os.Getenv(constants.EnvKeySmtpHost)
} }
if envData.StringEnv[constants.EnvKeySmtpPort] == "" { if envData.StringEnv[constants.EnvKeySmtpPort] == "" {
envData.StringEnv[constants.EnvKeySmtpPort] = os.Getenv("SMTP_PORT") envData.StringEnv[constants.EnvKeySmtpPort] = os.Getenv(constants.EnvKeySmtpPort)
} }
if envData.StringEnv[constants.EnvKeySmtpUsername] == "" { if envData.StringEnv[constants.EnvKeySmtpUsername] == "" {
envData.StringEnv[constants.EnvKeySmtpUsername] = os.Getenv("SMTP_USERNAME") envData.StringEnv[constants.EnvKeySmtpUsername] = os.Getenv(constants.EnvKeySmtpUsername)
} }
if envData.StringEnv[constants.EnvKeySmtpPassword] == "" { if envData.StringEnv[constants.EnvKeySmtpPassword] == "" {
envData.StringEnv[constants.EnvKeySmtpPassword] = os.Getenv("SMTP_PASSWORD") envData.StringEnv[constants.EnvKeySmtpPassword] = os.Getenv(constants.EnvKeySmtpPassword)
} }
if envData.StringEnv[constants.EnvKeySenderEmail] == "" { if envData.StringEnv[constants.EnvKeySenderEmail] == "" {
envData.StringEnv[constants.EnvKeySenderEmail] = os.Getenv("SENDER_EMAIL") envData.StringEnv[constants.EnvKeySenderEmail] = os.Getenv(constants.EnvKeySenderEmail)
} }
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" { if envData.StringEnv[constants.EnvKeyJwtSecret] == "" {
envData.StringEnv[constants.EnvKeyJwtSecret] = os.Getenv("JWT_SECRET") envData.StringEnv[constants.EnvKeyJwtSecret] = os.Getenv(constants.EnvKeyJwtSecret)
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" { if envData.StringEnv[constants.EnvKeyJwtSecret] == "" {
envData.StringEnv[constants.EnvKeyJwtSecret] = uuid.New().String() envData.StringEnv[constants.EnvKeyJwtSecret] = uuid.New().String()
} }
} }
if envData.StringEnv[constants.EnvKeyJwtPrivateKey] == "" {
envData.StringEnv[constants.EnvKeyJwtPrivateKey] = os.Getenv(constants.EnvKeyJwtPrivateKey)
}
if envData.StringEnv[constants.EnvKeyJwtPublicKey] == "" {
envData.StringEnv[constants.EnvKeyJwtPublicKey] = os.Getenv(constants.EnvKeyJwtPublicKey)
}
if envData.StringEnv[constants.EnvKeyJwtType] == "" { if envData.StringEnv[constants.EnvKeyJwtType] == "" {
envData.StringEnv[constants.EnvKeyJwtType] = os.Getenv("JWT_TYPE") envData.StringEnv[constants.EnvKeyJwtType] = os.Getenv(constants.EnvKeyJwtType)
if envData.StringEnv[constants.EnvKeyJwtType] == "" { if envData.StringEnv[constants.EnvKeyJwtType] == "" {
envData.StringEnv[constants.EnvKeyJwtType] = "HS256" envData.StringEnv[constants.EnvKeyJwtType] = "HS256"
} }
} }
if envData.StringEnv[constants.EnvKeyJwtRoleClaim] == "" { if envData.StringEnv[constants.EnvKeyJwtRoleClaim] == "" {
envData.StringEnv[constants.EnvKeyJwtRoleClaim] = os.Getenv("JWT_ROLE_CLAIM") envData.StringEnv[constants.EnvKeyJwtRoleClaim] = os.Getenv(constants.EnvKeyJwtRoleClaim)
if envData.StringEnv[constants.EnvKeyJwtRoleClaim] == "" { if envData.StringEnv[constants.EnvKeyJwtRoleClaim] == "" {
envData.StringEnv[constants.EnvKeyJwtRoleClaim] = "role" envData.StringEnv[constants.EnvKeyJwtRoleClaim] = "role"
@@ -133,48 +142,48 @@ func InitEnv() {
} }
if envData.StringEnv[constants.EnvKeyRedisURL] == "" { if envData.StringEnv[constants.EnvKeyRedisURL] == "" {
envData.StringEnv[constants.EnvKeyRedisURL] = os.Getenv("REDIS_URL") envData.StringEnv[constants.EnvKeyRedisURL] = os.Getenv(constants.EnvKeyRedisURL)
} }
if envData.StringEnv[constants.EnvKeyCookieName] == "" { if envData.StringEnv[constants.EnvKeyCookieName] == "" {
envData.StringEnv[constants.EnvKeyCookieName] = os.Getenv("COOKIE_NAME") envData.StringEnv[constants.EnvKeyCookieName] = os.Getenv(constants.EnvKeyCookieName)
if envData.StringEnv[constants.EnvKeyCookieName] == "" { if envData.StringEnv[constants.EnvKeyCookieName] == "" {
envData.StringEnv[constants.EnvKeyCookieName] = "authorizer" envData.StringEnv[constants.EnvKeyCookieName] = "authorizer"
} }
} }
if envData.StringEnv[constants.EnvKeyGoogleClientID] == "" { if envData.StringEnv[constants.EnvKeyGoogleClientID] == "" {
envData.StringEnv[constants.EnvKeyGoogleClientID] = os.Getenv("GOOGLE_CLIENT_ID") envData.StringEnv[constants.EnvKeyGoogleClientID] = os.Getenv(constants.EnvKeyGoogleClientID)
} }
if envData.StringEnv[constants.EnvKeyGoogleClientSecret] == "" { if envData.StringEnv[constants.EnvKeyGoogleClientSecret] == "" {
envData.StringEnv[constants.EnvKeyGoogleClientSecret] = os.Getenv("GOOGLE_CLIENT_SECRET") envData.StringEnv[constants.EnvKeyGoogleClientSecret] = os.Getenv(constants.EnvKeyGoogleClientSecret)
} }
if envData.StringEnv[constants.EnvKeyGithubClientID] == "" { if envData.StringEnv[constants.EnvKeyGithubClientID] == "" {
envData.StringEnv[constants.EnvKeyGithubClientID] = os.Getenv("GITHUB_CLIENT_ID") envData.StringEnv[constants.EnvKeyGithubClientID] = os.Getenv(constants.EnvKeyGithubClientID)
} }
if envData.StringEnv[constants.EnvKeyGithubClientSecret] == "" { if envData.StringEnv[constants.EnvKeyGithubClientSecret] == "" {
envData.StringEnv[constants.EnvKeyGithubClientSecret] = os.Getenv("GITHUB_CLIENT_SECRET") envData.StringEnv[constants.EnvKeyGithubClientSecret] = os.Getenv(constants.EnvKeyGithubClientSecret)
} }
if envData.StringEnv[constants.EnvKeyFacebookClientID] == "" { if envData.StringEnv[constants.EnvKeyFacebookClientID] == "" {
envData.StringEnv[constants.EnvKeyFacebookClientID] = os.Getenv("FACEBOOK_CLIENT_ID") envData.StringEnv[constants.EnvKeyFacebookClientID] = os.Getenv(constants.EnvKeyFacebookClientID)
} }
if envData.StringEnv[constants.EnvKeyFacebookClientSecret] == "" { if envData.StringEnv[constants.EnvKeyFacebookClientSecret] == "" {
envData.StringEnv[constants.EnvKeyFacebookClientSecret] = os.Getenv("FACEBOOK_CLIENT_SECRET") envData.StringEnv[constants.EnvKeyFacebookClientSecret] = os.Getenv(constants.EnvKeyFacebookClientSecret)
} }
if envData.StringEnv[constants.EnvKeyResetPasswordURL] == "" { if envData.StringEnv[constants.EnvKeyResetPasswordURL] == "" {
envData.StringEnv[constants.EnvKeyResetPasswordURL] = strings.TrimPrefix(os.Getenv("RESET_PASSWORD_URL"), "/") envData.StringEnv[constants.EnvKeyResetPasswordURL] = strings.TrimPrefix(os.Getenv(constants.EnvKeyResetPasswordURL), "/")
} }
envData.BoolEnv[constants.EnvKeyDisableBasicAuthentication] = os.Getenv("DISABLE_BASIC_AUTHENTICATION") == "true" envData.BoolEnv[constants.EnvKeyDisableBasicAuthentication] = os.Getenv(constants.EnvKeyDisableBasicAuthentication) == "true"
envData.BoolEnv[constants.EnvKeyDisableEmailVerification] = os.Getenv("DISABLE_EMAIL_VERIFICATION") == "true" envData.BoolEnv[constants.EnvKeyDisableEmailVerification] = os.Getenv(constants.EnvKeyDisableEmailVerification) == "true"
envData.BoolEnv[constants.EnvKeyDisableMagicLinkLogin] = os.Getenv("DISABLE_MAGIC_LINK_LOGIN") == "true" envData.BoolEnv[constants.EnvKeyDisableMagicLinkLogin] = os.Getenv(constants.EnvKeyDisableMagicLinkLogin) == "true"
envData.BoolEnv[constants.EnvKeyDisableLoginPage] = os.Getenv("DISABLE_LOGIN_PAGE") == "true" envData.BoolEnv[constants.EnvKeyDisableLoginPage] = os.Getenv(constants.EnvKeyDisableLoginPage) == "true"
// no need to add nil check as its already done above // no need to add nil check as its already done above
if envData.StringEnv[constants.EnvKeySmtpHost] == "" || envData.StringEnv[constants.EnvKeySmtpUsername] == "" || envData.StringEnv[constants.EnvKeySmtpPassword] == "" || envData.StringEnv[constants.EnvKeySenderEmail] == "" && envData.StringEnv[constants.EnvKeySmtpPort] == "" { if envData.StringEnv[constants.EnvKeySmtpHost] == "" || envData.StringEnv[constants.EnvKeySmtpUsername] == "" || envData.StringEnv[constants.EnvKeySmtpPassword] == "" || envData.StringEnv[constants.EnvKeySenderEmail] == "" && envData.StringEnv[constants.EnvKeySmtpPort] == "" {
@@ -186,7 +195,7 @@ func InitEnv() {
envData.BoolEnv[constants.EnvKeyDisableMagicLinkLogin] = true envData.BoolEnv[constants.EnvKeyDisableMagicLinkLogin] = true
} }
allowedOriginsSplit := strings.Split(os.Getenv("ALLOWED_ORIGINS"), ",") allowedOriginsSplit := strings.Split(os.Getenv(constants.EnvKeyAllowedOrigins), ",")
allowedOrigins := []string{} allowedOrigins := []string{}
hasWildCard := false hasWildCard := false
@@ -214,14 +223,14 @@ func InitEnv() {
envData.SliceEnv[constants.EnvKeyAllowedOrigins] = allowedOrigins envData.SliceEnv[constants.EnvKeyAllowedOrigins] = allowedOrigins
rolesEnv := strings.TrimSpace(os.Getenv("ROLES")) rolesEnv := strings.TrimSpace(os.Getenv(constants.EnvKeyRoles))
rolesSplit := strings.Split(rolesEnv, ",") rolesSplit := strings.Split(rolesEnv, ",")
roles := []string{} roles := []string{}
if len(rolesEnv) == 0 { if len(rolesEnv) == 0 {
roles = []string{"user"} roles = []string{"user"}
} }
defaultRolesEnv := strings.TrimSpace(os.Getenv("DEFAULT_ROLES")) defaultRolesEnv := strings.TrimSpace(os.Getenv(constants.EnvKeyDefaultRoles))
defaultRoleSplit := strings.Split(defaultRolesEnv, ",") defaultRoleSplit := strings.Split(defaultRolesEnv, ",")
defaultRoles := []string{} defaultRoles := []string{}
@@ -229,7 +238,7 @@ func InitEnv() {
defaultRoles = []string{"user"} defaultRoles = []string{"user"}
} }
protectedRolesEnv := strings.TrimSpace(os.Getenv("PROTECTED_ROLES")) protectedRolesEnv := strings.TrimSpace(os.Getenv(constants.EnvKeyProtectedRoles))
protectedRolesSplit := strings.Split(protectedRolesEnv, ",") protectedRolesSplit := strings.Split(protectedRolesEnv, ",")
protectedRoles := []string{} protectedRoles := []string{}
@@ -258,12 +267,12 @@ func InitEnv() {
envData.SliceEnv[constants.EnvKeyDefaultRoles] = defaultRoles envData.SliceEnv[constants.EnvKeyDefaultRoles] = defaultRoles
envData.SliceEnv[constants.EnvKeyProtectedRoles] = protectedRoles envData.SliceEnv[constants.EnvKeyProtectedRoles] = protectedRoles
if os.Getenv("ORGANIZATION_NAME") != "" { if os.Getenv(constants.EnvKeyOrganizationName) != "" {
envData.StringEnv[constants.EnvKeyOrganizationName] = os.Getenv("ORGANIZATION_NAME") envData.StringEnv[constants.EnvKeyOrganizationName] = os.Getenv(constants.EnvKeyOrganizationName)
} }
if os.Getenv("ORGANIZATION_LOGO") != "" { if os.Getenv(constants.EnvKeyOrganizationLogo) != "" {
envData.StringEnv[constants.EnvKeyOrganizationLogo] = os.Getenv("ORGANIZATION_LOGO") envData.StringEnv[constants.EnvKeyOrganizationLogo] = os.Getenv(constants.EnvKeyOrganizationLogo)
} }
envstore.EnvInMemoryStoreObj.UpdateEnvStore(envData) envstore.EnvInMemoryStoreObj.UpdateEnvStore(envData)

View File

@@ -70,6 +70,8 @@ type ComplexityRoot struct {
GithubClientSecret func(childComplexity int) int GithubClientSecret func(childComplexity int) int
GoogleClientID func(childComplexity int) int GoogleClientID func(childComplexity int) int
GoogleClientSecret func(childComplexity int) int GoogleClientSecret func(childComplexity int) int
JwtPrivateKey func(childComplexity int) int
JwtPublicKey func(childComplexity int) int
JwtRoleClaim func(childComplexity int) int JwtRoleClaim func(childComplexity int) int
JwtSecret func(childComplexity int) int JwtSecret func(childComplexity int) int
JwtType func(childComplexity int) int JwtType func(childComplexity int) int
@@ -391,6 +393,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Env.GoogleClientSecret(childComplexity), true return e.complexity.Env.GoogleClientSecret(childComplexity), true
case "Env.JWT_PRIVATE_KEY":
if e.complexity.Env.JwtPrivateKey == nil {
break
}
return e.complexity.Env.JwtPrivateKey(childComplexity), true
case "Env.JWT_PUBLIC_KEY":
if e.complexity.Env.JwtPublicKey == nil {
break
}
return e.complexity.Env.JwtPublicKey(childComplexity), true
case "Env.JWT_ROLE_CLAIM": case "Env.JWT_ROLE_CLAIM":
if e.complexity.Env.JwtRoleClaim == nil { if e.complexity.Env.JwtRoleClaim == nil {
break break
@@ -1206,6 +1222,8 @@ type Env {
SENDER_EMAIL: String SENDER_EMAIL: String
JWT_TYPE: String JWT_TYPE: String
JWT_SECRET: String JWT_SECRET: String
JWT_PRIVATE_KEY: String
JWT_PUBLIC_KEY: String
ALLOWED_ORIGINS: [String!] ALLOWED_ORIGINS: [String!]
APP_URL: String APP_URL: String
REDIS_URL: String REDIS_URL: String
@@ -1240,6 +1258,8 @@ input UpdateEnvInput {
SENDER_EMAIL: String SENDER_EMAIL: String
JWT_TYPE: String JWT_TYPE: String
JWT_SECRET: String JWT_SECRET: String
JWT_PRIVATE_KEY: String
JWT_PUBLIC_KEY: String
ALLOWED_ORIGINS: [String!] ALLOWED_ORIGINS: [String!]
APP_URL: String APP_URL: String
REDIS_URL: String REDIS_URL: String
@@ -2229,6 +2249,70 @@ func (ec *executionContext) _Env_JWT_SECRET(ctx context.Context, field graphql.C
return ec.marshalOString2ᚖstring(ctx, field.Selections, res) return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
} }
func (ec *executionContext) _Env_JWT_PRIVATE_KEY(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "Env",
Field: field,
Args: nil,
IsMethod: false,
IsResolver: false,
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.JwtPrivateKey, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*string)
fc.Result = res
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
}
func (ec *executionContext) _Env_JWT_PUBLIC_KEY(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "Env",
Field: field,
Args: nil,
IsMethod: false,
IsResolver: false,
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.JwtPublicKey, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*string)
fc.Result = res
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
}
func (ec *executionContext) _Env_ALLOWED_ORIGINS(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { func (ec *executionContext) _Env_ALLOWED_ORIGINS(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
@@ -7044,6 +7128,22 @@ func (ec *executionContext) unmarshalInputUpdateEnvInput(ctx context.Context, ob
if err != nil { if err != nil {
return it, err return it, err
} }
case "JWT_PRIVATE_KEY":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("JWT_PRIVATE_KEY"))
it.JwtPrivateKey, err = ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
case "JWT_PUBLIC_KEY":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("JWT_PUBLIC_KEY"))
it.JwtPublicKey, err = ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
case "ALLOWED_ORIGINS": case "ALLOWED_ORIGINS":
var err error var err error
@@ -7539,6 +7639,10 @@ func (ec *executionContext) _Env(ctx context.Context, sel ast.SelectionSet, obj
out.Values[i] = ec._Env_JWT_TYPE(ctx, field, obj) out.Values[i] = ec._Env_JWT_TYPE(ctx, field, obj)
case "JWT_SECRET": case "JWT_SECRET":
out.Values[i] = ec._Env_JWT_SECRET(ctx, field, obj) out.Values[i] = ec._Env_JWT_SECRET(ctx, field, obj)
case "JWT_PRIVATE_KEY":
out.Values[i] = ec._Env_JWT_PRIVATE_KEY(ctx, field, obj)
case "JWT_PUBLIC_KEY":
out.Values[i] = ec._Env_JWT_PUBLIC_KEY(ctx, field, obj)
case "ALLOWED_ORIGINS": case "ALLOWED_ORIGINS":
out.Values[i] = ec._Env_ALLOWED_ORIGINS(ctx, field, obj) out.Values[i] = ec._Env_ALLOWED_ORIGINS(ctx, field, obj)
case "APP_URL": case "APP_URL":

View File

@@ -34,6 +34,8 @@ type Env struct {
SenderEmail *string `json:"SENDER_EMAIL"` SenderEmail *string `json:"SENDER_EMAIL"`
JwtType *string `json:"JWT_TYPE"` JwtType *string `json:"JWT_TYPE"`
JwtSecret *string `json:"JWT_SECRET"` JwtSecret *string `json:"JWT_SECRET"`
JwtPrivateKey *string `json:"JWT_PRIVATE_KEY"`
JwtPublicKey *string `json:"JWT_PUBLIC_KEY"`
AllowedOrigins []string `json:"ALLOWED_ORIGINS"` AllowedOrigins []string `json:"ALLOWED_ORIGINS"`
AppURL *string `json:"APP_URL"` AppURL *string `json:"APP_URL"`
RedisURL *string `json:"REDIS_URL"` RedisURL *string `json:"REDIS_URL"`
@@ -153,6 +155,8 @@ type UpdateEnvInput struct {
SenderEmail *string `json:"SENDER_EMAIL"` SenderEmail *string `json:"SENDER_EMAIL"`
JwtType *string `json:"JWT_TYPE"` JwtType *string `json:"JWT_TYPE"`
JwtSecret *string `json:"JWT_SECRET"` JwtSecret *string `json:"JWT_SECRET"`
JwtPrivateKey *string `json:"JWT_PRIVATE_KEY"`
JwtPublicKey *string `json:"JWT_PUBLIC_KEY"`
AllowedOrigins []string `json:"ALLOWED_ORIGINS"` AllowedOrigins []string `json:"ALLOWED_ORIGINS"`
AppURL *string `json:"APP_URL"` AppURL *string `json:"APP_URL"`
RedisURL *string `json:"REDIS_URL"` RedisURL *string `json:"REDIS_URL"`

View File

@@ -97,6 +97,8 @@ type Env {
SENDER_EMAIL: String SENDER_EMAIL: String
JWT_TYPE: String JWT_TYPE: String
JWT_SECRET: String JWT_SECRET: String
JWT_PRIVATE_KEY: String
JWT_PUBLIC_KEY: String
ALLOWED_ORIGINS: [String!] ALLOWED_ORIGINS: [String!]
APP_URL: String APP_URL: String
REDIS_URL: String REDIS_URL: String
@@ -131,6 +133,8 @@ input UpdateEnvInput {
SENDER_EMAIL: String SENDER_EMAIL: String
JWT_TYPE: String JWT_TYPE: String
JWT_SECRET: String JWT_SECRET: String
JWT_PRIVATE_KEY: String
JWT_PUBLIC_KEY: String
ALLOWED_ORIGINS: [String!] ALLOWED_ORIGINS: [String!]
APP_URL: String APP_URL: String
REDIS_URL: String REDIS_URL: String

15
server/handlers/health.go Normal file
View File

@@ -0,0 +1,15 @@
package handlers
import (
"net/http"
"github.com/gin-gonic/gin"
)
// HealthHandler is the handler for /health route.
// It states if server is in healthy state or not
func HealthHandler() gin.HandlerFunc {
return func(c *gin.Context) {
c.String(http.StatusOK, "OK")
}
}

View File

@@ -33,13 +33,13 @@ func VerifyEmailHandler() gin.HandlerFunc {
} }
// verify if token exists in db // verify if token exists in db
claim, err := token.VerifyVerificationToken(tokenInQuery) claim, err := token.ParseJWTToken(tokenInQuery)
if err != nil { if err != nil {
c.JSON(400, errorRes) c.JSON(400, errorRes)
return return
} }
user, err := db.Provider.GetUserByEmail(claim.Email) user, err := db.Provider.GetUserByEmail(claim["email"].(string))
if err != nil { if err != nil {
c.JSON(400, gin.H{ c.JSON(400, gin.H{
"message": err.Error(), "message": err.Error(),
@@ -68,6 +68,6 @@ func VerifyEmailHandler() gin.HandlerFunc {
cookie.SetCookie(c, authToken.AccessToken.Token, authToken.RefreshToken.Token, authToken.FingerPrintHash) cookie.SetCookie(c, authToken.AccessToken.Token, authToken.RefreshToken.Token, authToken.FingerPrintHash)
utils.SaveSessionInDB(user.ID, c) utils.SaveSessionInDB(user.ID, c)
c.Redirect(http.StatusTemporaryRedirect, claim.RedirectURL) c.Redirect(http.StatusTemporaryRedirect, claim["redirect_url"].(string))
} }
} }

View File

@@ -40,6 +40,8 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
jwtType := store.StringEnv[constants.EnvKeyJwtType] jwtType := store.StringEnv[constants.EnvKeyJwtType]
jwtSecret := store.StringEnv[constants.EnvKeyJwtSecret] jwtSecret := store.StringEnv[constants.EnvKeyJwtSecret]
jwtRoleClaim := store.StringEnv[constants.EnvKeyJwtRoleClaim] jwtRoleClaim := store.StringEnv[constants.EnvKeyJwtRoleClaim]
jwtPublicKey := store.StringEnv[constants.EnvKeyJwtPublicKey]
jwtPrivateKey := store.StringEnv[constants.EnvKeyJwtPrivateKey]
allowedOrigins := store.SliceEnv[constants.EnvKeyAllowedOrigins] allowedOrigins := store.SliceEnv[constants.EnvKeyAllowedOrigins]
appURL := store.StringEnv[constants.EnvKeyAppURL] appURL := store.StringEnv[constants.EnvKeyAppURL]
redisURL := store.StringEnv[constants.EnvKeyRedisURL] redisURL := store.StringEnv[constants.EnvKeyRedisURL]
@@ -74,6 +76,8 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
SenderEmail: &senderEmail, SenderEmail: &senderEmail,
JwtType: &jwtType, JwtType: &jwtType,
JwtSecret: &jwtSecret, JwtSecret: &jwtSecret,
JwtPrivateKey: &jwtPrivateKey,
JwtPublicKey: &jwtPublicKey,
JwtRoleClaim: &jwtRoleClaim, JwtRoleClaim: &jwtRoleClaim,
AllowedOrigins: allowedOrigins, AllowedOrigins: allowedOrigins,
AppURL: &appURL, AppURL: &appURL,

View File

@@ -26,7 +26,7 @@ func IsValidJwtResolver(ctx context.Context, params *model.IsValidJWTQueryInput)
} }
} }
claims, err := tokenHelper.VerifyJWTToken(token) claims, err := tokenHelper.ParseJWTToken(token)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -38,7 +38,7 @@ func LogoutResolver(ctx context.Context) (*model.Response, error) {
fingerPrint := string(decryptedFingerPrint) fingerPrint := string(decryptedFingerPrint)
// verify refresh token and fingerprint // verify refresh token and fingerprint
claims, err := token.VerifyJWTToken(refreshToken) claims, err := token.ParseJWTToken(refreshToken)
if err != nil { if err != nil {
return res, err return res, err
} }

View File

@@ -31,12 +31,12 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput)
} }
// verify if token exists in db // verify if token exists in db
claim, err := token.VerifyVerificationToken(params.Token) claim, err := token.ParseJWTToken(params.Token)
if err != nil { if err != nil {
return res, fmt.Errorf(`invalid token`) return res, fmt.Errorf(`invalid token`)
} }
user, err := db.Provider.GetUserByEmail(claim.Email) user, err := db.Provider.GetUserByEmail(claim["email"].(string))
if err != nil { if err != nil {
return res, err return res, err
} }

View File

@@ -41,7 +41,7 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
fingerPrint := string(decryptedFingerPrint) fingerPrint := string(decryptedFingerPrint)
// verify refresh token and fingerprint // verify refresh token and fingerprint
claims, err := token.VerifyJWTToken(refreshToken) claims, err := token.ParseJWTToken(refreshToken)
if err != nil { if err != nil {
return res, err return res, err
} }

View File

@@ -28,12 +28,12 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
} }
// verify if token exists in db // verify if token exists in db
claim, err := token.VerifyVerificationToken(params.Token) claim, err := token.ParseJWTToken(params.Token)
if err != nil { if err != nil {
return res, fmt.Errorf(`invalid token`) return res, fmt.Errorf(`invalid token`)
} }
user, err := db.Provider.GetUserByEmail(claim.Email) user, err := db.Provider.GetUserByEmail(claim["email"].(string))
if err != nil { if err != nil {
return res, err return res, err
} }

View File

@@ -14,6 +14,7 @@ func InitRouter() *gin.Engine {
router.Use(middlewares.CORSMiddleware()) router.Use(middlewares.CORSMiddleware())
router.GET("/", handlers.RootHandler()) router.GET("/", handlers.RootHandler())
router.GET("/health", handlers.HealthHandler())
router.POST("/graphql", handlers.GraphqlHandler()) router.POST("/graphql", handlers.GraphqlHandler())
router.GET("/playground", handlers.PlaygroundHandler()) router.GET("/playground", handlers.PlaygroundHandler())
router.GET("/oauth_login/:oauth_provider", handlers.OAuthLoginHandler()) router.GET("/oauth_login/:oauth_provider", handlers.OAuthLoginHandler())

View File

@@ -138,7 +138,6 @@ func InitSession() {
} }
} else { } else {
log.Println("using in memory store to save sessions")
SessionStoreObj.InMemoryStoreObj = &InMemoryStore{ SessionStoreObj.InMemoryStoreObj = &InMemoryStore{
store: map[string]map[string]string{}, store: map[string]map[string]string{},
socialLoginState: map[string]string{}, socialLoginState: map[string]string{},

143
server/test/jwt_test.go Normal file
View File

@@ -0,0 +1,143 @@
package test
import (
"testing"
"time"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/token"
"github.com/golang-jwt/jwt"
"github.com/stretchr/testify/assert"
)
func TestJwt(t *testing.T) {
claims := jwt.MapClaims{
"exp": time.Now().Add(time.Minute * 30).Unix(),
"iat": time.Now().Unix(),
"email": "test@yopmail.com",
}
// persist older data till test is done and then reset it
jwtType := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
jwtSecret := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)
t.Run("invalid jwt type", func(t *testing.T) {
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "invalid")
token, err := token.SignJWTToken(claims)
assert.Error(t, err, "unsupported signing method")
assert.Empty(t, token)
})
t.Run("expired jwt token", func(t *testing.T) {
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "HS256")
expiredClaims := jwt.MapClaims{
"exp": time.Now().Add(-time.Minute * 30).Unix(),
"iat": time.Now().Unix(),
"email": "test@yopmail.com",
}
jwtToken, err := token.SignJWTToken(expiredClaims)
assert.NoError(t, err)
_, err = token.ParseJWTToken(jwtToken)
assert.Error(t, err, err.Error(), "Token is expired")
})
t.Run("HMAC algorithms", func(t *testing.T) {
t.Run("HS256", func(t *testing.T) {
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "HS256")
jwtToken, err := token.SignJWTToken(claims)
assert.NoError(t, err)
assert.NotEmpty(t, jwtToken)
c, err := token.ParseJWTToken(jwtToken)
assert.NoError(t, err)
assert.Equal(t, c["email"].(string), claims["email"])
})
t.Run("HS384", func(t *testing.T) {
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "HS384")
jwtToken, err := token.SignJWTToken(claims)
assert.NoError(t, err)
assert.NotEmpty(t, jwtToken)
c, err := token.ParseJWTToken(jwtToken)
assert.NoError(t, err)
assert.Equal(t, c["email"].(string), claims["email"])
})
t.Run("HS512", func(t *testing.T) {
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "HS512")
jwtToken, err := token.SignJWTToken(claims)
assert.NoError(t, err)
assert.NotEmpty(t, jwtToken)
c, err := token.ParseJWTToken(jwtToken)
assert.NoError(t, err)
assert.Equal(t, c["email"].(string), claims["email"])
})
})
t.Run("RSA algorithms", func(t *testing.T) {
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, "-----BEGIN RSA PRIVATE KEY-----\nMIICWgIBAAKBgHUQac/v0f3c8m4L9BMWfxBiEzkdV5CoaqfxhO5IwAX/1cs0WceN\njM7g/qzC7YmEOSiYqupiRtsyn6riz0xT/VUg4uv1uZ/muC6EVfOjR5Ack3Brquql\nD+oMxN4CeA0Wzp2dEV4N3Gv7wWHdhg9ZSc4g6+ZUdlkhIPfeO9RNK9pPAgMBAAEC\ngYBqLrIbp0dNQn0vbm48ZhppDNys4L2NfAYKQZs23Aw5JN6Si/CnffBrsk+u+ryl\nEKcb+KaHJQ9qQdfsFAC+FizhMQy0Dq9yw6shnqHX+paB6E6z2/vX8ToPzJRwxBY3\nyuaetCEpSXR7pQEd5YWDTUH7qYnb9FObD+umhVvmlsTHCQJBALagPmexu0DvMXKZ\nWdplik6eXg9lptiuj5MYqitEUyzU9E9HNeHKlZM7szGeWG3jNduoKcyo4M0Flvt9\ncP+soVUCQQCkGOQ5Y3/GoZmclKWMVwqGdmL6wEjhNfg4PRfgUalHBif9Q1KnM8FP\nAvIqIH8bttRfyT185WmaM2gml0ApwF0TAkBVil9QoK4t7xvBKtUsd809n+481gc9\njR4Q70edtoYjBKhejeNOHF7NNPRtNFcFOZybg3v4sc2CGrEqoQoRp+F1AkBeLmMe\nhPrbF/jAI5h4WaSS0/OvExlBGOaj8Hx5pKTRPLlK5I7VpCC4pmoyv3/0ehSd/TQr\nMMhRVlvaeki7Lcq9AkBravJUadVCAIsB6oh03mo8gUFFFqXDyEl6BiJYqrjCQ5wd\nAQYJGbqQvgjPxN9+PTPldDNi6KVXntSg5gF/dA+Z\n-----END RSA PRIVATE KEY-----")
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, "-----BEGIN PUBLIC KEY-----\nMIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHUQac/v0f3c8m4L9BMWfxBiEzkd\nV5CoaqfxhO5IwAX/1cs0WceNjM7g/qzC7YmEOSiYqupiRtsyn6riz0xT/VUg4uv1\nuZ/muC6EVfOjR5Ack3BrquqlD+oMxN4CeA0Wzp2dEV4N3Gv7wWHdhg9ZSc4g6+ZU\ndlkhIPfeO9RNK9pPAgMBAAE=\n-----END PUBLIC KEY-----")
t.Run("RS256", func(t *testing.T) {
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "RS256")
jwtToken, err := token.SignJWTToken(claims)
assert.NoError(t, err)
assert.NotEmpty(t, jwtToken)
c, err := token.ParseJWTToken(jwtToken)
assert.NoError(t, err)
assert.Equal(t, c["email"].(string), claims["email"])
})
t.Run("RS384", func(t *testing.T) {
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "RS384")
jwtToken, err := token.SignJWTToken(claims)
assert.NoError(t, err)
assert.NotEmpty(t, jwtToken)
c, err := token.ParseJWTToken(jwtToken)
assert.NoError(t, err)
assert.Equal(t, c["email"].(string), claims["email"])
})
t.Run("RS512", func(t *testing.T) {
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "RS512")
jwtToken, err := token.SignJWTToken(claims)
assert.NoError(t, err)
assert.NotEmpty(t, jwtToken)
c, err := token.ParseJWTToken(jwtToken)
assert.NoError(t, err)
assert.Equal(t, c["email"].(string), claims["email"])
})
})
t.Run("ECDSA algorithms", func(t *testing.T) {
t.Run("ES256", func(t *testing.T) {
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgevZzL1gdAFr88hb2\nOF/2NxApJCzGCEDdfSp6VQO30hyhRANCAAQRWz+jn65BtOMvdyHKcvjBeBSDZH2r\n1RTwjmYSi9R/zpBnuQ4EiMnCqfMPWiZqB4QdbAd0E7oH50VpuZ1P087G\n-----END PRIVATE KEY-----")
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEVs/o5+uQbTjL3chynL4wXgUg2R9\nq9UU8I5mEovUf86QZ7kOBIjJwqnzD1omageEHWwHdBO6B+dFabmdT9POxg==\n-----END PUBLIC KEY-----")
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "ES256")
jwtToken, err := token.SignJWTToken(claims)
assert.NoError(t, err)
assert.NotEmpty(t, jwtToken)
c, err := token.ParseJWTToken(jwtToken)
assert.NoError(t, err)
assert.Equal(t, c["email"].(string), claims["email"])
})
t.Run("ES384", func(t *testing.T) {
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, "-----BEGIN PRIVATE KEY-----\nMIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCAHpFQ62QnGCEvYh/p\nE9QmR1C9aLcDItRbslbmhen/h1tt8AyMhskeenT+rAyyPhGhZANiAAQLW5ZJePZz\nMIPAxMtZXkEWbDF0zo9f2n4+T1h/2sh/fviblc/VTyrv10GEtIi5qiOy85Pf1RRw\n8lE5IPUWpgu553SteKigiKLUPeNpbqmYZUkWGh3MLfVzLmx85ii2vMU=\n-----END PRIVATE KEY-----")
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, "-----BEGIN PUBLIC KEY-----\nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEC1uWSXj2czCDwMTLWV5BFmwxdM6PX9p+\nPk9Yf9rIf374m5XP1U8q79dBhLSIuaojsvOT39UUcPJROSD1FqYLued0rXiooIii\n1D3jaW6pmGVJFhodzC31cy5sfOYotrzF\n-----END PUBLIC KEY-----")
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "ES384")
jwtToken, err := token.SignJWTToken(claims)
assert.NoError(t, err)
assert.NotEmpty(t, jwtToken)
c, err := token.ParseJWTToken(jwtToken)
assert.NoError(t, err)
assert.Equal(t, c["email"].(string), claims["email"])
})
t.Run("ES512", func(t *testing.T) {
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, "-----BEGIN PRIVATE KEY-----\nMIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBiyAa7aRHFDCh2qga\n9sTUGINE5jHAFnmM8xWeT/uni5I4tNqhV5Xx0pDrmCV9mbroFtfEa0XVfKuMAxxf\nZ6LM/yKhgYkDgYYABAGBzgdnP798FsLuWYTDDQA7c0r3BVk8NnRUSexpQUsRilPN\nv3SchO0lRw9Ru86x1khnVDx+duq4BiDFcvlSAcyjLACJvjvoyTLJiA+TQFdmrear\njMiZNE25pT2yWP1NUndJxPcvVtfBW48kPOmvkY4WlqP5bAwCXwbsKrCgk6xbsp12\new==\n-----END PRIVATE KEY-----")
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, "-----BEGIN PUBLIC KEY-----\nMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgc4HZz+/fBbC7lmEww0AO3NK9wVZ\nPDZ0VEnsaUFLEYpTzb90nITtJUcPUbvOsdZIZ1Q8fnbquAYgxXL5UgHMoywAib47\n6MkyyYgPk0BXZq3mq4zImTRNuaU9slj9TVJ3ScT3L1bXwVuPJDzpr5GOFpaj+WwM\nAl8G7CqwoJOsW7Kddns=\n-----END PUBLIC KEY-----")
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "ES512")
jwtToken, err := token.SignJWTToken(claims)
assert.NoError(t, err)
assert.NotEmpty(t, jwtToken)
c, err := token.ParseJWTToken(jwtToken)
assert.NoError(t, err)
assert.Equal(t, c["email"].(string), claims["email"])
})
})
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, jwtType)
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtSecret, jwtSecret)
}

View File

@@ -62,7 +62,6 @@ func CreateAuthToken(user models.User, roles []string) (*Token, error) {
// CreateRefreshToken util to create JWT token // CreateRefreshToken util to create JWT token
func CreateRefreshToken(user models.User, roles []string) (string, int64, error) { func CreateRefreshToken(user models.User, roles []string) (string, int64, error) {
t := jwt.New(jwt.GetSigningMethod(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)))
// expires in 1 year // expires in 1 year
expiryBound := time.Hour * 8760 expiryBound := time.Hour * 8760
expiresAt := time.Now().Add(expiryBound).Unix() expiresAt := time.Now().Add(expiryBound).Unix()
@@ -75,8 +74,7 @@ func CreateRefreshToken(user models.User, roles []string) (string, int64, error)
"id": user.ID, "id": user.ID,
} }
t.Claims = customClaims token, err := SignJWTToken(customClaims)
token, err := t.SignedString([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)))
if err != nil { if err != nil {
return "", 0, err return "", 0, err
} }
@@ -86,9 +84,7 @@ func CreateRefreshToken(user models.User, roles []string) (string, int64, error)
// CreateAccessToken util to create JWT token, based on // CreateAccessToken util to create JWT token, based on
// user information, roles config and CUSTOM_ACCESS_TOKEN_SCRIPT // user information, roles config and CUSTOM_ACCESS_TOKEN_SCRIPT
func CreateAccessToken(user models.User, roles []string) (string, int64, error) { func CreateAccessToken(user models.User, roles []string) (string, int64, error) {
t := jwt.New(jwt.GetSigningMethod(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)))
expiryBound := time.Minute * 30 expiryBound := time.Minute * 30
expiresAt := time.Now().Add(expiryBound).Unix() expiresAt := time.Now().Add(expiryBound).Unix()
resUser := user.AsAPIUser() resUser := user.AsAPIUser()
@@ -141,9 +137,7 @@ func CreateAccessToken(user models.User, roles []string) (string, int64, error)
} }
} }
t.Claims = customClaims token, err := SignJWTToken(customClaims)
token, err := t.SignedString([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)))
if err != nil { if err != nil {
return "", 0, err return "", 0, err
} }
@@ -187,43 +181,13 @@ func GetFingerPrint(gc *gin.Context) (string, error) {
return fingerPrint, nil return fingerPrint, nil
} }
// VerifyJWTToken helps in verifying the JWT token
func VerifyJWTToken(token string) (map[string]interface{}, error) {
var res map[string]interface{}
claims := jwt.MapClaims{}
t, err := jwt.ParseWithClaims(token, claims, func(token *jwt.Token) (interface{}, error) {
return []byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)), nil
})
if err != nil {
return res, err
}
if !t.Valid {
return res, fmt.Errorf(`invalid token`)
}
// claim parses exp & iat into float 64 with e^10,
// but we expect it to be int64
// hence we need to assert interface and convert to int64
intExp := int64(claims["exp"].(float64))
intIat := int64(claims["iat"].(float64))
data, _ := json.Marshal(claims)
json.Unmarshal(data, &res)
res["exp"] = intExp
res["iat"] = intIat
return res, nil
}
func ValidateAccessToken(gc *gin.Context) (map[string]interface{}, error) { func ValidateAccessToken(gc *gin.Context) (map[string]interface{}, error) {
token, err := GetAccessToken(gc) token, err := GetAccessToken(gc)
if err != nil { if err != nil {
return nil, err return nil, err
} }
claims, err := VerifyJWTToken(token) claims, err := ParseJWTToken(token)
if err != nil { if err != nil {
return nil, err return nil, err
} }

89
server/token/jwt.go Normal file
View File

@@ -0,0 +1,89 @@
package token
import (
"errors"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/golang-jwt/jwt"
)
// SignJWTToken common util to sing jwt token
func SignJWTToken(claims jwt.MapClaims) (string, error) {
jwtType := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
signingMethod := jwt.GetSigningMethod(jwtType)
if signingMethod == nil {
return "", errors.New("unsupported signing method")
}
t := jwt.New(signingMethod)
if t == nil {
return "", errors.New("unsupported signing method")
}
t.Claims = claims
switch signingMethod {
case jwt.SigningMethodHS256, jwt.SigningMethodHS384, jwt.SigningMethodHS512:
return t.SignedString([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)))
case jwt.SigningMethodRS256, jwt.SigningMethodRS384, jwt.SigningMethodRS512:
key, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPrivateKey)))
if err != nil {
return "", err
}
return t.SignedString(key)
case jwt.SigningMethodES256, jwt.SigningMethodES384, jwt.SigningMethodES512:
key, err := jwt.ParseECPrivateKeyFromPEM([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPrivateKey)))
if err != nil {
return "", err
}
return t.SignedString(key)
default:
return "", errors.New("unsupported signing method")
}
}
// ParseJWTToken common util to parse jwt token
func ParseJWTToken(token string) (jwt.MapClaims, error) {
jwtType := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
signingMethod := jwt.GetSigningMethod(jwtType)
var err error
var claims jwt.MapClaims
switch signingMethod {
case jwt.SigningMethodHS256, jwt.SigningMethodHS384, jwt.SigningMethodHS512:
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
return []byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)), nil
})
case jwt.SigningMethodRS256, jwt.SigningMethodRS384, jwt.SigningMethodRS512:
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
key, err := jwt.ParseRSAPublicKeyFromPEM([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)))
if err != nil {
return nil, err
}
return key, nil
})
case jwt.SigningMethodES256, jwt.SigningMethodES384, jwt.SigningMethodES512:
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
key, err := jwt.ParseECPublicKeyFromPEM([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)))
if err != nil {
return nil, err
}
return key, nil
})
default:
err = errors.New("unsupported signing method")
}
if err != nil {
return claims, err
}
// claim parses exp & iat into float 64 with e^10,
// but we expect it to be int64
// hence we need to assert interface and convert to int64
intExp := int64(claims["exp"].(float64))
intIat := int64(claims["iat"].(float64))
claims["exp"] = intExp
claims["iat"] = intIat
return claims, nil
}

View File

@@ -8,44 +8,16 @@ import (
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt"
) )
// VerificationRequestToken is the user info that is stored in the JWT of verification request
type VerificationRequestToken struct {
Email string `json:"email"`
Host string `json:"host"`
RedirectURL string `json:"redirect_url"`
}
// CustomClaim is the custom claim that is stored in the JWT of verification request
type CustomClaim struct {
*jwt.StandardClaims
TokenType string `json:"token_type"`
VerificationRequestToken
}
// CreateVerificationToken creates a verification JWT token // CreateVerificationToken creates a verification JWT token
func CreateVerificationToken(email, tokenType, hostname string) (string, error) { func CreateVerificationToken(email, tokenType, hostname string) (string, error) {
t := jwt.New(jwt.GetSigningMethod(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType))) claims := jwt.MapClaims{
"exp": time.Now().Add(time.Minute * 30).Unix(),
t.Claims = &CustomClaim{ "iat": time.Now().Unix(),
&jwt.StandardClaims{ "token_type": tokenType,
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(), "email": email,
}, "host": hostname,
tokenType, "redirect_url": envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAppURL),
VerificationRequestToken{Email: email, Host: hostname, RedirectURL: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAppURL)},
} }
return t.SignedString([]byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret))) return SignJWTToken(claims)
}
// VerifyVerificationToken verifies the verification JWT token
func VerifyVerificationToken(token string) (*CustomClaim, error) {
claims := &CustomClaim{}
_, err := jwt.ParseWithClaims(token, claims, func(token *jwt.Token) (interface{}, error) {
return []byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)), nil
})
if err != nil {
return claims, err
}
return claims, nil
} }