Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5bf26f7385 | ||
![]() |
1b269dc6db | ||
![]() |
ce9a115a14 | ||
![]() |
f2f4c72aa6 | ||
![]() |
9970eb16c9 | ||
![]() |
23e53286bd | ||
![]() |
47acff05e2 | ||
![]() |
5572928619 | ||
![]() |
85b4cd6339 | ||
![]() |
f0d38ab260 | ||
![]() |
1276af43ef | ||
![]() |
66d42fc2bc | ||
![]() |
1f058f954d | ||
![]() |
8259fb515c |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -10,4 +10,5 @@ build
|
|||||||
data.db
|
data.db
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.env.local
|
.env.local
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
|
.vscode/
|
3
Makefile
3
Makefile
@@ -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
|
||||||
|
|
@@ -7,7 +7,7 @@
|
|||||||
Authorizer
|
Authorizer
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
**Authorizer** is an open-source authentication and authorization solution for your applications. Bring your database and have complete control over the user information. You can self-host authorizer instances and connect to any database (Currently supports [Postgres](https://www.postgresql.org/), [MySQL](https://www.mysql.com/), [SQLite](https://www.sqlite.org/index.html), [SQLServer](https://www.microsoft.com/en-us/sql-server/), [MongoDB](https://mongodb.com/),[ArangoDB](https://www.arangodb.com/)).
|
**Authorizer** is an open-source authentication and authorization solution for your applications. Bring your database and have complete control over the user information. You can self-host authorizer instances and connect to any database (Currently supports [Postgres](https://www.postgresql.org/), [MySQL](https://www.mysql.com/), [SQLite](https://www.sqlite.org/index.html), [SQLServer](https://www.microsoft.com/en-us/sql-server/), [MongoDB](https://mongodb.com/), [ArangoDB](https://www.arangodb.com/)).
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
|
@@ -259,17 +259,6 @@ const InputField = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (Object.values(SelectInputType).includes(inputType)) {
|
if (Object.values(SelectInputType).includes(inputType)) {
|
||||||
if (inputType === SelectInputType.JWT_TYPE) {
|
|
||||||
return (
|
|
||||||
<Select size="sm" {...props}>
|
|
||||||
{[variables[inputType]].map((value: string) => (
|
|
||||||
<option value="value" key={value}>
|
|
||||||
{value}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const { options, ...rest } = props;
|
const { options, ...rest } = props;
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
@@ -293,10 +282,18 @@ const InputField = ({
|
|||||||
<Textarea
|
<Textarea
|
||||||
{...props}
|
{...props}
|
||||||
size="lg"
|
size="lg"
|
||||||
value={inputData[inputType]}
|
fontSize={14}
|
||||||
onChange={(e: any) => {
|
value={variables[inputType] ? variables[inputType] : ''}
|
||||||
setInputData({ ...inputData, [inputType]: e.target.value });
|
onChange={(
|
||||||
}}
|
event: Event & {
|
||||||
|
target: HTMLInputElement;
|
||||||
|
}
|
||||||
|
) =>
|
||||||
|
setVariables({
|
||||||
|
...variables,
|
||||||
|
[inputType]: event.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -49,6 +49,8 @@ export const SelectInputType = {
|
|||||||
|
|
||||||
export const TextAreaInputType = {
|
export const TextAreaInputType = {
|
||||||
CUSTOM_ACCESS_TOKEN_SCRIPT: 'CUSTOM_ACCESS_TOKEN_SCRIPT',
|
CUSTOM_ACCESS_TOKEN_SCRIPT: 'CUSTOM_ACCESS_TOKEN_SCRIPT',
|
||||||
|
JWT_PRIVATE_KEY: 'JWT_PRIVATE_KEY',
|
||||||
|
JWT_PUBLIC_KEY: 'JWT_PUBLIC_KEY',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SwitchInputType = {
|
export const SwitchInputType = {
|
||||||
@@ -66,3 +68,21 @@ export const ArrayInputOperations = {
|
|||||||
APPEND: 'APPEND',
|
APPEND: 'APPEND',
|
||||||
REMOVE: 'REMOVE',
|
REMOVE: 'REMOVE',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const HMACEncryptionType = {
|
||||||
|
HS256: 'HS256',
|
||||||
|
HS384: 'HS384',
|
||||||
|
HS512: 'HS512',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RSAEncryptionType = {
|
||||||
|
RS256: 'RS256',
|
||||||
|
RS384: 'RS384',
|
||||||
|
RS512: 'RS512',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ECDSAEncryptionType = {
|
||||||
|
ES256: 'ES256',
|
||||||
|
ES384: 'ES384',
|
||||||
|
ES512: 'ES512',
|
||||||
|
};
|
||||||
|
@@ -21,6 +21,8 @@ export const EnvVariablesQuery = `
|
|||||||
JWT_TYPE,
|
JWT_TYPE,
|
||||||
JWT_SECRET,
|
JWT_SECRET,
|
||||||
JWT_ROLE_CLAIM,
|
JWT_ROLE_CLAIM,
|
||||||
|
JWT_PRIVATE_KEY,
|
||||||
|
JWT_PUBLIC_KEY,
|
||||||
REDIS_URL,
|
REDIS_URL,
|
||||||
SMTP_HOST,
|
SMTP_HOST,
|
||||||
SMTP_PORT,
|
SMTP_PORT,
|
||||||
|
@@ -31,6 +31,9 @@ import {
|
|||||||
TextInputType,
|
TextInputType,
|
||||||
TextAreaInputType,
|
TextAreaInputType,
|
||||||
SwitchInputType,
|
SwitchInputType,
|
||||||
|
HMACEncryptionType,
|
||||||
|
RSAEncryptionType,
|
||||||
|
ECDSAEncryptionType,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { UpdateEnvVariables } from '../graphql/mutation';
|
import { UpdateEnvVariables } from '../graphql/mutation';
|
||||||
import { getObjectDiff, capitalizeFirstLetter } from '../utils';
|
import { getObjectDiff, capitalizeFirstLetter } from '../utils';
|
||||||
@@ -48,6 +51,8 @@ interface envVarTypes {
|
|||||||
JWT_TYPE: string;
|
JWT_TYPE: string;
|
||||||
JWT_SECRET: string;
|
JWT_SECRET: string;
|
||||||
JWT_ROLE_CLAIM: string;
|
JWT_ROLE_CLAIM: string;
|
||||||
|
JWT_PRIVATE_KEY: string;
|
||||||
|
JWT_PUBLIC_KEY: string;
|
||||||
REDIS_URL: string;
|
REDIS_URL: string;
|
||||||
SMTP_HOST: string;
|
SMTP_HOST: string;
|
||||||
SMTP_PORT: string;
|
SMTP_PORT: string;
|
||||||
@@ -92,6 +97,8 @@ export default function Environment() {
|
|||||||
JWT_TYPE: '',
|
JWT_TYPE: '',
|
||||||
JWT_SECRET: '',
|
JWT_SECRET: '',
|
||||||
JWT_ROLE_CLAIM: '',
|
JWT_ROLE_CLAIM: '',
|
||||||
|
JWT_PRIVATE_KEY: '',
|
||||||
|
JWT_PUBLIC_KEY: '',
|
||||||
REDIS_URL: '',
|
REDIS_URL: '',
|
||||||
SMTP_HOST: '',
|
SMTP_HOST: '',
|
||||||
SMTP_PORT: '',
|
SMTP_PORT: '',
|
||||||
@@ -177,7 +184,6 @@ export default function Environment() {
|
|||||||
const {
|
const {
|
||||||
data: { _env: envData },
|
data: { _env: envData },
|
||||||
} = await client.query(EnvVariablesQuery).toPromise();
|
} = await client.query(EnvVariablesQuery).toPromise();
|
||||||
|
|
||||||
const diff = getObjectDiff(envVariables, envData);
|
const diff = getObjectDiff(envVariables, envData);
|
||||||
const updatedEnvVariables = diff.reduce(
|
const updatedEnvVariables = diff.reduce(
|
||||||
(acc: any, property: string) => ({
|
(acc: any, property: string) => ({
|
||||||
@@ -374,39 +380,67 @@ export default function Environment() {
|
|||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
<Text fontSize="sm">JWT Type:</Text>
|
<Text fontSize="sm">JWT Type:</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Center w="70%">
|
<Flex w="70%">
|
||||||
<Flex w="100%" justifyContent="space-between">
|
|
||||||
<Flex flex="2">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={SelectInputType.JWT_TYPE}
|
|
||||||
isDisabled={true}
|
|
||||||
defaultValue={SelectInputType.JWT_TYPE}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
<Flex flex="3" justifyContent="center" alignItems="center">
|
|
||||||
<Text fontSize="sm">
|
|
||||||
More JWT types will be enabled in upcoming releases.
|
|
||||||
</Text>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">JWT Secret</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
<InputField
|
||||||
variables={envVariables}
|
variables={envVariables}
|
||||||
setVariables={setEnvVariables}
|
setVariables={setEnvVariables}
|
||||||
fieldVisibility={fieldVisibility}
|
inputType={SelectInputType.JWT_TYPE}
|
||||||
setFieldVisibility={setFieldVisibility}
|
value={SelectInputType.JWT_TYPE}
|
||||||
inputType={HiddenInputType.JWT_SECRET}
|
options={{
|
||||||
|
...HMACEncryptionType,
|
||||||
|
...RSAEncryptionType,
|
||||||
|
...ECDSAEncryptionType,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Center>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
{Object.values(HMACEncryptionType).includes(envVariables.JWT_TYPE) ? (
|
||||||
|
<Flex>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">JWT Secret</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center w="70%">
|
||||||
|
<InputField
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setEnvVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.JWT_SECRET}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Flex>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Public Key</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center w="70%">
|
||||||
|
<InputField
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setEnvVariables}
|
||||||
|
inputType={TextAreaInputType.JWT_PUBLIC_KEY}
|
||||||
|
placeholder="Add public key here"
|
||||||
|
minH="25vh"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Private Key</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center w="70%">
|
||||||
|
<InputField
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setEnvVariables}
|
||||||
|
inputType={TextAreaInputType.JWT_PRIVATE_KEY}
|
||||||
|
placeholder="Add private key here"
|
||||||
|
minH="25vh"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<Flex>
|
<Flex>
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
<Text fontSize="sm">JWT Role Claim:</Text>
|
<Text fontSize="sm">JWT Role Claim:</Text>
|
||||||
|
@@ -15,4 +15,6 @@ const (
|
|||||||
DbTypeMongodb = "mongodb"
|
DbTypeMongodb = "mongodb"
|
||||||
// DbTypeYugabyte is the yugabyte database type
|
// DbTypeYugabyte is the yugabyte database type
|
||||||
DbTypeYugabyte = "yugabyte"
|
DbTypeYugabyte = "yugabyte"
|
||||||
|
// DbTypeMariaDB is the mariadb database type
|
||||||
|
DbTypeMariaDB = "mariadb"
|
||||||
)
|
)
|
||||||
|
@@ -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
|
||||||
|
@@ -44,16 +44,12 @@ func NewProvider() (*provider, error) {
|
|||||||
switch envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) {
|
switch envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) {
|
||||||
case constants.DbTypePostgres, constants.DbTypeYugabyte:
|
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
|
|
||||||
case constants.DbTypeSqlite:
|
case constants.DbTypeSqlite:
|
||||||
sqlDB, err = gorm.Open(sqlite.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
sqlDB, err = gorm.Open(sqlite.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
||||||
break
|
case constants.DbTypeMysql, constants.DbTypeMariaDB:
|
||||||
case constants.DbTypeMysql:
|
|
||||||
sqlDB, err = gorm.Open(mysql.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
sqlDB, err = gorm.Open(mysql.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
||||||
break
|
|
||||||
case constants.DbTypeSqlserver:
|
case constants.DbTypeSqlserver:
|
||||||
sqlDB, err = gorm.Open(sqlserver.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
sqlDB, err = gorm.Open(sqlserver.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
82
server/env/env.go
vendored
82
server/env/env.go
vendored
@@ -19,7 +19,7 @@ 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"
|
||||||
}
|
}
|
||||||
@@ -50,18 +50,18 @@ func InitEnv() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
@@ -73,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
|
||||||
@@ -85,48 +85,60 @@ 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.EnvKeyCustomAccessTokenScript] == "" {
|
||||||
|
envData.StringEnv[constants.EnvKeyCustomAccessTokenScript] = os.Getenv(constants.EnvKeyCustomAccessTokenScript)
|
||||||
|
}
|
||||||
|
|
||||||
|
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"
|
||||||
@@ -134,48 +146,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] == "" {
|
||||||
@@ -187,7 +199,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
|
||||||
|
|
||||||
@@ -215,14 +227,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{}
|
||||||
|
|
||||||
@@ -230,7 +242,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{}
|
||||||
|
|
||||||
@@ -259,12 +271,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)
|
||||||
|
@@ -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":
|
||||||
|
@@ -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"`
|
||||||
|
@@ -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
|
||||||
|
@@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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,
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
18
server/sessionstore/redis_client.go
Normal file
18
server/sessionstore/redis_client.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package sessionstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RedisSessionClient interface {
|
||||||
|
HMSet(ctx context.Context, key string, values ...interface{}) *redis.BoolCmd
|
||||||
|
Del(ctx context.Context, keys ...string) *redis.IntCmd
|
||||||
|
HDel(ctx context.Context, key string, fields ...string) *redis.IntCmd
|
||||||
|
HMGet(ctx context.Context, key string, fields ...string) *redis.SliceCmd
|
||||||
|
HGetAll(ctx context.Context, key string) *redis.StringStringMapCmd
|
||||||
|
Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *redis.StatusCmd
|
||||||
|
Get(ctx context.Context, key string) *redis.StringCmd
|
||||||
|
}
|
@@ -4,13 +4,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type RedisStore struct {
|
type RedisStore struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
store *redis.Client
|
store RedisSessionClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddUserSession adds the user session to redis
|
// AddUserSession adds the user session to redis
|
||||||
|
@@ -3,6 +3,7 @@ package sessionstore
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
@@ -121,6 +122,23 @@ func RemoveSocialLoginState(key string) {
|
|||||||
func InitSession() {
|
func InitSession() {
|
||||||
if envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL) != "" {
|
if envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL) != "" {
|
||||||
log.Println("using redis store to save sessions")
|
log.Println("using redis store to save sessions")
|
||||||
|
if isCluster(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL)) {
|
||||||
|
clusterOpt, err := getClusterOptions(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error parsing redis url:", err)
|
||||||
|
}
|
||||||
|
rdb := redis.NewClusterClient(clusterOpt)
|
||||||
|
ctx := context.Background()
|
||||||
|
_, err = rdb.Ping(ctx).Result()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error connecting to redis cluster server", err)
|
||||||
|
}
|
||||||
|
SessionStoreObj.RedisMemoryStoreObj = &RedisStore{
|
||||||
|
ctx: ctx,
|
||||||
|
store: rdb,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
opt, err := redis.ParseURL(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL))
|
opt, err := redis.ParseURL(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Error parsing redis url:", err)
|
log.Fatalln("Error parsing redis url:", err)
|
||||||
@@ -144,3 +162,19 @@ func InitSession() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isCluster(url string) bool {
|
||||||
|
return len(strings.Split(url, ",")) > 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func getClusterOptions(url string) (*redis.ClusterOptions, error) {
|
||||||
|
hostPortsList := strings.Split(url, ",")
|
||||||
|
opt, err := redis.ParseURL(hostPortsList[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
urls := []string{opt.Addr}
|
||||||
|
urlList := hostPortsList[1:]
|
||||||
|
urls = append(urls, urlList...)
|
||||||
|
return &redis.ClusterOptions{Addrs: urls}, nil
|
||||||
|
}
|
||||||
|
143
server/test/jwt_test.go
Normal file
143
server/test/jwt_test.go
Normal 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)
|
||||||
|
}
|
@@ -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
89
server/token/jwt.go
Normal 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
|
||||||
|
}
|
@@ -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
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user