Compare commits
37 Commits
0.11.0
...
0.14.0-bet
Author | SHA1 | Date | |
---|---|---|---|
![]() |
57bc091499 | ||
![]() |
128a2a8f75 | ||
![]() |
7b09a8817c | ||
![]() |
1d61840c6d | ||
![]() |
4b25e8941c | ||
![]() |
136eda15bf | ||
![]() |
eea6349318 | ||
![]() |
513b5d2948 | ||
![]() |
e61dc2f08a | ||
![]() |
07552bc0b1 | ||
![]() |
0787a3b494 | ||
![]() |
2946428ab8 | ||
![]() |
5c7d32ec16 | ||
![]() |
f0f2e0b6c8 | ||
![]() |
5399ea8f32 | ||
![]() |
4830a7e9ac | ||
![]() |
df1c56bb1c | ||
![]() |
b68d9ce661 | ||
![]() |
145091dce1 | ||
![]() |
ad46210112 | ||
![]() |
4e19f73845 | ||
![]() |
332269ecf9 | ||
![]() |
dfa96f09a0 | ||
![]() |
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
|
||||||
|
|
||||||
|
30
app/package-lock.json
generated
30
app/package-lock.json
generated
@@ -9,7 +9,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@authorizerdev/authorizer-react": "latest",
|
"@authorizerdev/authorizer-react": "0.8.0",
|
||||||
"@types/react": "^17.0.15",
|
"@types/react": "^17.0.15",
|
||||||
"@types/react-dom": "^17.0.9",
|
"@types/react-dom": "^17.0.9",
|
||||||
"esbuild": "^0.12.17",
|
"esbuild": "^0.12.17",
|
||||||
@@ -24,9 +24,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@authorizerdev/authorizer-js": {
|
"node_modules/@authorizerdev/authorizer-js": {
|
||||||
"version": "0.2.1",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-0.3.0.tgz",
|
||||||
"integrity": "sha512-5lQlh+nc5xTsPongfTyCSX24A1WESu/BjhmZwUNuScEOGady0qPoDHE3RBf46dpi5v05wbHCDN1IFEalX5zssQ==",
|
"integrity": "sha512-KCE5Dw5MUnEgstBUayBriDQAOjqbxU7ixC00rTHAE6aD6TxJkeSls0vCTXpvt4iiKhFK6q9BhHwa/5NwWYpDBQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-fetch": "^2.6.1"
|
"node-fetch": "^2.6.1"
|
||||||
},
|
},
|
||||||
@@ -35,11 +35,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@authorizerdev/authorizer-react": {
|
"node_modules/@authorizerdev/authorizer-react": {
|
||||||
"version": "0.4.3",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-0.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-0.8.0.tgz",
|
||||||
"integrity": "sha512-o/wWe9zZ3ARYdjbDfhGfvOxe1YQrE1YQ+UN9pcq85YSDkbfBkOfcnJ4YxlxWdL0Obd/ErDIeQ3vskyrfvRf3sA==",
|
"integrity": "sha512-178XWGEPsovy3f6Yi2Llh6kFmjdf3ZrkIsqIAKEGPhZawV/1sA6v+4FZp7ReuCxsCelckFFQUnPR8P7od+2HeA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@authorizerdev/authorizer-js": "^0.2.1",
|
"@authorizerdev/authorizer-js": "^0.3.0",
|
||||||
"final-form": "^4.20.2",
|
"final-form": "^4.20.2",
|
||||||
"react-final-form": "^6.5.3",
|
"react-final-form": "^6.5.3",
|
||||||
"styled-components": "^5.3.0"
|
"styled-components": "^5.3.0"
|
||||||
@@ -829,19 +829,19 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@authorizerdev/authorizer-js": {
|
"@authorizerdev/authorizer-js": {
|
||||||
"version": "0.2.1",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-0.3.0.tgz",
|
||||||
"integrity": "sha512-5lQlh+nc5xTsPongfTyCSX24A1WESu/BjhmZwUNuScEOGady0qPoDHE3RBf46dpi5v05wbHCDN1IFEalX5zssQ==",
|
"integrity": "sha512-KCE5Dw5MUnEgstBUayBriDQAOjqbxU7ixC00rTHAE6aD6TxJkeSls0vCTXpvt4iiKhFK6q9BhHwa/5NwWYpDBQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"node-fetch": "^2.6.1"
|
"node-fetch": "^2.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@authorizerdev/authorizer-react": {
|
"@authorizerdev/authorizer-react": {
|
||||||
"version": "0.4.3",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-0.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-0.8.0.tgz",
|
||||||
"integrity": "sha512-o/wWe9zZ3ARYdjbDfhGfvOxe1YQrE1YQ+UN9pcq85YSDkbfBkOfcnJ4YxlxWdL0Obd/ErDIeQ3vskyrfvRf3sA==",
|
"integrity": "sha512-178XWGEPsovy3f6Yi2Llh6kFmjdf3ZrkIsqIAKEGPhZawV/1sA6v+4FZp7ReuCxsCelckFFQUnPR8P7od+2HeA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@authorizerdev/authorizer-js": "^0.2.1",
|
"@authorizerdev/authorizer-js": "^0.3.0",
|
||||||
"final-form": "^4.20.2",
|
"final-form": "^4.20.2",
|
||||||
"react-final-form": "^6.5.3",
|
"react-final-form": "^6.5.3",
|
||||||
"styled-components": "^5.3.0"
|
"styled-components": "^5.3.0"
|
||||||
|
@@ -6,6 +6,9 @@ import Root from './Root';
|
|||||||
export default function App() {
|
export default function App() {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const globalState: Record<string, string> = window['__authorizer__'];
|
const globalState: Record<string, string> = window['__authorizer__'];
|
||||||
|
if (globalState.state) {
|
||||||
|
sessionStorage.setItem('authorizer_state', globalState.state);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
@@ -11,9 +11,14 @@ export default function Root() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (token) {
|
if (token) {
|
||||||
|
const state = sessionStorage.getItem('authorizer_state')?.trim();
|
||||||
const url = new URL(config.redirectURL || '/app');
|
const url = new URL(config.redirectURL || '/app');
|
||||||
if (url.origin !== window.location.origin) {
|
if (url.origin !== window.location.origin) {
|
||||||
window.location.href = config.redirectURL || '/app';
|
console.log({ x: `${config.redirectURL || '/app'}?state=${state}` });
|
||||||
|
sessionStorage.removeItem('authorizer_state');
|
||||||
|
window.location.replace(
|
||||||
|
`${config.redirectURL || '/app'}?state=${state}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return () => {};
|
return () => {};
|
||||||
|
@@ -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,
|
||||||
|
})
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ export const LOGO_URL =
|
|||||||
'https://user-images.githubusercontent.com/6964334/147834043-fc384cab-e7ca-40f8-9663-38fc25fd5f3a.png';
|
'https://user-images.githubusercontent.com/6964334/147834043-fc384cab-e7ca-40f8-9663-38fc25fd5f3a.png';
|
||||||
|
|
||||||
export const TextInputType = {
|
export const TextInputType = {
|
||||||
|
CLIENT_ID: 'CLIENT_ID',
|
||||||
GOOGLE_CLIENT_ID: 'GOOGLE_CLIENT_ID',
|
GOOGLE_CLIENT_ID: 'GOOGLE_CLIENT_ID',
|
||||||
GITHUB_CLIENT_ID: 'GITHUB_CLIENT_ID',
|
GITHUB_CLIENT_ID: 'GITHUB_CLIENT_ID',
|
||||||
FACEBOOK_CLIENT_ID: 'FACEBOOK_CLIENT_ID',
|
FACEBOOK_CLIENT_ID: 'FACEBOOK_CLIENT_ID',
|
||||||
@@ -25,6 +26,7 @@ export const TextInputType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const HiddenInputType = {
|
export const HiddenInputType = {
|
||||||
|
CLIENT_SECRET: 'CLIENT_SECRET',
|
||||||
GOOGLE_CLIENT_SECRET: 'GOOGLE_CLIENT_SECRET',
|
GOOGLE_CLIENT_SECRET: 'GOOGLE_CLIENT_SECRET',
|
||||||
GITHUB_CLIENT_SECRET: 'GITHUB_CLIENT_SECRET',
|
GITHUB_CLIENT_SECRET: 'GITHUB_CLIENT_SECRET',
|
||||||
FACEBOOK_CLIENT_SECRET: 'FACEBOOK_CLIENT_SECRET',
|
FACEBOOK_CLIENT_SECRET: 'FACEBOOK_CLIENT_SECRET',
|
||||||
@@ -49,6 +51,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 +70,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',
|
||||||
|
};
|
||||||
|
@@ -9,6 +9,8 @@ export const AdminSessionQuery = `
|
|||||||
export const EnvVariablesQuery = `
|
export const EnvVariablesQuery = `
|
||||||
query {
|
query {
|
||||||
_env{
|
_env{
|
||||||
|
CLIENT_ID,
|
||||||
|
CLIENT_SECRET,
|
||||||
GOOGLE_CLIENT_ID,
|
GOOGLE_CLIENT_ID,
|
||||||
GOOGLE_CLIENT_SECRET,
|
GOOGLE_CLIENT_SECRET,
|
||||||
GITHUB_CLIENT_ID,
|
GITHUB_CLIENT_ID,
|
||||||
@@ -21,6 +23,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) => ({
|
||||||
@@ -234,6 +240,42 @@ export default function Environment() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box m="5" py="5" px="10" bg="white" rounded="md">
|
<Box m="5" py="5" px="10" bg="white" rounded="md">
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
||||||
|
Your instance information
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Client ID</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center w="70%">
|
||||||
|
<InputField
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={() => {}}
|
||||||
|
inputType={TextInputType.CLIENT_ID}
|
||||||
|
placeholder="Client ID"
|
||||||
|
isDisabled={true}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Client Secret</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center w="70%">
|
||||||
|
<InputField
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setEnvVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.CLIENT_SECRET}
|
||||||
|
placeholder="Client Secret"
|
||||||
|
isDisabled={true}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
<Divider marginTop="2%" marginBottom="2%" />
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
||||||
Social Media Logins
|
Social Media Logins
|
||||||
</Text>
|
</Text>
|
||||||
@@ -374,39 +416,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
|
||||||
@@ -55,8 +59,6 @@ const (
|
|||||||
EnvKeyAdminCookieName = "ADMIN_COOKIE_NAME"
|
EnvKeyAdminCookieName = "ADMIN_COOKIE_NAME"
|
||||||
// EnvKeyResetPasswordURL key for env variable RESET_PASSWORD_URL
|
// EnvKeyResetPasswordURL key for env variable RESET_PASSWORD_URL
|
||||||
EnvKeyResetPasswordURL = "RESET_PASSWORD_URL"
|
EnvKeyResetPasswordURL = "RESET_PASSWORD_URL"
|
||||||
// EnvKeyEncryptionKey key for env variable ENCRYPTION_KEY
|
|
||||||
EnvKeyEncryptionKey = "ENCRYPTION_KEY"
|
|
||||||
// EnvKeyDisableEmailVerification key for env variable DISABLE_EMAIL_VERIFICATION
|
// EnvKeyDisableEmailVerification key for env variable DISABLE_EMAIL_VERIFICATION
|
||||||
EnvKeyDisableEmailVerification = "DISABLE_EMAIL_VERIFICATION"
|
EnvKeyDisableEmailVerification = "DISABLE_EMAIL_VERIFICATION"
|
||||||
// EnvKeyDisableBasicAuthentication key for env variable DISABLE_BASIC_AUTH
|
// EnvKeyDisableBasicAuthentication key for env variable DISABLE_BASIC_AUTH
|
||||||
@@ -89,8 +91,18 @@ const (
|
|||||||
EnvKeyOrganizationName = "ORGANIZATION_NAME"
|
EnvKeyOrganizationName = "ORGANIZATION_NAME"
|
||||||
// EnvKeyOrganizationLogo key for env variable ORGANIZATION_LOGO
|
// EnvKeyOrganizationLogo key for env variable ORGANIZATION_LOGO
|
||||||
EnvKeyOrganizationLogo = "ORGANIZATION_LOGO"
|
EnvKeyOrganizationLogo = "ORGANIZATION_LOGO"
|
||||||
// EnvKeyIsProd key for env variable IS_PROD
|
|
||||||
EnvKeyIsProd = "IS_PROD"
|
|
||||||
// EnvKeyCustomAccessTokenScript key for env variable CUSTOM_ACCESS_TOKEN_SCRIPT
|
// EnvKeyCustomAccessTokenScript key for env variable CUSTOM_ACCESS_TOKEN_SCRIPT
|
||||||
EnvKeyCustomAccessTokenScript = "CUSTOM_ACCESS_TOKEN_SCRIPT"
|
EnvKeyCustomAccessTokenScript = "CUSTOM_ACCESS_TOKEN_SCRIPT"
|
||||||
|
|
||||||
|
// Not Exposed Keys
|
||||||
|
// EnvKeyClientID key for env variable CLIENT_ID
|
||||||
|
EnvKeyClientID = "CLIENT_ID"
|
||||||
|
// EnvKeyClientSecret key for env variable CLIENT_SECRET
|
||||||
|
EnvKeyClientSecret = "CLIENT_SECRET"
|
||||||
|
// EnvKeyEncryptionKey key for env variable ENCRYPTION_KEY
|
||||||
|
EnvKeyEncryptionKey = "ENCRYPTION_KEY"
|
||||||
|
// EnvKeyJWK key for env variable JWK
|
||||||
|
EnvKeyJWK = "JWK"
|
||||||
|
// EnvKeyIsProd key for env variable IS_PROD
|
||||||
|
EnvKeyIsProd = "IS_PROD"
|
||||||
)
|
)
|
||||||
|
@@ -5,4 +5,6 @@ const (
|
|||||||
TokenTypeRefreshToken = "refresh_token"
|
TokenTypeRefreshToken = "refresh_token"
|
||||||
// TokenTypeAccessToken is the access_token token type
|
// TokenTypeAccessToken is the access_token token type
|
||||||
TokenTypeAccessToken = "access_token"
|
TokenTypeAccessToken = "access_token"
|
||||||
|
// TokenTypeIdentityToken is the identity_token token type
|
||||||
|
TokenTypeIdentityToken = "id_token"
|
||||||
)
|
)
|
||||||
|
@@ -16,12 +16,12 @@ func SetAdminCookie(gc *gin.Context, token string) {
|
|||||||
hostname := utils.GetHost(gc)
|
hostname := utils.GetHost(gc)
|
||||||
host, _ := utils.GetHostParts(hostname)
|
host, _ := utils.GetHostParts(hostname)
|
||||||
|
|
||||||
gc.SetCookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), token, 3600, "/", host, secure, httpOnly)
|
gc.SetCookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), token, 3600, "/", host, secure, httpOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAdminCookie gets the admin cookie from the request
|
// GetAdminCookie gets the admin cookie from the request
|
||||||
func GetAdminCookie(gc *gin.Context) (string, error) {
|
func GetAdminCookie(gc *gin.Context) (string, error) {
|
||||||
cookie, err := gc.Request.Cookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName))
|
cookie, err := gc.Request.Cookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -42,5 +42,5 @@ func DeleteAdminCookie(gc *gin.Context) {
|
|||||||
hostname := utils.GetHost(gc)
|
hostname := utils.GetHost(gc)
|
||||||
host, _ := utils.GetHostParts(hostname)
|
host, _ := utils.GetHostParts(hostname)
|
||||||
|
|
||||||
gc.SetCookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), "", -1, "/", host, secure, httpOnly)
|
gc.SetCookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), "", -1, "/", host, secure, httpOnly)
|
||||||
}
|
}
|
||||||
|
@@ -10,13 +10,8 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetCookie sets the cookie in the response. It sets 4 cookies
|
// SetSession sets the session cookie in the response
|
||||||
// 1 COOKIE_NAME.access_token jwt token for the host (temp.abc.com)
|
func SetSession(gc *gin.Context, sessionID string) {
|
||||||
// 2 COOKIE_NAME.access_token.domain jwt token for the domain (abc.com).
|
|
||||||
// 3 COOKIE_NAME.fingerprint fingerprint hash for the refresh token verification.
|
|
||||||
// 4 COOKIE_NAME.refresh_token refresh token
|
|
||||||
// Note all sites don't allow 2nd type of cookie
|
|
||||||
func SetCookie(gc *gin.Context, accessToken, refreshToken, fingerprintHash string) {
|
|
||||||
secure := true
|
secure := true
|
||||||
httpOnly := true
|
httpOnly := true
|
||||||
hostname := utils.GetHost(gc)
|
hostname := utils.GetHost(gc)
|
||||||
@@ -26,77 +21,45 @@ func SetCookie(gc *gin.Context, accessToken, refreshToken, fingerprintHash strin
|
|||||||
domain = "." + domain
|
domain = "." + domain
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO allow configuring from dashboard
|
||||||
year := 60 * 60 * 24 * 365
|
year := 60 * 60 * 24 * 365
|
||||||
thirtyMin := 60 * 30
|
|
||||||
|
|
||||||
gc.SetSameSite(http.SameSiteNoneMode)
|
gc.SetSameSite(http.SameSiteNoneMode)
|
||||||
// set cookie for host
|
gc.SetCookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+"_session", sessionID, year, "/", host, secure, httpOnly)
|
||||||
gc.SetCookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".access_token", accessToken, thirtyMin, "/", host, secure, httpOnly)
|
gc.SetCookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+"_session_domain", sessionID, year, "/", domain, secure, httpOnly)
|
||||||
|
|
||||||
// in case of subdomain, set cookie for domain
|
|
||||||
gc.SetCookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".access_token.domain", accessToken, thirtyMin, "/", domain, secure, httpOnly)
|
|
||||||
|
|
||||||
// set finger print cookie (this should be accessed via cookie only)
|
|
||||||
gc.SetCookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".fingerprint", fingerprintHash, year, "/", host, secure, httpOnly)
|
|
||||||
|
|
||||||
// set refresh token cookie (this should be accessed via cookie only)
|
|
||||||
gc.SetCookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".refresh_token", refreshToken, year, "/", host, secure, httpOnly)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccessTokenCookie to get access token cookie from the request
|
// DeleteSession sets session cookies to expire
|
||||||
func GetAccessTokenCookie(gc *gin.Context) (string, error) {
|
func DeleteSession(gc *gin.Context) {
|
||||||
cookie, err := gc.Request.Cookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName) + ".access_token")
|
secure := true
|
||||||
|
httpOnly := true
|
||||||
|
hostname := utils.GetHost(gc)
|
||||||
|
host, _ := utils.GetHostParts(hostname)
|
||||||
|
domain := utils.GetDomainName(hostname)
|
||||||
|
if domain != "localhost" {
|
||||||
|
domain = "." + domain
|
||||||
|
}
|
||||||
|
|
||||||
|
gc.SetSameSite(http.SameSiteNoneMode)
|
||||||
|
gc.SetCookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+"_session", "", -1, "/", host, secure, httpOnly)
|
||||||
|
gc.SetCookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+"_session_domain", "", -1, "/", domain, secure, httpOnly)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSession gets the session cookie from context
|
||||||
|
func GetSession(gc *gin.Context) (string, error) {
|
||||||
|
var cookie *http.Cookie
|
||||||
|
var err error
|
||||||
|
cookie, err = gc.Request.Cookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName) + "_session")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cookie, err = gc.Request.Cookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName) + ".access_token.domain")
|
cookie, err = gc.Request.Cookie(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName) + "_session_domain")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cookie.Value, nil
|
decodedValue, err := url.PathUnescape(cookie.Value)
|
||||||
}
|
|
||||||
|
|
||||||
// GetRefreshTokenCookie to get refresh token cookie
|
|
||||||
func GetRefreshTokenCookie(gc *gin.Context) (string, error) {
|
|
||||||
cookie, err := gc.Request.Cookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName) + ".refresh_token")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return cookie.Value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFingerPrintCookie to get fingerprint cookie
|
|
||||||
func GetFingerPrintCookie(gc *gin.Context) (string, error) {
|
|
||||||
cookie, err := gc.Request.Cookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName) + ".fingerprint")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
// cookie escapes special characters like $
|
|
||||||
// hence we need to unescape before comparing
|
|
||||||
decodedValue, err := url.QueryUnescape(cookie.Value)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return decodedValue, nil
|
return decodedValue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteCookie sets response cookies to expire
|
|
||||||
func DeleteCookie(gc *gin.Context) {
|
|
||||||
secure := true
|
|
||||||
httpOnly := true
|
|
||||||
hostname := utils.GetHost(gc)
|
|
||||||
host, _ := utils.GetHostParts(hostname)
|
|
||||||
domain := utils.GetDomainName(hostname)
|
|
||||||
if domain != "localhost" {
|
|
||||||
domain = "." + domain
|
|
||||||
}
|
|
||||||
|
|
||||||
gc.SetSameSite(http.SameSiteNoneMode)
|
|
||||||
gc.SetCookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".access_token", "", -1, "/", host, secure, httpOnly)
|
|
||||||
gc.SetCookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".access_token.domain", "", -1, "/", domain, secure, httpOnly)
|
|
||||||
gc.SetCookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".fingerprint", "", -1, "/", host, secure, httpOnly)
|
|
||||||
gc.SetCookie(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".refresh_token", "", -1, "/", host, secure, httpOnly)
|
|
||||||
}
|
|
||||||
|
@@ -1,35 +1,52 @@
|
|||||||
package utils
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"golang.org/x/crypto/bcrypt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// EncryptB64 encrypts data into base64 string
|
var bytes = []byte{35, 46, 57, 24, 85, 35, 24, 74, 87, 35, 88, 98, 66, 32, 14, 0o5}
|
||||||
func EncryptB64(text string) string {
|
|
||||||
return base64.StdEncoding.EncodeToString([]byte(text))
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptB64 decrypts from base64 string to readable string
|
// EncryptAES method is to encrypt or hide any classified text
|
||||||
func DecryptB64(s string) (string, error) {
|
func EncryptAES(text string) (string, error) {
|
||||||
data, err := base64.StdEncoding.DecodeString(s)
|
key := []byte(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey))
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return string(data), nil
|
plainText := []byte(text)
|
||||||
|
cfb := cipher.NewCFBEncrypter(block, bytes)
|
||||||
|
cipherText := make([]byte, len(plainText))
|
||||||
|
cfb.XORKeyStream(cipherText, plainText)
|
||||||
|
return EncryptB64(string(cipherText)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncryptAES encrypts data using AES algorithm
|
// DecryptAES method is to extract back the encrypted text
|
||||||
func EncryptAES(text []byte) ([]byte, error) {
|
func DecryptAES(text string) (string, error) {
|
||||||
key := []byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey))
|
key := []byte(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey))
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
cipherText, err := DecryptB64(text)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
cfb := cipher.NewCFBDecrypter(block, bytes)
|
||||||
|
plainText := make([]byte, len(cipherText))
|
||||||
|
cfb.XORKeyStream(plainText, []byte(cipherText))
|
||||||
|
return string(plainText), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncryptAESEnv encrypts data using AES algorithm
|
||||||
|
// kept for the backward compatibility of env data encryption
|
||||||
|
func EncryptAESEnv(text []byte) ([]byte, error) {
|
||||||
|
key := []byte(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey))
|
||||||
c, err := aes.NewCipher(key)
|
c, err := aes.NewCipher(key)
|
||||||
var res []byte
|
var res []byte
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -62,8 +79,9 @@ func EncryptAES(text []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DecryptAES decrypts data using AES algorithm
|
// DecryptAES decrypts data using AES algorithm
|
||||||
func DecryptAES(ciphertext []byte) ([]byte, error) {
|
// Kept for the backward compatibility of env data decryption
|
||||||
key := []byte(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey))
|
func DecryptAESEnv(ciphertext []byte) ([]byte, error) {
|
||||||
|
key := []byte(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEncryptionKey))
|
||||||
c, err := aes.NewCipher(key)
|
c, err := aes.NewCipher(key)
|
||||||
var res []byte
|
var res []byte
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -88,39 +106,3 @@ func DecryptAES(ciphertext []byte) ([]byte, error) {
|
|||||||
|
|
||||||
return plaintext, nil
|
return plaintext, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncryptEnvData is used to encrypt the env data
|
|
||||||
func EncryptEnvData(data envstore.Store) (string, error) {
|
|
||||||
jsonBytes, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
envStoreObj := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
|
||||||
|
|
||||||
err = json.Unmarshal(jsonBytes, &envStoreObj)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
configData, err := json.Marshal(envStoreObj)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
encryptedConfig, err := EncryptAES(configData)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return EncryptB64(string(encryptedConfig)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptPassword is used for encrypting password
|
|
||||||
func EncryptPassword(password string) (string, error) {
|
|
||||||
pw, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(pw), nil
|
|
||||||
}
|
|
17
server/crypto/b64.go
Normal file
17
server/crypto/b64.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package crypto
|
||||||
|
|
||||||
|
import "encoding/base64"
|
||||||
|
|
||||||
|
// EncryptB64 encrypts data into base64 string
|
||||||
|
func EncryptB64(text string) string {
|
||||||
|
return base64.StdEncoding.EncodeToString([]byte(text))
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecryptB64 decrypts from base64 string to readable string
|
||||||
|
func DecryptB64(s string) (string, error) {
|
||||||
|
data, err := base64.StdEncoding.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(data), nil
|
||||||
|
}
|
114
server/crypto/common.go
Normal file
114
server/crypto/common.go
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
"gopkg.in/square/go-jose.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetPubJWK returns JWK for given keys
|
||||||
|
func GetPubJWK(algo, keyID string, publicKey interface{}) (string, error) {
|
||||||
|
jwk := &jose.JSONWebKeySet{
|
||||||
|
Keys: []jose.JSONWebKey{
|
||||||
|
{
|
||||||
|
Algorithm: algo,
|
||||||
|
Key: publicKey,
|
||||||
|
Use: "sig",
|
||||||
|
KeyID: keyID,
|
||||||
|
Certificates: []*x509.Certificate{},
|
||||||
|
CertificateThumbprintSHA1: []uint8{},
|
||||||
|
CertificateThumbprintSHA256: []uint8{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
jwkPublicKey, err := jwk.Keys[0].MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(jwkPublicKey), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateJWKBasedOnEnv generates JWK based on env
|
||||||
|
// make sure clientID, jwtType, jwtSecret / public & private key pair is set
|
||||||
|
// this is called while initializing app / when env is updated
|
||||||
|
func GenerateJWKBasedOnEnv() (string, error) {
|
||||||
|
jwk := ""
|
||||||
|
algo := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
|
||||||
|
clientID := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyClientID)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
// check if jwt secret is provided
|
||||||
|
if IsHMACA(algo) {
|
||||||
|
jwk, err = GetPubJWK(algo, clientID, []byte(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsRSA(algo) {
|
||||||
|
publicKeyInstance, err := ParseRsaPublicKeyFromPemStr(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
jwk, err = GetPubJWK(algo, clientID, publicKeyInstance)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsECDSA(algo) {
|
||||||
|
publicKeyInstance, err := ParseEcdsaPublicKeyFromPemStr(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
jwk, err = GetPubJWK(algo, clientID, publicKeyInstance)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return jwk, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncryptEnvData is used to encrypt the env data
|
||||||
|
func EncryptEnvData(data envstore.Store) (string, error) {
|
||||||
|
jsonBytes, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
storeData := envstore.EnvStoreObj.GetEnvStoreClone()
|
||||||
|
|
||||||
|
err = json.Unmarshal(jsonBytes, &storeData)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
configData, err := json.Marshal(storeData)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
encryptedConfig, err := EncryptAESEnv(configData)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return EncryptB64(string(encryptedConfig)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncryptPassword is used for encrypting password
|
||||||
|
func EncryptPassword(password string) (string, error) {
|
||||||
|
pw, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(pw), nil
|
||||||
|
}
|
154
server/crypto/ecdsa.go
Normal file
154
server/crypto/ecdsa.go
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewECDSAKey to generate new ECDSA Key if env is not set
|
||||||
|
// returns key instance, private key string, public key string, jwk string, error
|
||||||
|
func NewECDSAKey(algo, keyID string) (*ecdsa.PrivateKey, string, string, string, error) {
|
||||||
|
var curve elliptic.Curve
|
||||||
|
switch algo {
|
||||||
|
case "ES256":
|
||||||
|
curve = elliptic.P256()
|
||||||
|
case "ES384":
|
||||||
|
curve = elliptic.P384()
|
||||||
|
case "ES512":
|
||||||
|
curve = elliptic.P521()
|
||||||
|
default:
|
||||||
|
return nil, "", "", "", errors.New("Invalid algo")
|
||||||
|
}
|
||||||
|
key, err := ecdsa.GenerateKey(curve, rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey, publicKey, err := AsECDSAStr(key, &key.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
jwkPublicKey, err := GetPubJWK(algo, keyID, &key.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return key, privateKey, publicKey, string(jwkPublicKey), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsECDSA checks if given string is valid ECDSA algo
|
||||||
|
func IsECDSA(algo string) bool {
|
||||||
|
switch algo {
|
||||||
|
case "ES256", "ES384", "ES512":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportEcdsaPrivateKeyAsPemStr to get ECDSA private key as pem string
|
||||||
|
func ExportEcdsaPrivateKeyAsPemStr(privkey *ecdsa.PrivateKey) (string, error) {
|
||||||
|
privkeyBytes, err := x509.MarshalECPrivateKey(privkey)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
privkeyPem := pem.EncodeToMemory(
|
||||||
|
&pem.Block{
|
||||||
|
Type: "ECDSA PRIVATE KEY",
|
||||||
|
Bytes: privkeyBytes,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return string(privkeyPem), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportEcdsaPublicKeyAsPemStr to get ECDSA public key as pem string
|
||||||
|
func ExportEcdsaPublicKeyAsPemStr(pubkey *ecdsa.PublicKey) (string, error) {
|
||||||
|
pubkeyBytes, err := x509.MarshalPKIXPublicKey(pubkey)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
pubkeyPem := pem.EncodeToMemory(
|
||||||
|
&pem.Block{
|
||||||
|
Type: "ECDSA PUBLIC KEY",
|
||||||
|
Bytes: pubkeyBytes,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return string(pubkeyPem), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseEcdsaPrivateKeyFromPemStr to parse ECDSA private key from pem string
|
||||||
|
func ParseEcdsaPrivateKeyFromPemStr(privPEM string) (*ecdsa.PrivateKey, error) {
|
||||||
|
block, _ := pem.Decode([]byte(privPEM))
|
||||||
|
if block == nil {
|
||||||
|
return nil, errors.New("failed to parse PEM block containing the key")
|
||||||
|
}
|
||||||
|
|
||||||
|
priv, err := x509.ParseECPrivateKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return priv, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseEcdsaPublicKeyFromPemStr to parse ECDSA public key from pem string
|
||||||
|
func ParseEcdsaPublicKeyFromPemStr(pubPEM string) (*ecdsa.PublicKey, error) {
|
||||||
|
block, _ := pem.Decode([]byte(pubPEM))
|
||||||
|
if block == nil {
|
||||||
|
return nil, errors.New("failed to parse PEM block containing the key")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch pub := pub.(type) {
|
||||||
|
case *ecdsa.PublicKey:
|
||||||
|
return pub, nil
|
||||||
|
default:
|
||||||
|
break // fall through
|
||||||
|
}
|
||||||
|
return nil, errors.New("Key type is not ECDSA")
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsECDSAStr returns private, public key string or error
|
||||||
|
func AsECDSAStr(privateKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey) (string, string, error) {
|
||||||
|
// Export the keys to pem string
|
||||||
|
privPem, err := ExportEcdsaPrivateKeyAsPemStr(privateKey)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
pubPem, err := ExportEcdsaPublicKeyAsPemStr(publicKey)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import the keys from pem string
|
||||||
|
privParsed, err := ParseEcdsaPrivateKeyFromPemStr(privPem)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
pubParsed, err := ParseEcdsaPublicKeyFromPemStr(pubPem)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export the newly imported keys
|
||||||
|
privParsedPem, err := ExportEcdsaPrivateKeyAsPemStr(privParsed)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
pubParsedPem, err := ExportEcdsaPublicKeyAsPemStr(pubParsed)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return privParsedPem, pubParsedPem, nil
|
||||||
|
}
|
26
server/crypto/hmac.go
Normal file
26
server/crypto/hmac.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewHMAC key returns new key that can be used to ecnrypt data using HMAC algo
|
||||||
|
// returns key, string, error
|
||||||
|
func NewHMACKey(algo, keyID string) (string, string, error) {
|
||||||
|
key := uuid.New().String()
|
||||||
|
jwkPublicKey, err := GetPubJWK(algo, keyID, []byte(key))
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
return key, string(jwkPublicKey), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHMACValid checks if given string is valid HMCA algo
|
||||||
|
func IsHMACA(algo string) bool {
|
||||||
|
switch algo {
|
||||||
|
case "HS256", "HS384", "HS512":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
118
server/crypto/rsa.go
Normal file
118
server/crypto/rsa.go
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewRSAKey to generate new RSA Key if env is not set
|
||||||
|
// returns key instance, private key string, public key string, jwk string, error
|
||||||
|
func NewRSAKey(algo, keyID string) (*rsa.PrivateKey, string, string, string, error) {
|
||||||
|
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey, publicKey, err := AsRSAStr(key, &key.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
jwkPublicKey, err := GetPubJWK(algo, keyID, &key.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return key, privateKey, publicKey, string(jwkPublicKey), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRSA checks if given string is valid RSA algo
|
||||||
|
func IsRSA(algo string) bool {
|
||||||
|
switch algo {
|
||||||
|
case "RS256", "RS384", "RS512":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportRsaPrivateKeyAsPemStr to get RSA private key as pem string
|
||||||
|
func ExportRsaPrivateKeyAsPemStr(privkey *rsa.PrivateKey) string {
|
||||||
|
privkeyBytes := x509.MarshalPKCS1PrivateKey(privkey)
|
||||||
|
privkeyPem := pem.EncodeToMemory(
|
||||||
|
&pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: privkeyBytes,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return string(privkeyPem)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportRsaPublicKeyAsPemStr to get RSA public key as pem string
|
||||||
|
func ExportRsaPublicKeyAsPemStr(pubkey *rsa.PublicKey) string {
|
||||||
|
pubkeyBytes := x509.MarshalPKCS1PublicKey(pubkey)
|
||||||
|
pubkeyPem := pem.EncodeToMemory(
|
||||||
|
&pem.Block{
|
||||||
|
Type: "RSA PUBLIC KEY",
|
||||||
|
Bytes: pubkeyBytes,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return string(pubkeyPem)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseRsaPrivateKeyFromPemStr to parse RSA private key from pem string
|
||||||
|
func ParseRsaPrivateKeyFromPemStr(privPEM string) (*rsa.PrivateKey, error) {
|
||||||
|
block, _ := pem.Decode([]byte(privPEM))
|
||||||
|
if block == nil {
|
||||||
|
return nil, errors.New("failed to parse PEM block containing the key")
|
||||||
|
}
|
||||||
|
|
||||||
|
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return priv, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseRsaPublicKeyFromPemStr to parse RSA public key from pem string
|
||||||
|
func ParseRsaPublicKeyFromPemStr(pubPEM string) (*rsa.PublicKey, error) {
|
||||||
|
block, _ := pem.Decode([]byte(pubPEM))
|
||||||
|
if block == nil {
|
||||||
|
return nil, errors.New("failed to parse PEM block containing the key")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub, err := x509.ParsePKCS1PublicKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pub, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsRSAStr returns private, public key string or error
|
||||||
|
func AsRSAStr(privateKey *rsa.PrivateKey, publickKey *rsa.PublicKey) (string, string, error) {
|
||||||
|
// Export the keys to pem string
|
||||||
|
privPem := ExportRsaPrivateKeyAsPemStr(privateKey)
|
||||||
|
pubPem := ExportRsaPublicKeyAsPemStr(publickKey)
|
||||||
|
|
||||||
|
// Import the keys from pem string
|
||||||
|
privParsed, err := ParseRsaPrivateKeyFromPemStr(privPem)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
pubParsed, err := ParseRsaPublicKeyFromPemStr(pubPem)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export the newly imported keys
|
||||||
|
privParsedPem := ExportRsaPrivateKeyAsPemStr(privParsed)
|
||||||
|
pubParsedPem := ExportRsaPublicKeyAsPemStr(pubParsed)
|
||||||
|
|
||||||
|
return privParsedPem, pubParsedPem, nil
|
||||||
|
}
|
@@ -1,8 +1,6 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db/providers"
|
"github.com/authorizerdev/authorizer/server/db/providers"
|
||||||
"github.com/authorizerdev/authorizer/server/db/providers/arangodb"
|
"github.com/authorizerdev/authorizer/server/db/providers/arangodb"
|
||||||
@@ -14,31 +12,33 @@ import (
|
|||||||
// Provider returns the current database provider
|
// Provider returns the current database provider
|
||||||
var Provider providers.Provider
|
var Provider providers.Provider
|
||||||
|
|
||||||
func InitDB() {
|
func InitDB() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
isSQL := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeArangodb && envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeMongodb
|
isSQL := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeArangodb && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeMongodb
|
||||||
isArangoDB := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeArangodb
|
isArangoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeArangodb
|
||||||
isMongoDB := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeMongodb
|
isMongoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeMongodb
|
||||||
|
|
||||||
if isSQL {
|
if isSQL {
|
||||||
Provider, err = sql.NewProvider()
|
Provider, err = sql.NewProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("=> error setting sql provider:", err)
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isArangoDB {
|
if isArangoDB {
|
||||||
Provider, err = arangodb.NewProvider()
|
Provider, err = arangodb.NewProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("=> error setting arangodb provider:", err)
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isMongoDB {
|
if isMongoDB {
|
||||||
Provider, err = mongodb.NewProvider()
|
Provider, err = mongodb.NewProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("=> error setting arangodb provider:", err)
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,7 @@ type VerificationRequest struct {
|
|||||||
CreatedAt int64 `json:"created_at" bson:"created_at"`
|
CreatedAt int64 `json:"created_at" bson:"created_at"`
|
||||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at"`
|
UpdatedAt int64 `json:"updated_at" bson:"updated_at"`
|
||||||
Email string `gorm:"uniqueIndex:idx_email_identifier" json:"email" bson:"email"`
|
Email string `gorm:"uniqueIndex:idx_email_identifier" json:"email" bson:"email"`
|
||||||
|
Nonce string `gorm:"type:char(36)" json:"nonce" bson:"nonce"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VerificationRequest) AsAPIVerificationRequest() *model.VerificationRequest {
|
func (v *VerificationRequest) AsAPIVerificationRequest() *model.VerificationRequest {
|
||||||
|
@@ -24,7 +24,7 @@ type provider struct {
|
|||||||
func NewProvider() (*provider, error) {
|
func NewProvider() (*provider, error) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
conn, err := http.NewConnection(http.ConnectionConfig{
|
conn, err := http.NewConnection(http.ConnectionConfig{
|
||||||
Endpoints: []string{envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)},
|
Endpoints: []string{envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -39,16 +39,16 @@ func NewProvider() (*provider, error) {
|
|||||||
|
|
||||||
var arangodb driver.Database
|
var arangodb driver.Database
|
||||||
|
|
||||||
arangodb_exists, err := arangoClient.DatabaseExists(nil, envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName))
|
arangodb_exists, err := arangoClient.DatabaseExists(nil, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName))
|
||||||
|
|
||||||
if arangodb_exists {
|
if arangodb_exists {
|
||||||
log.Println(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName) + " db exists already")
|
log.Println(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName) + " db exists already")
|
||||||
arangodb, err = arangoClient.Database(nil, envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName))
|
arangodb, err = arangoClient.Database(nil, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
arangodb, err = arangoClient.CreateDatabase(nil, envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName), nil)
|
arangodb, err = arangoClient.CreateDatabase(nil, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -34,7 +34,6 @@ func (p *provider) DeleteSession(userId string) error {
|
|||||||
}
|
}
|
||||||
cursor, err := p.db.Query(nil, query, bindVars)
|
cursor, err := p.db.Query(nil, query, bindVars)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("=> error deleting arangodb session:", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer cursor.Close()
|
defer cursor.Close()
|
||||||
|
@@ -23,7 +23,7 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if user.Roles == "" {
|
if user.Roles == "" {
|
||||||
user.Roles = strings.Join(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
user.Roles = strings.Join(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
user.CreatedAt = time.Now().Unix()
|
user.CreatedAt = time.Now().Unix()
|
||||||
|
@@ -19,7 +19,7 @@ type provider struct {
|
|||||||
|
|
||||||
// NewProvider to initialize mongodb connection
|
// NewProvider to initialize mongodb connection
|
||||||
func NewProvider() (*provider, error) {
|
func NewProvider() (*provider, error) {
|
||||||
mongodbOptions := options.Client().ApplyURI(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL))
|
mongodbOptions := options.Client().ApplyURI(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL))
|
||||||
maxWait := time.Duration(5 * time.Second)
|
maxWait := time.Duration(5 * time.Second)
|
||||||
mongodbOptions.ConnectTimeout = &maxWait
|
mongodbOptions.ConnectTimeout = &maxWait
|
||||||
mongoClient, err := mongo.NewClient(mongodbOptions)
|
mongoClient, err := mongo.NewClient(mongodbOptions)
|
||||||
@@ -37,7 +37,7 @@ func NewProvider() (*provider, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mongodb := mongoClient.Database(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName), options.Database())
|
mongodb := mongoClient.Database(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName), options.Database())
|
||||||
|
|
||||||
mongodb.CreateCollection(ctx, models.Collections.User, options.CreateCollection())
|
mongodb.CreateCollection(ctx, models.Collections.User, options.CreateCollection())
|
||||||
userCollection := mongodb.Collection(models.Collections.User, options.Collection())
|
userCollection := mongodb.Collection(models.Collections.User, options.Collection())
|
||||||
|
@@ -21,7 +21,7 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if user.Roles == "" {
|
if user.Roles == "" {
|
||||||
user.Roles = strings.Join(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
user.Roles = strings.Join(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
||||||
}
|
}
|
||||||
user.CreatedAt = time.Now().Unix()
|
user.CreatedAt = time.Now().Unix()
|
||||||
user.UpdatedAt = time.Now().Unix()
|
user.UpdatedAt = time.Now().Unix()
|
||||||
|
@@ -41,26 +41,25 @@ func NewProvider() (*provider, error) {
|
|||||||
TablePrefix: models.Prefix,
|
TablePrefix: models.Prefix,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
switch envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) {
|
switch envstore.EnvStoreObj.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.EnvStoreObj.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.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
||||||
break
|
case constants.DbTypeMysql, constants.DbTypeMariaDB:
|
||||||
case constants.DbTypeMysql:
|
sqlDB, err = gorm.Open(mysql.Open(envstore.EnvStoreObj.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.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlDB.AutoMigrate(&models.User{}, &models.VerificationRequest{}, &models.Session{}, &models.Env{})
|
err = sqlDB.AutoMigrate(&models.User{}, &models.VerificationRequest{}, &models.Session{}, &models.Env{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &provider{
|
return &provider{
|
||||||
db: sqlDB,
|
db: sqlDB,
|
||||||
}, nil
|
}, nil
|
||||||
|
@@ -20,7 +20,7 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if user.Roles == "" {
|
if user.Roles == "" {
|
||||||
user.Roles = strings.Join(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
user.Roles = strings.Join(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
user.CreatedAt = time.Now().Unix()
|
user.CreatedAt = time.Now().Unix()
|
||||||
|
@@ -31,14 +31,18 @@ func addEmailTemplate(a string, b map[string]interface{}, templateName string) s
|
|||||||
|
|
||||||
// SendMail function to send mail
|
// SendMail function to send mail
|
||||||
func SendMail(to []string, Subject, bodyMessage string) error {
|
func SendMail(to []string, Subject, bodyMessage string) error {
|
||||||
|
// dont trigger email sending in case of test
|
||||||
|
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEnv) == "test" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
m := gomail.NewMessage()
|
m := gomail.NewMessage()
|
||||||
m.SetHeader("From", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeySenderEmail))
|
m.SetHeader("From", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeySenderEmail))
|
||||||
m.SetHeader("To", to...)
|
m.SetHeader("To", to...)
|
||||||
m.SetHeader("Subject", Subject)
|
m.SetHeader("Subject", Subject)
|
||||||
m.SetBody("text/html", bodyMessage)
|
m.SetBody("text/html", bodyMessage)
|
||||||
port, _ := strconv.Atoi(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeySmtpPort))
|
port, _ := strconv.Atoi(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeySmtpPort))
|
||||||
d := gomail.NewDialer(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeySmtpHost), port, envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeySmtpUsername), envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeySmtpPassword))
|
d := gomail.NewDialer(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeySmtpHost), port, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeySmtpUsername), envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeySmtpPassword))
|
||||||
if envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEnv) == "development" {
|
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEnv) == "development" {
|
||||||
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||||
}
|
}
|
||||||
if err := d.DialAndSend(m); err != nil {
|
if err := d.DialAndSend(m); err != nil {
|
||||||
|
@@ -7,9 +7,9 @@ import (
|
|||||||
|
|
||||||
// SendForgotPasswordMail to send forgot password email
|
// SendForgotPasswordMail to send forgot password email
|
||||||
func SendForgotPasswordMail(toEmail, token, hostname string) error {
|
func SendForgotPasswordMail(toEmail, token, hostname string) error {
|
||||||
resetPasswordUrl := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyResetPasswordURL)
|
resetPasswordUrl := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyResetPasswordURL)
|
||||||
if resetPasswordUrl == "" {
|
if resetPasswordUrl == "" {
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyResetPasswordURL, hostname+"/app/reset-password")
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyResetPasswordURL, hostname+"/app/reset-password")
|
||||||
}
|
}
|
||||||
|
|
||||||
// The receiver needs to be in slice as the receive supports multiple receiver
|
// The receiver needs to be in slice as the receive supports multiple receiver
|
||||||
@@ -103,8 +103,8 @@ func SendForgotPasswordMail(toEmail, token, hostname string) error {
|
|||||||
`
|
`
|
||||||
|
|
||||||
data := make(map[string]interface{}, 3)
|
data := make(map[string]interface{}, 3)
|
||||||
data["org_logo"] = envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
|
data["org_logo"] = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
|
||||||
data["org_name"] = envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
|
data["org_name"] = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
|
||||||
data["verification_url"] = resetPasswordUrl + "?token=" + token
|
data["verification_url"] = resetPasswordUrl + "?token=" + token
|
||||||
message = addEmailTemplate(message, data, "reset_password_email.tmpl")
|
message = addEmailTemplate(message, data, "reset_password_email.tmpl")
|
||||||
|
|
||||||
|
@@ -97,8 +97,8 @@ func SendVerificationMail(toEmail, token, hostname string) error {
|
|||||||
</html>
|
</html>
|
||||||
`
|
`
|
||||||
data := make(map[string]interface{}, 3)
|
data := make(map[string]interface{}, 3)
|
||||||
data["org_logo"] = envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
|
data["org_logo"] = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
|
||||||
data["org_name"] = envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
|
data["org_name"] = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
|
||||||
data["verification_url"] = hostname + "/verify_email?token=" + token
|
data["verification_url"] = hostname + "/verify_email?token=" + token
|
||||||
message = addEmailTemplate(message, data, "verify_email.tmpl")
|
message = addEmailTemplate(message, data, "verify_email.tmpl")
|
||||||
// bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
// bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
||||||
|
284
server/env/env.go
vendored
284
server/env/env.go
vendored
@@ -1,11 +1,13 @@
|
|||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"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/gin-gonic/gin"
|
||||||
@@ -13,13 +15,88 @@ import (
|
|||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// InitRequiredEnv to initialize EnvData and through error if required env are not present
|
||||||
|
func InitRequiredEnv() error {
|
||||||
|
envPath := os.Getenv(constants.EnvKeyEnvPath)
|
||||||
|
|
||||||
|
if envPath == "" {
|
||||||
|
envPath = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyEnvPath)
|
||||||
|
if envPath == "" {
|
||||||
|
envPath = `.env`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if envstore.ARG_ENV_FILE != nil && *envstore.ARG_ENV_FILE != "" {
|
||||||
|
envPath = *envstore.ARG_ENV_FILE
|
||||||
|
}
|
||||||
|
|
||||||
|
err := godotenv.Load(envPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("using OS env instead of %s file", envPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
dbURL := os.Getenv(constants.EnvKeyDatabaseURL)
|
||||||
|
dbType := os.Getenv(constants.EnvKeyDatabaseType)
|
||||||
|
dbName := os.Getenv(constants.EnvKeyDatabaseName)
|
||||||
|
|
||||||
|
if strings.TrimSpace(dbType) == "" {
|
||||||
|
if envstore.ARG_DB_TYPE != nil && *envstore.ARG_DB_TYPE != "" {
|
||||||
|
dbType = strings.TrimSpace(*envstore.ARG_DB_TYPE)
|
||||||
|
}
|
||||||
|
|
||||||
|
if dbType == "" {
|
||||||
|
return errors.New("invalid database type. DATABASE_TYPE is empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.TrimSpace(dbURL) == "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL) == "" {
|
||||||
|
if envstore.ARG_DB_URL != nil && *envstore.ARG_DB_URL != "" {
|
||||||
|
dbURL = strings.TrimSpace(*envstore.ARG_DB_URL)
|
||||||
|
}
|
||||||
|
|
||||||
|
if dbURL == "" {
|
||||||
|
return errors.New("invalid database url. DATABASE_URL is required")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if dbName == "" {
|
||||||
|
if dbName == "" {
|
||||||
|
dbName = "authorizer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEnvPath, envPath)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseURL, dbURL)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseType, dbType)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseName, dbName)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// InitEnv to initialize EnvData and through error if required env are not present
|
// InitEnv to initialize EnvData and through error if required env are not present
|
||||||
func InitEnv() {
|
func InitAllEnv() error {
|
||||||
// get clone of current store
|
envData, err := GetEnvData()
|
||||||
envData := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
if err != nil {
|
||||||
|
log.Println("No env data found in db, using local clone of env data")
|
||||||
|
// get clone of current store
|
||||||
|
envData = envstore.EnvStoreObj.GetEnvStoreClone()
|
||||||
|
}
|
||||||
|
|
||||||
|
clientID := envData.StringEnv[constants.EnvKeyClientID]
|
||||||
|
// unique client id for each instance
|
||||||
|
if clientID == "" {
|
||||||
|
clientID = uuid.New().String()
|
||||||
|
envData.StringEnv[constants.EnvKeyClientID] = clientID
|
||||||
|
}
|
||||||
|
|
||||||
|
clientSecret := envData.StringEnv[constants.EnvKeyClientSecret]
|
||||||
|
// unique client id for each instance
|
||||||
|
if clientSecret == "" {
|
||||||
|
clientSecret = uuid.New().String()
|
||||||
|
envData.StringEnv[constants.EnvKeyClientSecret] = clientSecret
|
||||||
|
}
|
||||||
|
|
||||||
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"
|
||||||
}
|
}
|
||||||
@@ -36,146 +113,174 @@ func InitEnv() {
|
|||||||
envData.StringEnv[constants.EnvKeyAppURL] = os.Getenv(constants.EnvKeyAppURL)
|
envData.StringEnv[constants.EnvKeyAppURL] = os.Getenv(constants.EnvKeyAppURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyEnvPath] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyEnvPath] = `.env`
|
|
||||||
}
|
|
||||||
|
|
||||||
if envstore.ARG_ENV_FILE != nil && *envstore.ARG_ENV_FILE != "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyEnvPath] = *envstore.ARG_ENV_FILE
|
|
||||||
}
|
|
||||||
|
|
||||||
err := godotenv.Load(envData.StringEnv[constants.EnvKeyEnvPath])
|
|
||||||
if err != nil {
|
|
||||||
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] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyDatabaseType] = os.Getenv("DATABASE_TYPE")
|
|
||||||
|
|
||||||
if envstore.ARG_DB_TYPE != nil && *envstore.ARG_DB_TYPE != "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyDatabaseType] = *envstore.ARG_DB_TYPE
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyDatabaseType] == "" {
|
|
||||||
panic("DATABASE_TYPE is required")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyDatabaseURL] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyDatabaseURL] = os.Getenv("DATABASE_URL")
|
|
||||||
|
|
||||||
if envstore.ARG_DB_URL != nil && *envstore.ARG_DB_URL != "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyDatabaseURL] = *envstore.ARG_DB_URL
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyDatabaseURL] == "" {
|
|
||||||
panic("DATABASE_URL is required")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyDatabaseName] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyDatabaseName] = os.Getenv("DATABASE_NAME")
|
|
||||||
if envData.StringEnv[constants.EnvKeyDatabaseName] == "" {
|
|
||||||
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] == "" {
|
algo := envData.StringEnv[constants.EnvKeyJwtType]
|
||||||
envData.StringEnv[constants.EnvKeyJwtSecret] = os.Getenv("JWT_SECRET")
|
if algo == "" {
|
||||||
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" {
|
envData.StringEnv[constants.EnvKeyJwtType] = os.Getenv(constants.EnvKeyJwtType)
|
||||||
envData.StringEnv[constants.EnvKeyJwtSecret] = uuid.New().String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyJwtType] == "" {
|
|
||||||
envData.StringEnv[constants.EnvKeyJwtType] = os.Getenv("JWT_TYPE")
|
|
||||||
if envData.StringEnv[constants.EnvKeyJwtType] == "" {
|
if envData.StringEnv[constants.EnvKeyJwtType] == "" {
|
||||||
envData.StringEnv[constants.EnvKeyJwtType] = "HS256"
|
envData.StringEnv[constants.EnvKeyJwtType] = "RS256"
|
||||||
|
algo = envData.StringEnv[constants.EnvKeyJwtType]
|
||||||
|
} else {
|
||||||
|
algo = envData.StringEnv[constants.EnvKeyJwtType]
|
||||||
|
if !crypto.IsHMACA(algo) && !crypto.IsRSA(algo) && !crypto.IsECDSA(algo) {
|
||||||
|
return errors.New("invalid JWT_TYPE")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if crypto.IsHMACA(algo) {
|
||||||
|
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" {
|
||||||
|
envData.StringEnv[constants.EnvKeyJwtSecret] = os.Getenv(constants.EnvKeyJwtSecret)
|
||||||
|
if envData.StringEnv[constants.EnvKeyJwtSecret] == "" {
|
||||||
|
envData.StringEnv[constants.EnvKeyJwtSecret], _, err = crypto.NewHMACKey(algo, clientID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if crypto.IsRSA(algo) || crypto.IsECDSA(algo) {
|
||||||
|
privateKey, publicKey := "", ""
|
||||||
|
|
||||||
|
if envData.StringEnv[constants.EnvKeyJwtPrivateKey] == "" {
|
||||||
|
privateKey = os.Getenv(constants.EnvKeyJwtPrivateKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
if envData.StringEnv[constants.EnvKeyJwtPublicKey] == "" {
|
||||||
|
publicKey = os.Getenv(constants.EnvKeyJwtPublicKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if algo is RSA / ECDSA, then we need to have both private and public key
|
||||||
|
// if either of them is not present generate new keys
|
||||||
|
if privateKey == "" || publicKey == "" {
|
||||||
|
if crypto.IsRSA(algo) {
|
||||||
|
_, privateKey, publicKey, _, err = crypto.NewRSAKey(algo, clientID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if crypto.IsECDSA(algo) {
|
||||||
|
_, privateKey, publicKey, _, err = crypto.NewECDSAKey(algo, clientID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// parse keys to make sure they are valid
|
||||||
|
if crypto.IsRSA(algo) {
|
||||||
|
_, err = crypto.ParseRsaPrivateKeyFromPemStr(privateKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := crypto.ParseRsaPublicKeyFromPemStr(publicKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if crypto.IsECDSA(algo) {
|
||||||
|
_, err = crypto.ParseEcdsaPrivateKeyFromPemStr(privateKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := crypto.ParseEcdsaPublicKeyFromPemStr(publicKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
envData.StringEnv[constants.EnvKeyJwtPrivateKey] = privateKey
|
||||||
|
envData.StringEnv[constants.EnvKeyJwtPublicKey] = publicKey
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if envData.StringEnv[constants.EnvKeyCustomAccessTokenScript] == "" {
|
||||||
|
envData.StringEnv[constants.EnvKeyCustomAccessTokenScript] = os.Getenv(constants.EnvKeyCustomAccessTokenScript)
|
||||||
|
}
|
||||||
|
|
||||||
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 +292,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 +320,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 +335,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{}
|
||||||
|
|
||||||
@@ -252,20 +357,21 @@ func InitEnv() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(roles) > 0 && len(defaultRoles) == 0 && len(defaultRolesEnv) > 0 {
|
if len(roles) > 0 && len(defaultRoles) == 0 && len(defaultRolesEnv) > 0 {
|
||||||
panic(`Invalid DEFAULT_ROLE environment variable. It can be one from give ROLES environment variable value`)
|
return errors.New(`invalid DEFAULT_ROLE environment variable. It can be one from give ROLES environment variable value`)
|
||||||
}
|
}
|
||||||
|
|
||||||
envData.SliceEnv[constants.EnvKeyRoles] = roles
|
envData.SliceEnv[constants.EnvKeyRoles] = roles
|
||||||
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.EnvStoreObj.UpdateEnvStore(envData)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
80
server/env/persist_env.go
vendored
80
server/env/persist_env.go
vendored
@@ -7,14 +7,51 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"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"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetEnvData returns the env data from database
|
||||||
|
func GetEnvData() (envstore.Store, error) {
|
||||||
|
var result envstore.Store
|
||||||
|
env, err := db.Provider.GetEnv()
|
||||||
|
// config not found in db
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
encryptionKey := env.Hash
|
||||||
|
decryptedEncryptionKey, err := crypto.DecryptB64(encryptionKey)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEncryptionKey, decryptedEncryptionKey)
|
||||||
|
|
||||||
|
b64DecryptedConfig, err := crypto.DecryptB64(env.EnvData)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
decryptedConfigs, err := crypto.DecryptAESEnv([]byte(b64DecryptedConfig))
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(decryptedConfigs, &result)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
// PersistEnv persists the environment variables to the database
|
// PersistEnv persists the environment variables to the database
|
||||||
func PersistEnv() error {
|
func PersistEnv() error {
|
||||||
env, err := db.Provider.GetEnv()
|
env, err := db.Provider.GetEnv()
|
||||||
@@ -22,45 +59,40 @@ func PersistEnv() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
// AES encryption needs 32 bit key only, so we chop off last 4 characters from 36 bit uuid
|
// AES encryption needs 32 bit key only, so we chop off last 4 characters from 36 bit uuid
|
||||||
hash := uuid.New().String()[:36-4]
|
hash := uuid.New().String()[:36-4]
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEncryptionKey, hash)
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEncryptionKey, hash)
|
||||||
encodedHash := utils.EncryptB64(hash)
|
encodedHash := crypto.EncryptB64(hash)
|
||||||
|
|
||||||
encryptedConfig, err := utils.EncryptEnvData(envstore.EnvInMemoryStoreObj.GetEnvStoreClone())
|
encryptedConfig, err := crypto.EncryptEnvData(envstore.EnvStoreObj.GetEnvStoreClone())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// configData, err := json.Marshal()
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// encryptedConfig, err := utils.EncryptAES(configData)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
env = models.Env{
|
env = models.Env{
|
||||||
Hash: encodedHash,
|
Hash: encodedHash,
|
||||||
EnvData: encryptedConfig,
|
EnvData: encryptedConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Provider.AddEnv(env)
|
env, err = db.Provider.AddEnv(env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// decrypt the config data from db
|
// decrypt the config data from db
|
||||||
// decryption can be done using the hash stored in db
|
// decryption can be done using the hash stored in db
|
||||||
encryptionKey := env.Hash
|
encryptionKey := env.Hash
|
||||||
decryptedEncryptionKey, err := utils.DecryptB64(encryptionKey)
|
decryptedEncryptionKey, err := crypto.DecryptB64(encryptionKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEncryptionKey, decryptedEncryptionKey)
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEncryptionKey, decryptedEncryptionKey)
|
||||||
b64DecryptedConfig, err := utils.DecryptB64(env.EnvData)
|
|
||||||
|
b64DecryptedConfig, err := crypto.DecryptB64(env.EnvData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptedConfigs, err := utils.DecryptAES([]byte(b64DecryptedConfig))
|
decryptedConfigs, err := crypto.DecryptAESEnv([]byte(b64DecryptedConfig))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -79,6 +111,7 @@ func PersistEnv() error {
|
|||||||
hasChanged := false
|
hasChanged := false
|
||||||
|
|
||||||
for key, value := range storeData.StringEnv {
|
for key, value := range storeData.StringEnv {
|
||||||
|
// don't override unexposed envs
|
||||||
if key != constants.EnvKeyEncryptionKey {
|
if key != constants.EnvKeyEncryptionKey {
|
||||||
// check only for derivative keys
|
// check only for derivative keys
|
||||||
// No need to check for ENCRYPTION_KEY which special key we use for encrypting config data
|
// No need to check for ENCRYPTION_KEY which special key we use for encrypting config data
|
||||||
@@ -132,10 +165,16 @@ func PersistEnv() error {
|
|||||||
hasChanged = true
|
hasChanged = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
envstore.EnvStoreObj.UpdateEnvStore(storeData)
|
||||||
|
jwk, err := crypto.GenerateJWKBasedOnEnv()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// updating jwk
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJWK, jwk)
|
||||||
|
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvStore(storeData)
|
|
||||||
if hasChanged {
|
if hasChanged {
|
||||||
encryptedConfig, err := utils.EncryptEnvData(storeData)
|
encryptedConfig, err := crypto.EncryptEnvData(storeData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -147,7 +186,6 @@ func PersistEnv() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@@ -22,14 +22,13 @@ type Store struct {
|
|||||||
SliceEnv map[string][]string `json:"slice_env"`
|
SliceEnv map[string][]string `json:"slice_env"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnvInMemoryStore struct
|
// EnvStore struct
|
||||||
type EnvInMemoryStore struct {
|
type EnvStore struct {
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
store *Store
|
store *Store
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnvInMemoryStoreObj global variable for EnvInMemoryStore
|
var defaultStore = &EnvStore{
|
||||||
var EnvInMemoryStoreObj = &EnvInMemoryStore{
|
|
||||||
store: &Store{
|
store: &Store{
|
||||||
StringEnv: map[string]string{
|
StringEnv: map[string]string{
|
||||||
constants.EnvKeyAdminCookieName: "authorizer-admin",
|
constants.EnvKeyAdminCookieName: "authorizer-admin",
|
||||||
@@ -47,8 +46,11 @@ var EnvInMemoryStoreObj = &EnvInMemoryStore{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnvStoreObj.GetBoolStoreEnvVariable global variable for EnvStore
|
||||||
|
var EnvStoreObj = defaultStore
|
||||||
|
|
||||||
// UpdateEnvStore to update the whole env store object
|
// UpdateEnvStore to update the whole env store object
|
||||||
func (e *EnvInMemoryStore) UpdateEnvStore(store Store) {
|
func (e *EnvStore) UpdateEnvStore(store Store) {
|
||||||
e.mutex.Lock()
|
e.mutex.Lock()
|
||||||
defer e.mutex.Unlock()
|
defer e.mutex.Unlock()
|
||||||
// just override the keys + new keys
|
// just override the keys + new keys
|
||||||
@@ -67,7 +69,7 @@ func (e *EnvInMemoryStore) UpdateEnvStore(store Store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateEnvVariable to update the particular env variable
|
// UpdateEnvVariable to update the particular env variable
|
||||||
func (e *EnvInMemoryStore) UpdateEnvVariable(storeIdentifier, key string, value interface{}) {
|
func (e *EnvStore) UpdateEnvVariable(storeIdentifier, key string, value interface{}) {
|
||||||
e.mutex.Lock()
|
e.mutex.Lock()
|
||||||
defer e.mutex.Unlock()
|
defer e.mutex.Unlock()
|
||||||
switch storeIdentifier {
|
switch storeIdentifier {
|
||||||
@@ -81,31 +83,37 @@ func (e *EnvInMemoryStore) UpdateEnvVariable(storeIdentifier, key string, value
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetStringStoreEnvVariable to get the env variable from string store object
|
// GetStringStoreEnvVariable to get the env variable from string store object
|
||||||
func (e *EnvInMemoryStore) GetStringStoreEnvVariable(key string) string {
|
func (e *EnvStore) GetStringStoreEnvVariable(key string) string {
|
||||||
// e.mutex.Lock()
|
// e.mutex.Lock()
|
||||||
// defer e.mutex.Unlock()
|
// defer e.mutex.Unlock()
|
||||||
return e.store.StringEnv[key]
|
return e.store.StringEnv[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBoolStoreEnvVariable to get the env variable from bool store object
|
// GetBoolStoreEnvVariable to get the env variable from bool store object
|
||||||
func (e *EnvInMemoryStore) GetBoolStoreEnvVariable(key string) bool {
|
func (e *EnvStore) GetBoolStoreEnvVariable(key string) bool {
|
||||||
// e.mutex.Lock()
|
// e.mutex.Lock()
|
||||||
// defer e.mutex.Unlock()
|
// defer e.mutex.Unlock()
|
||||||
return e.store.BoolEnv[key]
|
return e.store.BoolEnv[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSliceStoreEnvVariable to get the env variable from slice store object
|
// GetSliceStoreEnvVariable to get the env variable from slice store object
|
||||||
func (e *EnvInMemoryStore) GetSliceStoreEnvVariable(key string) []string {
|
func (e *EnvStore) GetSliceStoreEnvVariable(key string) []string {
|
||||||
// e.mutex.Lock()
|
// e.mutex.Lock()
|
||||||
// defer e.mutex.Unlock()
|
// defer e.mutex.Unlock()
|
||||||
return e.store.SliceEnv[key]
|
return e.store.SliceEnv[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEnvStoreClone to get clone of current env store object
|
// GetEnvStoreClone to get clone of current env store object
|
||||||
func (e *EnvInMemoryStore) GetEnvStoreClone() Store {
|
func (e *EnvStore) GetEnvStoreClone() Store {
|
||||||
e.mutex.Lock()
|
e.mutex.Lock()
|
||||||
defer e.mutex.Unlock()
|
defer e.mutex.Unlock()
|
||||||
|
|
||||||
result := *e.store
|
result := *e.store
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *EnvStore) ResetStore() {
|
||||||
|
e.mutex.Lock()
|
||||||
|
defer e.mutex.Unlock()
|
||||||
|
e.store = defaultStore.store
|
||||||
|
}
|
||||||
|
@@ -30,6 +30,7 @@ require (
|
|||||||
google.golang.org/protobuf v1.27.1 // indirect
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/mail.v2 v2.3.1
|
gopkg.in/mail.v2 v2.3.1
|
||||||
|
gopkg.in/square/go-jose.v2 v2.6.0
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gorm.io/driver/mysql v1.2.1
|
gorm.io/driver/mysql v1.2.1
|
||||||
gorm.io/driver/postgres v1.2.3
|
gorm.io/driver/postgres v1.2.3
|
||||||
|
@@ -682,8 +682,9 @@ gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
|
|||||||
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=
|
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=
|
||||||
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
|
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
|
||||||
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
|
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
|
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
|
||||||
|
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
@@ -44,16 +44,20 @@ type DirectiveRoot struct {
|
|||||||
|
|
||||||
type ComplexityRoot struct {
|
type ComplexityRoot struct {
|
||||||
AuthResponse struct {
|
AuthResponse struct {
|
||||||
AccessToken func(childComplexity int) int
|
AccessToken func(childComplexity int) int
|
||||||
ExpiresAt func(childComplexity int) int
|
ExpiresIn func(childComplexity int) int
|
||||||
Message func(childComplexity int) int
|
IDToken func(childComplexity int) int
|
||||||
User func(childComplexity int) int
|
Message func(childComplexity int) int
|
||||||
|
RefreshToken func(childComplexity int) int
|
||||||
|
User func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
Env struct {
|
Env struct {
|
||||||
AdminSecret func(childComplexity int) int
|
AdminSecret func(childComplexity int) int
|
||||||
AllowedOrigins func(childComplexity int) int
|
AllowedOrigins func(childComplexity int) int
|
||||||
AppURL func(childComplexity int) int
|
AppURL func(childComplexity int) int
|
||||||
|
ClientID func(childComplexity int) int
|
||||||
|
ClientSecret func(childComplexity int) int
|
||||||
CookieName func(childComplexity int) int
|
CookieName func(childComplexity int) int
|
||||||
CustomAccessTokenScript func(childComplexity int) int
|
CustomAccessTokenScript func(childComplexity int) int
|
||||||
DatabaseName func(childComplexity int) int
|
DatabaseName func(childComplexity int) int
|
||||||
@@ -70,6 +74,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
|
||||||
@@ -92,6 +98,7 @@ type ComplexityRoot struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Meta struct {
|
Meta struct {
|
||||||
|
ClientID func(childComplexity int) int
|
||||||
IsBasicAuthenticationEnabled func(childComplexity int) int
|
IsBasicAuthenticationEnabled func(childComplexity int) int
|
||||||
IsEmailVerificationEnabled func(childComplexity int) int
|
IsEmailVerificationEnabled func(childComplexity int) int
|
||||||
IsFacebookLoginEnabled func(childComplexity int) int
|
IsFacebookLoginEnabled func(childComplexity int) int
|
||||||
@@ -129,7 +136,6 @@ type ComplexityRoot struct {
|
|||||||
Query struct {
|
Query struct {
|
||||||
AdminSession func(childComplexity int) int
|
AdminSession func(childComplexity int) int
|
||||||
Env func(childComplexity int) int
|
Env func(childComplexity int) int
|
||||||
IsValidJwt func(childComplexity int, params *model.IsValidJWTQueryInput) int
|
|
||||||
Meta func(childComplexity int) int
|
Meta func(childComplexity int) int
|
||||||
Profile func(childComplexity int) int
|
Profile func(childComplexity int) int
|
||||||
Session func(childComplexity int, params *model.SessionQueryInput) int
|
Session func(childComplexity int, params *model.SessionQueryInput) int
|
||||||
@@ -166,11 +172,6 @@ type ComplexityRoot struct {
|
|||||||
Users func(childComplexity int) int
|
Users func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
ValidJWTResponse struct {
|
|
||||||
Message func(childComplexity int) int
|
|
||||||
Valid func(childComplexity int) int
|
|
||||||
}
|
|
||||||
|
|
||||||
VerificationRequest struct {
|
VerificationRequest struct {
|
||||||
CreatedAt func(childComplexity int) int
|
CreatedAt func(childComplexity int) int
|
||||||
Email func(childComplexity int) int
|
Email func(childComplexity int) int
|
||||||
@@ -207,7 +208,6 @@ type MutationResolver interface {
|
|||||||
type QueryResolver interface {
|
type QueryResolver interface {
|
||||||
Meta(ctx context.Context) (*model.Meta, error)
|
Meta(ctx context.Context) (*model.Meta, error)
|
||||||
Session(ctx context.Context, params *model.SessionQueryInput) (*model.AuthResponse, error)
|
Session(ctx context.Context, params *model.SessionQueryInput) (*model.AuthResponse, error)
|
||||||
IsValidJwt(ctx context.Context, params *model.IsValidJWTQueryInput) (*model.ValidJWTResponse, error)
|
|
||||||
Profile(ctx context.Context) (*model.User, error)
|
Profile(ctx context.Context) (*model.User, error)
|
||||||
Users(ctx context.Context, params *model.PaginatedInput) (*model.Users, error)
|
Users(ctx context.Context, params *model.PaginatedInput) (*model.Users, error)
|
||||||
VerificationRequests(ctx context.Context, params *model.PaginatedInput) (*model.VerificationRequests, error)
|
VerificationRequests(ctx context.Context, params *model.PaginatedInput) (*model.VerificationRequests, error)
|
||||||
@@ -237,12 +237,19 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.AuthResponse.AccessToken(childComplexity), true
|
return e.complexity.AuthResponse.AccessToken(childComplexity), true
|
||||||
|
|
||||||
case "AuthResponse.expires_at":
|
case "AuthResponse.expires_in":
|
||||||
if e.complexity.AuthResponse.ExpiresAt == nil {
|
if e.complexity.AuthResponse.ExpiresIn == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.complexity.AuthResponse.ExpiresAt(childComplexity), true
|
return e.complexity.AuthResponse.ExpiresIn(childComplexity), true
|
||||||
|
|
||||||
|
case "AuthResponse.id_token":
|
||||||
|
if e.complexity.AuthResponse.IDToken == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.AuthResponse.IDToken(childComplexity), true
|
||||||
|
|
||||||
case "AuthResponse.message":
|
case "AuthResponse.message":
|
||||||
if e.complexity.AuthResponse.Message == nil {
|
if e.complexity.AuthResponse.Message == nil {
|
||||||
@@ -251,6 +258,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.AuthResponse.Message(childComplexity), true
|
return e.complexity.AuthResponse.Message(childComplexity), true
|
||||||
|
|
||||||
|
case "AuthResponse.refresh_token":
|
||||||
|
if e.complexity.AuthResponse.RefreshToken == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.AuthResponse.RefreshToken(childComplexity), true
|
||||||
|
|
||||||
case "AuthResponse.user":
|
case "AuthResponse.user":
|
||||||
if e.complexity.AuthResponse.User == nil {
|
if e.complexity.AuthResponse.User == nil {
|
||||||
break
|
break
|
||||||
@@ -279,6 +293,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Env.AppURL(childComplexity), true
|
return e.complexity.Env.AppURL(childComplexity), true
|
||||||
|
|
||||||
|
case "Env.CLIENT_ID":
|
||||||
|
if e.complexity.Env.ClientID == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Env.ClientID(childComplexity), true
|
||||||
|
|
||||||
|
case "Env.CLIENT_SECRET":
|
||||||
|
if e.complexity.Env.ClientSecret == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Env.ClientSecret(childComplexity), true
|
||||||
|
|
||||||
case "Env.COOKIE_NAME":
|
case "Env.COOKIE_NAME":
|
||||||
if e.complexity.Env.CookieName == nil {
|
if e.complexity.Env.CookieName == nil {
|
||||||
break
|
break
|
||||||
@@ -391,6 +419,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
|
||||||
@@ -503,6 +545,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Error.Reason(childComplexity), true
|
return e.complexity.Error.Reason(childComplexity), true
|
||||||
|
|
||||||
|
case "Meta.client_id":
|
||||||
|
if e.complexity.Meta.ClientID == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Meta.ClientID(childComplexity), true
|
||||||
|
|
||||||
case "Meta.is_basic_authentication_enabled":
|
case "Meta.is_basic_authentication_enabled":
|
||||||
if e.complexity.Meta.IsBasicAuthenticationEnabled == nil {
|
if e.complexity.Meta.IsBasicAuthenticationEnabled == nil {
|
||||||
break
|
break
|
||||||
@@ -764,18 +813,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Query.Env(childComplexity), true
|
return e.complexity.Query.Env(childComplexity), true
|
||||||
|
|
||||||
case "Query.is_valid_jwt":
|
|
||||||
if e.complexity.Query.IsValidJwt == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
args, err := ec.field_Query_is_valid_jwt_args(context.TODO(), rawArgs)
|
|
||||||
if err != nil {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.complexity.Query.IsValidJwt(childComplexity, args["params"].(*model.IsValidJWTQueryInput)), true
|
|
||||||
|
|
||||||
case "Query.meta":
|
case "Query.meta":
|
||||||
if e.complexity.Query.Meta == nil {
|
if e.complexity.Query.Meta == nil {
|
||||||
break
|
break
|
||||||
@@ -966,20 +1003,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Users.Users(childComplexity), true
|
return e.complexity.Users.Users(childComplexity), true
|
||||||
|
|
||||||
case "ValidJWTResponse.message":
|
|
||||||
if e.complexity.ValidJWTResponse.Message == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.complexity.ValidJWTResponse.Message(childComplexity), true
|
|
||||||
|
|
||||||
case "ValidJWTResponse.valid":
|
|
||||||
if e.complexity.ValidJWTResponse.Valid == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.complexity.ValidJWTResponse.Valid(childComplexity), true
|
|
||||||
|
|
||||||
case "VerificationRequest.created_at":
|
case "VerificationRequest.created_at":
|
||||||
if e.complexity.VerificationRequest.CreatedAt == nil {
|
if e.complexity.VerificationRequest.CreatedAt == nil {
|
||||||
break
|
break
|
||||||
@@ -1123,6 +1146,7 @@ type Pagination {
|
|||||||
|
|
||||||
type Meta {
|
type Meta {
|
||||||
version: String!
|
version: String!
|
||||||
|
client_id: String!
|
||||||
is_google_login_enabled: Boolean!
|
is_google_login_enabled: Boolean!
|
||||||
is_facebook_login_enabled: Boolean!
|
is_facebook_login_enabled: Boolean!
|
||||||
is_github_login_enabled: Boolean!
|
is_github_login_enabled: Boolean!
|
||||||
@@ -1180,7 +1204,9 @@ type Error {
|
|||||||
type AuthResponse {
|
type AuthResponse {
|
||||||
message: String!
|
message: String!
|
||||||
access_token: String
|
access_token: String
|
||||||
expires_at: Int64
|
id_token: String
|
||||||
|
refresh_token: String
|
||||||
|
expires_in: Int64
|
||||||
user: User
|
user: User
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1188,16 +1214,13 @@ type Response {
|
|||||||
message: String!
|
message: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
type ValidJWTResponse {
|
|
||||||
valid: Boolean!
|
|
||||||
message: String!
|
|
||||||
}
|
|
||||||
|
|
||||||
type Env {
|
type Env {
|
||||||
ADMIN_SECRET: String
|
ADMIN_SECRET: String
|
||||||
DATABASE_NAME: String
|
DATABASE_NAME: String!
|
||||||
DATABASE_URL: String
|
DATABASE_URL: String!
|
||||||
DATABASE_TYPE: String
|
DATABASE_TYPE: String!
|
||||||
|
CLIENT_ID: String!
|
||||||
|
CLIENT_SECRET: String!
|
||||||
CUSTOM_ACCESS_TOKEN_SCRIPT: String
|
CUSTOM_ACCESS_TOKEN_SCRIPT: String
|
||||||
SMTP_HOST: String
|
SMTP_HOST: String
|
||||||
SMTP_PORT: String
|
SMTP_PORT: String
|
||||||
@@ -1206,6 +1229,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 +1265,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
|
||||||
@@ -1290,6 +1317,7 @@ input LoginInput {
|
|||||||
email: String!
|
email: String!
|
||||||
password: String!
|
password: String!
|
||||||
roles: [String!]
|
roles: [String!]
|
||||||
|
scope: [String!]
|
||||||
}
|
}
|
||||||
|
|
||||||
input VerifyEmailInput {
|
input VerifyEmailInput {
|
||||||
@@ -1348,15 +1376,12 @@ input DeleteUserInput {
|
|||||||
input MagicLinkLoginInput {
|
input MagicLinkLoginInput {
|
||||||
email: String!
|
email: String!
|
||||||
roles: [String!]
|
roles: [String!]
|
||||||
|
scope: [String!]
|
||||||
}
|
}
|
||||||
|
|
||||||
input SessionQueryInput {
|
input SessionQueryInput {
|
||||||
roles: [String!]
|
roles: [String!]
|
||||||
}
|
scope: [String!]
|
||||||
|
|
||||||
input IsValidJWTQueryInput {
|
|
||||||
jwt: String
|
|
||||||
roles: [String!]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input PaginationInput {
|
input PaginationInput {
|
||||||
@@ -1390,7 +1415,6 @@ type Mutation {
|
|||||||
type Query {
|
type Query {
|
||||||
meta: Meta!
|
meta: Meta!
|
||||||
session(params: SessionQueryInput): AuthResponse!
|
session(params: SessionQueryInput): AuthResponse!
|
||||||
is_valid_jwt(params: IsValidJWTQueryInput): ValidJWTResponse!
|
|
||||||
profile: User!
|
profile: User!
|
||||||
# admin only apis
|
# admin only apis
|
||||||
_users(params: PaginatedInput): Users!
|
_users(params: PaginatedInput): Users!
|
||||||
@@ -1646,21 +1670,6 @@ func (ec *executionContext) field_Query__verification_requests_args(ctx context.
|
|||||||
return args, nil
|
return args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) field_Query_is_valid_jwt_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
|
||||||
var err error
|
|
||||||
args := map[string]interface{}{}
|
|
||||||
var arg0 *model.IsValidJWTQueryInput
|
|
||||||
if tmp, ok := rawArgs["params"]; ok {
|
|
||||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params"))
|
|
||||||
arg0, err = ec.unmarshalOIsValidJWTQueryInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐIsValidJWTQueryInput(ctx, tmp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
args["params"] = arg0
|
|
||||||
return args, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *executionContext) field_Query_session_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
func (ec *executionContext) field_Query_session_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||||
var err error
|
var err error
|
||||||
args := map[string]interface{}{}
|
args := map[string]interface{}{}
|
||||||
@@ -1781,7 +1790,7 @@ func (ec *executionContext) _AuthResponse_access_token(ctx context.Context, fiel
|
|||||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _AuthResponse_expires_at(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) {
|
func (ec *executionContext) _AuthResponse_id_token(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
@@ -1799,7 +1808,71 @@ func (ec *executionContext) _AuthResponse_expires_at(ctx context.Context, field
|
|||||||
ctx = graphql.WithFieldContext(ctx, fc)
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
ctx = rctx // use context from middleware stack in children
|
ctx = rctx // use context from middleware stack in children
|
||||||
return obj.ExpiresAt, nil
|
return obj.IDToken, 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) _AuthResponse_refresh_token(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fc := &graphql.FieldContext{
|
||||||
|
Object: "AuthResponse",
|
||||||
|
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.RefreshToken, 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) _AuthResponse_expires_in(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fc := &graphql.FieldContext{
|
||||||
|
Object: "AuthResponse",
|
||||||
|
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.ExpiresIn, nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ec.Error(ctx, err)
|
ec.Error(ctx, err)
|
||||||
@@ -1902,11 +1975,14 @@ func (ec *executionContext) _Env_DATABASE_NAME(ctx context.Context, field graphq
|
|||||||
return graphql.Null
|
return graphql.Null
|
||||||
}
|
}
|
||||||
if resTmp == nil {
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
return graphql.Null
|
return graphql.Null
|
||||||
}
|
}
|
||||||
res := resTmp.(*string)
|
res := resTmp.(string)
|
||||||
fc.Result = res
|
fc.Result = res
|
||||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Env_DATABASE_URL(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Env_DATABASE_URL(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||||
@@ -1934,11 +2010,14 @@ func (ec *executionContext) _Env_DATABASE_URL(ctx context.Context, field graphql
|
|||||||
return graphql.Null
|
return graphql.Null
|
||||||
}
|
}
|
||||||
if resTmp == nil {
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
return graphql.Null
|
return graphql.Null
|
||||||
}
|
}
|
||||||
res := resTmp.(*string)
|
res := resTmp.(string)
|
||||||
fc.Result = res
|
fc.Result = res
|
||||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Env_DATABASE_TYPE(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Env_DATABASE_TYPE(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||||
@@ -1966,11 +2045,84 @@ func (ec *executionContext) _Env_DATABASE_TYPE(ctx context.Context, field graphq
|
|||||||
return graphql.Null
|
return graphql.Null
|
||||||
}
|
}
|
||||||
if resTmp == nil {
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
return graphql.Null
|
return graphql.Null
|
||||||
}
|
}
|
||||||
res := resTmp.(*string)
|
res := resTmp.(string)
|
||||||
fc.Result = res
|
fc.Result = res
|
||||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Env_CLIENT_ID(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.ClientID, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(string)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Env_CLIENT_SECRET(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.ClientSecret, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(string)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Env_CUSTOM_ACCESS_TOKEN_SCRIPT(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Env_CUSTOM_ACCESS_TOKEN_SCRIPT(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||||
@@ -2229,6 +2381,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 {
|
||||||
@@ -3006,6 +3222,41 @@ func (ec *executionContext) _Meta_version(ctx context.Context, field graphql.Col
|
|||||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Meta_client_id(ctx context.Context, field graphql.CollectedField, obj *model.Meta) (ret graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fc := &graphql.FieldContext{
|
||||||
|
Object: "Meta",
|
||||||
|
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.ClientID, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(string)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Meta_is_google_login_enabled(ctx context.Context, field graphql.CollectedField, obj *model.Meta) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Meta_is_google_login_enabled(ctx context.Context, field graphql.CollectedField, obj *model.Meta) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@@ -4049,48 +4300,6 @@ func (ec *executionContext) _Query_session(ctx context.Context, field graphql.Co
|
|||||||
return ec.marshalNAuthResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐAuthResponse(ctx, field.Selections, res)
|
return ec.marshalNAuthResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐAuthResponse(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Query_is_valid_jwt(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
|
||||||
ret = graphql.Null
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
fc := &graphql.FieldContext{
|
|
||||||
Object: "Query",
|
|
||||||
Field: field,
|
|
||||||
Args: nil,
|
|
||||||
IsMethod: true,
|
|
||||||
IsResolver: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = graphql.WithFieldContext(ctx, fc)
|
|
||||||
rawArgs := field.ArgumentMap(ec.Variables)
|
|
||||||
args, err := ec.field_Query_is_valid_jwt_args(ctx, rawArgs)
|
|
||||||
if err != nil {
|
|
||||||
ec.Error(ctx, err)
|
|
||||||
return graphql.Null
|
|
||||||
}
|
|
||||||
fc.Args = args
|
|
||||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
|
||||||
ctx = rctx // use context from middleware stack in children
|
|
||||||
return ec.resolvers.Query().IsValidJwt(rctx, args["params"].(*model.IsValidJWTQueryInput))
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
ec.Error(ctx, err)
|
|
||||||
return graphql.Null
|
|
||||||
}
|
|
||||||
if resTmp == nil {
|
|
||||||
if !graphql.HasFieldError(ctx, fc) {
|
|
||||||
ec.Errorf(ctx, "must not be null")
|
|
||||||
}
|
|
||||||
return graphql.Null
|
|
||||||
}
|
|
||||||
res := resTmp.(*model.ValidJWTResponse)
|
|
||||||
fc.Result = res
|
|
||||||
return ec.marshalNValidJWTResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐValidJWTResponse(ctx, field.Selections, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *executionContext) _Query_profile(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Query_profile(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@@ -5015,76 +5224,6 @@ func (ec *executionContext) _Users_users(ctx context.Context, field graphql.Coll
|
|||||||
return ec.marshalNUser2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐUserᚄ(ctx, field.Selections, res)
|
return ec.marshalNUser2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐUserᚄ(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _ValidJWTResponse_valid(ctx context.Context, field graphql.CollectedField, obj *model.ValidJWTResponse) (ret graphql.Marshaler) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
|
||||||
ret = graphql.Null
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
fc := &graphql.FieldContext{
|
|
||||||
Object: "ValidJWTResponse",
|
|
||||||
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.Valid, nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
ec.Error(ctx, err)
|
|
||||||
return graphql.Null
|
|
||||||
}
|
|
||||||
if resTmp == nil {
|
|
||||||
if !graphql.HasFieldError(ctx, fc) {
|
|
||||||
ec.Errorf(ctx, "must not be null")
|
|
||||||
}
|
|
||||||
return graphql.Null
|
|
||||||
}
|
|
||||||
res := resTmp.(bool)
|
|
||||||
fc.Result = res
|
|
||||||
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *executionContext) _ValidJWTResponse_message(ctx context.Context, field graphql.CollectedField, obj *model.ValidJWTResponse) (ret graphql.Marshaler) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
|
||||||
ret = graphql.Null
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
fc := &graphql.FieldContext{
|
|
||||||
Object: "ValidJWTResponse",
|
|
||||||
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.Message, nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
ec.Error(ctx, err)
|
|
||||||
return graphql.Null
|
|
||||||
}
|
|
||||||
if resTmp == nil {
|
|
||||||
if !graphql.HasFieldError(ctx, fc) {
|
|
||||||
ec.Errorf(ctx, "must not be null")
|
|
||||||
}
|
|
||||||
return graphql.Null
|
|
||||||
}
|
|
||||||
res := resTmp.(string)
|
|
||||||
fc.Result = res
|
|
||||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *executionContext) _VerificationRequest_id(ctx context.Context, field graphql.CollectedField, obj *model.VerificationRequest) (ret graphql.Marshaler) {
|
func (ec *executionContext) _VerificationRequest_id(ctx context.Context, field graphql.CollectedField, obj *model.VerificationRequest) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@@ -6596,37 +6735,6 @@ func (ec *executionContext) unmarshalInputForgotPasswordInput(ctx context.Contex
|
|||||||
return it, nil
|
return it, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) unmarshalInputIsValidJWTQueryInput(ctx context.Context, obj interface{}) (model.IsValidJWTQueryInput, error) {
|
|
||||||
var it model.IsValidJWTQueryInput
|
|
||||||
asMap := map[string]interface{}{}
|
|
||||||
for k, v := range obj.(map[string]interface{}) {
|
|
||||||
asMap[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range asMap {
|
|
||||||
switch k {
|
|
||||||
case "jwt":
|
|
||||||
var err error
|
|
||||||
|
|
||||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("jwt"))
|
|
||||||
it.Jwt, err = ec.unmarshalOString2ᚖstring(ctx, v)
|
|
||||||
if err != nil {
|
|
||||||
return it, err
|
|
||||||
}
|
|
||||||
case "roles":
|
|
||||||
var err error
|
|
||||||
|
|
||||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("roles"))
|
|
||||||
it.Roles, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v)
|
|
||||||
if err != nil {
|
|
||||||
return it, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return it, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *executionContext) unmarshalInputLoginInput(ctx context.Context, obj interface{}) (model.LoginInput, error) {
|
func (ec *executionContext) unmarshalInputLoginInput(ctx context.Context, obj interface{}) (model.LoginInput, error) {
|
||||||
var it model.LoginInput
|
var it model.LoginInput
|
||||||
asMap := map[string]interface{}{}
|
asMap := map[string]interface{}{}
|
||||||
@@ -6660,6 +6768,14 @@ func (ec *executionContext) unmarshalInputLoginInput(ctx context.Context, obj in
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return it, err
|
return it, err
|
||||||
}
|
}
|
||||||
|
case "scope":
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("scope"))
|
||||||
|
it.Scope, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6691,6 +6807,14 @@ func (ec *executionContext) unmarshalInputMagicLinkLoginInput(ctx context.Contex
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return it, err
|
return it, err
|
||||||
}
|
}
|
||||||
|
case "scope":
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("scope"))
|
||||||
|
it.Scope, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6838,6 +6962,14 @@ func (ec *executionContext) unmarshalInputSessionQueryInput(ctx context.Context,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return it, err
|
return it, err
|
||||||
}
|
}
|
||||||
|
case "scope":
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("scope"))
|
||||||
|
it.Scope, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7044,6 +7176,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
|
||||||
|
|
||||||
@@ -7489,8 +7637,12 @@ func (ec *executionContext) _AuthResponse(ctx context.Context, sel ast.Selection
|
|||||||
}
|
}
|
||||||
case "access_token":
|
case "access_token":
|
||||||
out.Values[i] = ec._AuthResponse_access_token(ctx, field, obj)
|
out.Values[i] = ec._AuthResponse_access_token(ctx, field, obj)
|
||||||
case "expires_at":
|
case "id_token":
|
||||||
out.Values[i] = ec._AuthResponse_expires_at(ctx, field, obj)
|
out.Values[i] = ec._AuthResponse_id_token(ctx, field, obj)
|
||||||
|
case "refresh_token":
|
||||||
|
out.Values[i] = ec._AuthResponse_refresh_token(ctx, field, obj)
|
||||||
|
case "expires_in":
|
||||||
|
out.Values[i] = ec._AuthResponse_expires_in(ctx, field, obj)
|
||||||
case "user":
|
case "user":
|
||||||
out.Values[i] = ec._AuthResponse_user(ctx, field, obj)
|
out.Values[i] = ec._AuthResponse_user(ctx, field, obj)
|
||||||
default:
|
default:
|
||||||
@@ -7519,10 +7671,29 @@ func (ec *executionContext) _Env(ctx context.Context, sel ast.SelectionSet, obj
|
|||||||
out.Values[i] = ec._Env_ADMIN_SECRET(ctx, field, obj)
|
out.Values[i] = ec._Env_ADMIN_SECRET(ctx, field, obj)
|
||||||
case "DATABASE_NAME":
|
case "DATABASE_NAME":
|
||||||
out.Values[i] = ec._Env_DATABASE_NAME(ctx, field, obj)
|
out.Values[i] = ec._Env_DATABASE_NAME(ctx, field, obj)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
case "DATABASE_URL":
|
case "DATABASE_URL":
|
||||||
out.Values[i] = ec._Env_DATABASE_URL(ctx, field, obj)
|
out.Values[i] = ec._Env_DATABASE_URL(ctx, field, obj)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
case "DATABASE_TYPE":
|
case "DATABASE_TYPE":
|
||||||
out.Values[i] = ec._Env_DATABASE_TYPE(ctx, field, obj)
|
out.Values[i] = ec._Env_DATABASE_TYPE(ctx, field, obj)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
|
case "CLIENT_ID":
|
||||||
|
out.Values[i] = ec._Env_CLIENT_ID(ctx, field, obj)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
|
case "CLIENT_SECRET":
|
||||||
|
out.Values[i] = ec._Env_CLIENT_SECRET(ctx, field, obj)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
case "CUSTOM_ACCESS_TOKEN_SCRIPT":
|
case "CUSTOM_ACCESS_TOKEN_SCRIPT":
|
||||||
out.Values[i] = ec._Env_CUSTOM_ACCESS_TOKEN_SCRIPT(ctx, field, obj)
|
out.Values[i] = ec._Env_CUSTOM_ACCESS_TOKEN_SCRIPT(ctx, field, obj)
|
||||||
case "SMTP_HOST":
|
case "SMTP_HOST":
|
||||||
@@ -7539,6 +7710,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":
|
||||||
@@ -7640,6 +7815,11 @@ func (ec *executionContext) _Meta(ctx context.Context, sel ast.SelectionSet, obj
|
|||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
invalids++
|
invalids++
|
||||||
}
|
}
|
||||||
|
case "client_id":
|
||||||
|
out.Values[i] = ec._Meta_client_id(ctx, field, obj)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
case "is_google_login_enabled":
|
case "is_google_login_enabled":
|
||||||
out.Values[i] = ec._Meta_is_google_login_enabled(ctx, field, obj)
|
out.Values[i] = ec._Meta_is_google_login_enabled(ctx, field, obj)
|
||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
@@ -7867,20 +8047,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
|||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
case "is_valid_jwt":
|
|
||||||
field := field
|
|
||||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
ec.Error(ctx, ec.Recover(ctx, r))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
res = ec._Query_is_valid_jwt(ctx, field)
|
|
||||||
if res == graphql.Null {
|
|
||||||
atomic.AddUint32(&invalids, 1)
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
})
|
|
||||||
case "profile":
|
case "profile":
|
||||||
field := field
|
field := field
|
||||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||||
@@ -8096,38 +8262,6 @@ func (ec *executionContext) _Users(ctx context.Context, sel ast.SelectionSet, ob
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
var validJWTResponseImplementors = []string{"ValidJWTResponse"}
|
|
||||||
|
|
||||||
func (ec *executionContext) _ValidJWTResponse(ctx context.Context, sel ast.SelectionSet, obj *model.ValidJWTResponse) graphql.Marshaler {
|
|
||||||
fields := graphql.CollectFields(ec.OperationContext, sel, validJWTResponseImplementors)
|
|
||||||
|
|
||||||
out := graphql.NewFieldSet(fields)
|
|
||||||
var invalids uint32
|
|
||||||
for i, field := range fields {
|
|
||||||
switch field.Name {
|
|
||||||
case "__typename":
|
|
||||||
out.Values[i] = graphql.MarshalString("ValidJWTResponse")
|
|
||||||
case "valid":
|
|
||||||
out.Values[i] = ec._ValidJWTResponse_valid(ctx, field, obj)
|
|
||||||
if out.Values[i] == graphql.Null {
|
|
||||||
invalids++
|
|
||||||
}
|
|
||||||
case "message":
|
|
||||||
out.Values[i] = ec._ValidJWTResponse_message(ctx, field, obj)
|
|
||||||
if out.Values[i] == graphql.Null {
|
|
||||||
invalids++
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic("unknown field " + strconv.Quote(field.Name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out.Dispatch()
|
|
||||||
if invalids > 0 {
|
|
||||||
return graphql.Null
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
var verificationRequestImplementors = []string{"VerificationRequest"}
|
var verificationRequestImplementors = []string{"VerificationRequest"}
|
||||||
|
|
||||||
func (ec *executionContext) _VerificationRequest(ctx context.Context, sel ast.SelectionSet, obj *model.VerificationRequest) graphql.Marshaler {
|
func (ec *executionContext) _VerificationRequest(ctx context.Context, sel ast.SelectionSet, obj *model.VerificationRequest) graphql.Marshaler {
|
||||||
@@ -8743,20 +8877,6 @@ func (ec *executionContext) marshalNUsers2ᚖgithubᚗcomᚋauthorizerdevᚋauth
|
|||||||
return ec._Users(ctx, sel, v)
|
return ec._Users(ctx, sel, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) marshalNValidJWTResponse2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐValidJWTResponse(ctx context.Context, sel ast.SelectionSet, v model.ValidJWTResponse) graphql.Marshaler {
|
|
||||||
return ec._ValidJWTResponse(ctx, sel, &v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *executionContext) marshalNValidJWTResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐValidJWTResponse(ctx context.Context, sel ast.SelectionSet, v *model.ValidJWTResponse) graphql.Marshaler {
|
|
||||||
if v == nil {
|
|
||||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
|
||||||
ec.Errorf(ctx, "must not be null")
|
|
||||||
}
|
|
||||||
return graphql.Null
|
|
||||||
}
|
|
||||||
return ec._ValidJWTResponse(ctx, sel, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *executionContext) marshalNVerificationRequest2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐVerificationRequestᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.VerificationRequest) graphql.Marshaler {
|
func (ec *executionContext) marshalNVerificationRequest2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐVerificationRequestᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.VerificationRequest) graphql.Marshaler {
|
||||||
ret := make(graphql.Array, len(v))
|
ret := make(graphql.Array, len(v))
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
@@ -9126,14 +9246,6 @@ func (ec *executionContext) marshalOInt642ᚖint64(ctx context.Context, sel ast.
|
|||||||
return graphql.MarshalInt64(*v)
|
return graphql.MarshalInt64(*v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *executionContext) unmarshalOIsValidJWTQueryInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐIsValidJWTQueryInput(ctx context.Context, v interface{}) (*model.IsValidJWTQueryInput, error) {
|
|
||||||
if v == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
res, err := ec.unmarshalInputIsValidJWTQueryInput(ctx, v)
|
|
||||||
return &res, graphql.ErrorOnPath(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ec *executionContext) unmarshalOPaginatedInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginatedInput(ctx context.Context, v interface{}) (*model.PaginatedInput, error) {
|
func (ec *executionContext) unmarshalOPaginatedInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginatedInput(ctx context.Context, v interface{}) (*model.PaginatedInput, error) {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@@ -11,10 +11,12 @@ type AdminSignupInput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AuthResponse struct {
|
type AuthResponse struct {
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
AccessToken *string `json:"access_token"`
|
AccessToken *string `json:"access_token"`
|
||||||
ExpiresAt *int64 `json:"expires_at"`
|
IDToken *string `json:"id_token"`
|
||||||
User *User `json:"user"`
|
RefreshToken *string `json:"refresh_token"`
|
||||||
|
ExpiresIn *int64 `json:"expires_in"`
|
||||||
|
User *User `json:"user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeleteUserInput struct {
|
type DeleteUserInput struct {
|
||||||
@@ -23,9 +25,11 @@ type DeleteUserInput struct {
|
|||||||
|
|
||||||
type Env struct {
|
type Env struct {
|
||||||
AdminSecret *string `json:"ADMIN_SECRET"`
|
AdminSecret *string `json:"ADMIN_SECRET"`
|
||||||
DatabaseName *string `json:"DATABASE_NAME"`
|
DatabaseName string `json:"DATABASE_NAME"`
|
||||||
DatabaseURL *string `json:"DATABASE_URL"`
|
DatabaseURL string `json:"DATABASE_URL"`
|
||||||
DatabaseType *string `json:"DATABASE_TYPE"`
|
DatabaseType string `json:"DATABASE_TYPE"`
|
||||||
|
ClientID string `json:"CLIENT_ID"`
|
||||||
|
ClientSecret string `json:"CLIENT_SECRET"`
|
||||||
CustomAccessTokenScript *string `json:"CUSTOM_ACCESS_TOKEN_SCRIPT"`
|
CustomAccessTokenScript *string `json:"CUSTOM_ACCESS_TOKEN_SCRIPT"`
|
||||||
SMTPHost *string `json:"SMTP_HOST"`
|
SMTPHost *string `json:"SMTP_HOST"`
|
||||||
SMTPPort *string `json:"SMTP_PORT"`
|
SMTPPort *string `json:"SMTP_PORT"`
|
||||||
@@ -34,6 +38,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"`
|
||||||
@@ -66,24 +72,22 @@ type ForgotPasswordInput struct {
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type IsValidJWTQueryInput struct {
|
|
||||||
Jwt *string `json:"jwt"`
|
|
||||||
Roles []string `json:"roles"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type LoginInput struct {
|
type LoginInput struct {
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Roles []string `json:"roles"`
|
Roles []string `json:"roles"`
|
||||||
|
Scope []string `json:"scope"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MagicLinkLoginInput struct {
|
type MagicLinkLoginInput struct {
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Roles []string `json:"roles"`
|
Roles []string `json:"roles"`
|
||||||
|
Scope []string `json:"scope"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Meta struct {
|
type Meta struct {
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
|
ClientID string `json:"client_id"`
|
||||||
IsGoogleLoginEnabled bool `json:"is_google_login_enabled"`
|
IsGoogleLoginEnabled bool `json:"is_google_login_enabled"`
|
||||||
IsFacebookLoginEnabled bool `json:"is_facebook_login_enabled"`
|
IsFacebookLoginEnabled bool `json:"is_facebook_login_enabled"`
|
||||||
IsGithubLoginEnabled bool `json:"is_github_login_enabled"`
|
IsGithubLoginEnabled bool `json:"is_github_login_enabled"`
|
||||||
@@ -125,6 +129,7 @@ type Response struct {
|
|||||||
|
|
||||||
type SessionQueryInput struct {
|
type SessionQueryInput struct {
|
||||||
Roles []string `json:"roles"`
|
Roles []string `json:"roles"`
|
||||||
|
Scope []string `json:"scope"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SignUpInput struct {
|
type SignUpInput struct {
|
||||||
@@ -153,6 +158,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"`
|
||||||
@@ -231,11 +238,6 @@ type Users struct {
|
|||||||
Users []*User `json:"users"`
|
Users []*User `json:"users"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ValidJWTResponse struct {
|
|
||||||
Valid bool `json:"valid"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type VerificationRequest struct {
|
type VerificationRequest struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Identifier *string `json:"identifier"`
|
Identifier *string `json:"identifier"`
|
||||||
|
@@ -14,6 +14,7 @@ type Pagination {
|
|||||||
|
|
||||||
type Meta {
|
type Meta {
|
||||||
version: String!
|
version: String!
|
||||||
|
client_id: String!
|
||||||
is_google_login_enabled: Boolean!
|
is_google_login_enabled: Boolean!
|
||||||
is_facebook_login_enabled: Boolean!
|
is_facebook_login_enabled: Boolean!
|
||||||
is_github_login_enabled: Boolean!
|
is_github_login_enabled: Boolean!
|
||||||
@@ -71,7 +72,9 @@ type Error {
|
|||||||
type AuthResponse {
|
type AuthResponse {
|
||||||
message: String!
|
message: String!
|
||||||
access_token: String
|
access_token: String
|
||||||
expires_at: Int64
|
id_token: String
|
||||||
|
refresh_token: String
|
||||||
|
expires_in: Int64
|
||||||
user: User
|
user: User
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,16 +82,13 @@ type Response {
|
|||||||
message: String!
|
message: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
type ValidJWTResponse {
|
|
||||||
valid: Boolean!
|
|
||||||
message: String!
|
|
||||||
}
|
|
||||||
|
|
||||||
type Env {
|
type Env {
|
||||||
ADMIN_SECRET: String
|
ADMIN_SECRET: String
|
||||||
DATABASE_NAME: String
|
DATABASE_NAME: String!
|
||||||
DATABASE_URL: String
|
DATABASE_URL: String!
|
||||||
DATABASE_TYPE: String
|
DATABASE_TYPE: String!
|
||||||
|
CLIENT_ID: String!
|
||||||
|
CLIENT_SECRET: String!
|
||||||
CUSTOM_ACCESS_TOKEN_SCRIPT: String
|
CUSTOM_ACCESS_TOKEN_SCRIPT: String
|
||||||
SMTP_HOST: String
|
SMTP_HOST: String
|
||||||
SMTP_PORT: String
|
SMTP_PORT: String
|
||||||
@@ -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
|
||||||
@@ -181,6 +185,7 @@ input LoginInput {
|
|||||||
email: String!
|
email: String!
|
||||||
password: String!
|
password: String!
|
||||||
roles: [String!]
|
roles: [String!]
|
||||||
|
scope: [String!]
|
||||||
}
|
}
|
||||||
|
|
||||||
input VerifyEmailInput {
|
input VerifyEmailInput {
|
||||||
@@ -239,15 +244,12 @@ input DeleteUserInput {
|
|||||||
input MagicLinkLoginInput {
|
input MagicLinkLoginInput {
|
||||||
email: String!
|
email: String!
|
||||||
roles: [String!]
|
roles: [String!]
|
||||||
|
scope: [String!]
|
||||||
}
|
}
|
||||||
|
|
||||||
input SessionQueryInput {
|
input SessionQueryInput {
|
||||||
roles: [String!]
|
roles: [String!]
|
||||||
}
|
scope: [String!]
|
||||||
|
|
||||||
input IsValidJWTQueryInput {
|
|
||||||
jwt: String
|
|
||||||
roles: [String!]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input PaginationInput {
|
input PaginationInput {
|
||||||
@@ -281,7 +283,6 @@ type Mutation {
|
|||||||
type Query {
|
type Query {
|
||||||
meta: Meta!
|
meta: Meta!
|
||||||
session(params: SessionQueryInput): AuthResponse!
|
session(params: SessionQueryInput): AuthResponse!
|
||||||
is_valid_jwt(params: IsValidJWTQueryInput): ValidJWTResponse!
|
|
||||||
profile: User!
|
profile: User!
|
||||||
# admin only apis
|
# admin only apis
|
||||||
_users(params: PaginatedInput): Users!
|
_users(params: PaginatedInput): Users!
|
||||||
|
@@ -79,10 +79,6 @@ func (r *queryResolver) Session(ctx context.Context, params *model.SessionQueryI
|
|||||||
return resolvers.SessionResolver(ctx, params)
|
return resolvers.SessionResolver(ctx, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) IsValidJwt(ctx context.Context, params *model.IsValidJWTQueryInput) (*model.ValidJWTResponse, error) {
|
|
||||||
return resolvers.IsValidJwtResolver(ctx, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *queryResolver) Profile(ctx context.Context) (*model.User, error) {
|
func (r *queryResolver) Profile(ctx context.Context) (*model.User, error) {
|
||||||
return resolvers.ProfileResolver(ctx)
|
return resolvers.ProfileResolver(ctx)
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"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/gin-gonic/gin"
|
||||||
@@ -17,13 +18,14 @@ import (
|
|||||||
type State struct {
|
type State struct {
|
||||||
AuthorizerURL string `json:"authorizerURL"`
|
AuthorizerURL string `json:"authorizerURL"`
|
||||||
RedirectURL string `json:"redirectURL"`
|
RedirectURL string `json:"redirectURL"`
|
||||||
|
State string `json:"state"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppHandler is the handler for the /app route
|
// AppHandler is the handler for the /app route
|
||||||
func AppHandler() gin.HandlerFunc {
|
func AppHandler() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
hostname := utils.GetHost(c)
|
hostname := utils.GetHost(c)
|
||||||
if envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableLoginPage) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableLoginPage) {
|
||||||
c.JSON(400, gin.H{"error": "login page is not enabled"})
|
c.JSON(400, gin.H{"error": "login page is not enabled"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -36,7 +38,7 @@ func AppHandler() gin.HandlerFunc {
|
|||||||
stateObj.AuthorizerURL = hostname
|
stateObj.AuthorizerURL = hostname
|
||||||
stateObj.RedirectURL = hostname + "/app"
|
stateObj.RedirectURL = hostname + "/app"
|
||||||
} else {
|
} else {
|
||||||
decodedState, err := utils.DecryptB64(state)
|
decodedState, err := crypto.DecryptB64(state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(400, gin.H{"error": "[unable to decode state] invalid state"})
|
c.JSON(400, gin.H{"error": "[unable to decode state] invalid state"})
|
||||||
return
|
return
|
||||||
@@ -79,8 +81,9 @@ func AppHandler() gin.HandlerFunc {
|
|||||||
"data": map[string]string{
|
"data": map[string]string{
|
||||||
"authorizerURL": stateObj.AuthorizerURL,
|
"authorizerURL": stateObj.AuthorizerURL,
|
||||||
"redirectURL": stateObj.RedirectURL,
|
"redirectURL": stateObj.RedirectURL,
|
||||||
"organizationName": envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName),
|
"state": stateObj.State,
|
||||||
"organizationLogo": envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo),
|
"organizationName": envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName),
|
||||||
|
"organizationLogo": envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
324
server/handlers/authorize.go
Normal file
324
server/handlers/authorize.go
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AuthorizeHandler is the handler for the /authorize route
|
||||||
|
// required params
|
||||||
|
// ?redirect_uri = redirect url
|
||||||
|
// ?response_mode = to decide if result should be html or re-direct
|
||||||
|
// state[recommended] = to prevent CSRF attack (for authorizer its compulsory)
|
||||||
|
// code_challenge = to prevent CSRF attack
|
||||||
|
// code_challenge_method = to prevent CSRF attack [only sh256 is supported]
|
||||||
|
|
||||||
|
// check the flow for generating and verifying codes: https://developer.okta.com/blog/2019/08/22/okta-authjs-pkce#:~:text=PKCE%20works%20by%20having%20the,is%20called%20the%20Code%20Challenge.
|
||||||
|
func AuthorizeHandler() gin.HandlerFunc {
|
||||||
|
return func(gc *gin.Context) {
|
||||||
|
redirectURI := strings.TrimSpace(gc.Query("redirect_uri"))
|
||||||
|
responseType := strings.TrimSpace(gc.Query("response_type"))
|
||||||
|
state := strings.TrimSpace(gc.Query("state"))
|
||||||
|
codeChallenge := strings.TrimSpace(gc.Query("code_challenge"))
|
||||||
|
scopeString := strings.TrimSpace(gc.Query("scope"))
|
||||||
|
clientID := strings.TrimSpace(gc.Query("client_id"))
|
||||||
|
template := "authorize.tmpl"
|
||||||
|
responseMode := strings.TrimSpace(gc.Query("response_mode"))
|
||||||
|
|
||||||
|
if responseMode == "" {
|
||||||
|
responseMode = "query"
|
||||||
|
}
|
||||||
|
|
||||||
|
if responseMode != "query" && responseMode != "web_message" {
|
||||||
|
gc.JSON(400, gin.H{"error": "invalid response mode"})
|
||||||
|
}
|
||||||
|
|
||||||
|
if redirectURI == "" {
|
||||||
|
redirectURI = "/app"
|
||||||
|
}
|
||||||
|
|
||||||
|
isQuery := responseMode == "query"
|
||||||
|
|
||||||
|
hostname := utils.GetHost(gc)
|
||||||
|
loginRedirectState := crypto.EncryptB64(`{"authorizerURL":"` + hostname + `","redirectURL":"` + redirectURI + `", "state":"` + state + `"}`)
|
||||||
|
loginURL := "/app?state=" + loginRedirectState
|
||||||
|
|
||||||
|
if clientID == "" {
|
||||||
|
if isQuery {
|
||||||
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
|
} else {
|
||||||
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
|
"target_origin": redirectURI,
|
||||||
|
"authorization_response": map[string]interface{}{
|
||||||
|
"type": "authorization_response",
|
||||||
|
"response": map[string]string{
|
||||||
|
"error": "client_id is required",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if clientID != envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyClientID) {
|
||||||
|
if isQuery {
|
||||||
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
|
} else {
|
||||||
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
|
"target_origin": redirectURI,
|
||||||
|
"authorization_response": map[string]interface{}{
|
||||||
|
"type": "authorization_response",
|
||||||
|
"response": map[string]string{
|
||||||
|
"error": "invalid_client_id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if state == "" {
|
||||||
|
if isQuery {
|
||||||
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
|
} else {
|
||||||
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
|
"target_origin": redirectURI,
|
||||||
|
"authorization_response": map[string]interface{}{
|
||||||
|
"type": "authorization_response",
|
||||||
|
"response": map[string]string{
|
||||||
|
"error": "state is required",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if responseType == "" {
|
||||||
|
responseType = "token"
|
||||||
|
}
|
||||||
|
|
||||||
|
var scope []string
|
||||||
|
if scopeString == "" {
|
||||||
|
scope = []string{"openid", "profile", "email"}
|
||||||
|
} else {
|
||||||
|
scope = strings.Split(scopeString, " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
isResponseTypeCode := responseType == "code"
|
||||||
|
isResponseTypeToken := responseType == "token"
|
||||||
|
|
||||||
|
if !isResponseTypeCode && !isResponseTypeToken {
|
||||||
|
if isQuery {
|
||||||
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
|
} else {
|
||||||
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
|
"target_origin": redirectURI,
|
||||||
|
"authorization_response": map[string]interface{}{
|
||||||
|
"type": "authorization_response",
|
||||||
|
"response": map[string]string{
|
||||||
|
"error": "response_type is invalid",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if isResponseTypeCode {
|
||||||
|
if codeChallenge == "" {
|
||||||
|
if isQuery {
|
||||||
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
|
} else {
|
||||||
|
gc.HTML(http.StatusBadRequest, template, gin.H{
|
||||||
|
"target_origin": redirectURI,
|
||||||
|
"authorization_response": map[string]interface{}{
|
||||||
|
"type": "authorization_response",
|
||||||
|
"response": map[string]string{
|
||||||
|
"error": "code_challenge is required",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionToken, err := cookie.GetSession(gc)
|
||||||
|
if err != nil {
|
||||||
|
if isQuery {
|
||||||
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
|
} else {
|
||||||
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
|
"target_origin": redirectURI,
|
||||||
|
"authorization_response": map[string]interface{}{
|
||||||
|
"type": "authorization_response",
|
||||||
|
"response": map[string]string{
|
||||||
|
"error": "login_required",
|
||||||
|
"error_description": "Login is required",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// get session from cookie
|
||||||
|
claims, err := token.ValidateBrowserSession(gc, sessionToken)
|
||||||
|
if err != nil {
|
||||||
|
if isQuery {
|
||||||
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
|
} else {
|
||||||
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
|
"target_origin": redirectURI,
|
||||||
|
"authorization_response": map[string]interface{}{
|
||||||
|
"type": "authorization_response",
|
||||||
|
"response": map[string]string{
|
||||||
|
"error": "login_required",
|
||||||
|
"error_description": "Login is required",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userID := claims.Subject
|
||||||
|
user, err := db.Provider.GetUserByID(userID)
|
||||||
|
if err != nil {
|
||||||
|
if isQuery {
|
||||||
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
|
} else {
|
||||||
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
|
"target_origin": redirectURI,
|
||||||
|
"authorization_response": map[string]interface{}{
|
||||||
|
"type": "authorization_response",
|
||||||
|
"response": map[string]string{
|
||||||
|
"error": "signup_required",
|
||||||
|
"error_description": "Sign up required",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// if user is logged in
|
||||||
|
// based on the response type, generate the response
|
||||||
|
if isResponseTypeCode {
|
||||||
|
// rollover the session for security
|
||||||
|
sessionstore.RemoveState(sessionToken)
|
||||||
|
nonce := uuid.New().String()
|
||||||
|
newSessionTokenData, newSessionToken, err := token.CreateSessionToken(user, nonce, claims.Roles, scope)
|
||||||
|
if err != nil {
|
||||||
|
if isQuery {
|
||||||
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
|
} else {
|
||||||
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
|
"target_origin": redirectURI,
|
||||||
|
"authorization_response": map[string]interface{}{
|
||||||
|
"type": "authorization_response",
|
||||||
|
"response": map[string]string{
|
||||||
|
"error": "login_required",
|
||||||
|
"error_description": "Login is required",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionstore.SetState(newSessionToken, newSessionTokenData.Nonce+"@"+user.ID)
|
||||||
|
cookie.SetSession(gc, newSessionToken)
|
||||||
|
code := uuid.New().String()
|
||||||
|
sessionstore.SetState(codeChallenge, code+"@"+newSessionToken)
|
||||||
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
|
"target_origin": redirectURI,
|
||||||
|
"authorization_response": map[string]interface{}{
|
||||||
|
"type": "authorization_response",
|
||||||
|
"response": map[string]string{
|
||||||
|
"code": code,
|
||||||
|
"state": state,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if isResponseTypeToken {
|
||||||
|
// rollover the session for security
|
||||||
|
authToken, err := token.CreateAuthToken(gc, user, claims.Roles, scope)
|
||||||
|
if err != nil {
|
||||||
|
if isQuery {
|
||||||
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
|
} else {
|
||||||
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
|
"target_origin": redirectURI,
|
||||||
|
"authorization_response": map[string]interface{}{
|
||||||
|
"type": "authorization_response",
|
||||||
|
"response": map[string]string{
|
||||||
|
"error": "login_required",
|
||||||
|
"error_description": "Login is required",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sessionstore.RemoveState(sessionToken)
|
||||||
|
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
|
|
||||||
|
expiresIn := int64(1800)
|
||||||
|
res := map[string]interface{}{
|
||||||
|
"access_token": authToken.AccessToken.Token,
|
||||||
|
"id_token": authToken.IDToken.Token,
|
||||||
|
"state": state,
|
||||||
|
"scope": scope,
|
||||||
|
"token_type": "Bearer",
|
||||||
|
"expires_in": expiresIn,
|
||||||
|
}
|
||||||
|
|
||||||
|
if authToken.RefreshToken != nil {
|
||||||
|
res["refresh_token"] = authToken.RefreshToken.Token
|
||||||
|
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
|
"target_origin": redirectURI,
|
||||||
|
"authorization_response": map[string]interface{}{
|
||||||
|
"type": "authorization_response",
|
||||||
|
"response": res,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if isQuery {
|
||||||
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
|
} else {
|
||||||
|
// by default return with error
|
||||||
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
|
"target_origin": redirectURI,
|
||||||
|
"authorization_response": map[string]interface{}{
|
||||||
|
"type": "authorization_response",
|
||||||
|
"response": map[string]string{
|
||||||
|
"error": "login_required",
|
||||||
|
"error_description": "Login is required",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -13,7 +13,7 @@ func DashboardHandler() gin.HandlerFunc {
|
|||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
isOnboardingCompleted := false
|
isOnboardingCompleted := false
|
||||||
|
|
||||||
if envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) != "" {
|
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) != "" {
|
||||||
isOnboardingCompleted = true
|
isOnboardingCompleted = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
server/handlers/jwks.go
Normal file
30
server/handlers/jwks.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func JWKsHandler() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
var data map[string]string
|
||||||
|
jwk := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJWK)
|
||||||
|
err := json.Unmarshal([]byte(jwk), &data)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(500, gin.H{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(200, gin.H{
|
||||||
|
"keys": []map[string]string{
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
40
server/handlers/logout.go
Normal file
40
server/handlers/logout.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LogoutHandler() gin.HandlerFunc {
|
||||||
|
return func(gc *gin.Context) {
|
||||||
|
// get fingerprint hash
|
||||||
|
fingerprintHash, err := cookie.GetSession(gc)
|
||||||
|
if err != nil {
|
||||||
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
decryptedFingerPrint, err := crypto.DecryptAES(fingerprintHash)
|
||||||
|
if err != nil {
|
||||||
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fingerPrint := string(decryptedFingerPrint)
|
||||||
|
|
||||||
|
sessionstore.RemoveState(fingerPrint)
|
||||||
|
cookie.DeleteSession(gc)
|
||||||
|
|
||||||
|
gc.JSON(http.StatusOK, gin.H{
|
||||||
|
"message": "Logged out successfully",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/coreos/go-oidc/v3/oidc"
|
"github.com/coreos/go-oidc/v3/oidc"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/google/uuid"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,11 +31,11 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||||||
provider := c.Param("oauth_provider")
|
provider := c.Param("oauth_provider")
|
||||||
state := c.Request.FormValue("state")
|
state := c.Request.FormValue("state")
|
||||||
|
|
||||||
sessionState := sessionstore.GetSocailLoginState(state)
|
sessionState := sessionstore.GetState(state)
|
||||||
if sessionState == "" {
|
if sessionState == "" {
|
||||||
c.JSON(400, gin.H{"error": "invalid oauth state"})
|
c.JSON(400, gin.H{"error": "invalid oauth state"})
|
||||||
}
|
}
|
||||||
sessionstore.RemoveSocialLoginState(state)
|
sessionstore.GetState(state)
|
||||||
// contains random token, redirect url, role
|
// contains random token, redirect url, role
|
||||||
sessionSplit := strings.Split(state, "___")
|
sessionSplit := strings.Split(state, "___")
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||||||
// make sure inputRoles don't include protected roles
|
// make sure inputRoles don't include protected roles
|
||||||
hasProtectedRole := false
|
hasProtectedRole := false
|
||||||
for _, ir := range inputRoles {
|
for _, ir := range inputRoles {
|
||||||
if utils.StringSliceContains(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles), ir) {
|
if utils.StringSliceContains(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles), ir) {
|
||||||
hasProtectedRole = true
|
hasProtectedRole = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,7 +123,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||||||
// check if it contains protected unassigned role
|
// check if it contains protected unassigned role
|
||||||
hasProtectedRole := false
|
hasProtectedRole := false
|
||||||
for _, ur := range unasignedRoles {
|
for _, ur := range unasignedRoles {
|
||||||
if utils.StringSliceContains(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles), ur) {
|
if utils.StringSliceContains(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles), ur) {
|
||||||
hasProtectedRole = true
|
hasProtectedRole = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,11 +145,17 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
authToken, _ := token.CreateAuthToken(user, inputRoles)
|
// TODO use query param
|
||||||
sessionstore.SetUserSession(user.ID, authToken.FingerPrint, authToken.RefreshToken.Token)
|
scope := []string{"openid", "email", "profile"}
|
||||||
cookie.SetCookie(c, authToken.AccessToken.Token, authToken.RefreshToken.Token, authToken.FingerPrintHash)
|
nonce := uuid.New().String()
|
||||||
utils.SaveSessionInDB(user.ID, c)
|
_, newSessionToken, err := token.CreateSessionToken(user, nonce, inputRoles, scope)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(500, gin.H{"error": err.Error()})
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionstore.SetState(newSessionToken, nonce+"@"+user.ID)
|
||||||
|
cookie.SetSession(c, newSessionToken)
|
||||||
|
go utils.SaveSessionInDB(c, user.ID)
|
||||||
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
|
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,7 +234,7 @@ func processGithubUserInfo(code string) (models.User, error) {
|
|||||||
GivenName: &firstName,
|
GivenName: &firstName,
|
||||||
FamilyName: &lastName,
|
FamilyName: &lastName,
|
||||||
Picture: &picture,
|
Picture: &picture,
|
||||||
Email: userRawData["email"],
|
Email: userRawData["sub"],
|
||||||
}
|
}
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
@@ -260,7 +267,7 @@ func processFacebookUserInfo(code string) (models.User, error) {
|
|||||||
userRawData := make(map[string]interface{})
|
userRawData := make(map[string]interface{})
|
||||||
json.Unmarshal(body, &userRawData)
|
json.Unmarshal(body, &userRawData)
|
||||||
|
|
||||||
email := fmt.Sprintf("%v", userRawData["email"])
|
email := fmt.Sprintf("%v", userRawData["sub"])
|
||||||
|
|
||||||
picObject := userRawData["picture"].(map[string]interface{})["data"]
|
picObject := userRawData["picture"].(map[string]interface{})["data"]
|
||||||
picDataObject := picObject.(map[string]interface{})
|
picDataObject := picObject.(map[string]interface{})
|
||||||
|
@@ -33,14 +33,14 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||||||
|
|
||||||
// use protected roles verification for admin login only.
|
// use protected roles verification for admin login only.
|
||||||
// though if not associated with user, it will be rejected from oauth_callback
|
// though if not associated with user, it will be rejected from oauth_callback
|
||||||
if !utils.IsValidRoles(append([]string{}, append(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles)...)...), rolesSplit) {
|
if !utils.IsValidRoles(append([]string{}, append(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles)...)...), rolesSplit) {
|
||||||
c.JSON(400, gin.H{
|
c.JSON(400, gin.H{
|
||||||
"error": "invalid role",
|
"error": "invalid role",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
roles = strings.Join(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
roles = strings.Join(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
uuid := uuid.New()
|
uuid := uuid.New()
|
||||||
@@ -54,7 +54,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||||||
isProviderConfigured = false
|
isProviderConfigured = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
sessionstore.SetSocailLoginState(oauthStateString, constants.SignupMethodGoogle)
|
sessionstore.SetState(oauthStateString, constants.SignupMethodGoogle)
|
||||||
// during the init of OAuthProvider authorizer url might be empty
|
// during the init of OAuthProvider authorizer url might be empty
|
||||||
oauth.OAuthProviders.GoogleConfig.RedirectURL = hostname + "/oauth_callback/google"
|
oauth.OAuthProviders.GoogleConfig.RedirectURL = hostname + "/oauth_callback/google"
|
||||||
url := oauth.OAuthProviders.GoogleConfig.AuthCodeURL(oauthStateString)
|
url := oauth.OAuthProviders.GoogleConfig.AuthCodeURL(oauthStateString)
|
||||||
@@ -64,7 +64,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||||||
isProviderConfigured = false
|
isProviderConfigured = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
sessionstore.SetSocailLoginState(oauthStateString, constants.SignupMethodGithub)
|
sessionstore.SetState(oauthStateString, constants.SignupMethodGithub)
|
||||||
oauth.OAuthProviders.GithubConfig.RedirectURL = hostname + "/oauth_callback/github"
|
oauth.OAuthProviders.GithubConfig.RedirectURL = hostname + "/oauth_callback/github"
|
||||||
url := oauth.OAuthProviders.GithubConfig.AuthCodeURL(oauthStateString)
|
url := oauth.OAuthProviders.GithubConfig.AuthCodeURL(oauthStateString)
|
||||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||||
@@ -73,7 +73,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||||||
isProviderConfigured = false
|
isProviderConfigured = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
sessionstore.SetSocailLoginState(oauthStateString, constants.SignupMethodFacebook)
|
sessionstore.SetState(oauthStateString, constants.SignupMethodFacebook)
|
||||||
oauth.OAuthProviders.FacebookConfig.RedirectURL = hostname + "/oauth_callback/facebook"
|
oauth.OAuthProviders.FacebookConfig.RedirectURL = hostname + "/oauth_callback/facebook"
|
||||||
url := oauth.OAuthProviders.FacebookConfig.AuthCodeURL(oauthStateString)
|
url := oauth.OAuthProviders.FacebookConfig.AuthCodeURL(oauthStateString)
|
||||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||||
|
30
server/handlers/openid_config.go
Normal file
30
server/handlers/openid_config.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OpenIDConfigurationHandler handler for open-id configurations
|
||||||
|
func OpenIDConfigurationHandler() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
issuer := utils.GetHost(c)
|
||||||
|
jwtType := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
|
||||||
|
|
||||||
|
c.JSON(200, gin.H{
|
||||||
|
"issuer": issuer,
|
||||||
|
"authorization_endpoint": issuer + "/authorize",
|
||||||
|
"token_endpoint": issuer + "/token",
|
||||||
|
"userinfo_endpoint": issuer + "/userinfo",
|
||||||
|
"jwks_uri": issuer + "/.well-known/jwks.json",
|
||||||
|
"response_types_supported": []string{"code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token"},
|
||||||
|
"scopes_supported": []string{"openid", "email", "profile", "email_verified", "given_name", "family_name", "nick_name", "picture"},
|
||||||
|
"response_modes_supported": []string{"query", "fragment", "form_post"},
|
||||||
|
"id_token_signing_alg_values_supported": []string{jwtType},
|
||||||
|
"claims_supported": []string{"aud", "exp", "iss", "iat", "sub", "given_name", "family_name", "middle_name", "nickname", "preferred_username", "picture", "email", "email_verified", "roles", "gender", "birthdate", "phone_number", "phone_number_verified"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
138
server/handlers/token.go
Normal file
138
server/handlers/token.go
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/base64"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TokenHandler() gin.HandlerFunc {
|
||||||
|
return func(gc *gin.Context) {
|
||||||
|
var reqBody map[string]string
|
||||||
|
if err := gc.BindJSON(&reqBody); err != nil {
|
||||||
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": "error_binding_json",
|
||||||
|
"error_description": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
codeVerifier := strings.TrimSpace(reqBody["code_verifier"])
|
||||||
|
code := strings.TrimSpace(reqBody["code"])
|
||||||
|
clientID := strings.TrimSpace(reqBody["client_id"])
|
||||||
|
|
||||||
|
if clientID == "" {
|
||||||
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": "client_id_required",
|
||||||
|
"error_description": "The client id is required",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if clientID != envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyClientID) {
|
||||||
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": "invalid_client_id",
|
||||||
|
"error_description": "The client id is invalid",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if codeVerifier == "" {
|
||||||
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": "invalid_code_verifier",
|
||||||
|
"error_description": "The code verifier is required",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if code == "" {
|
||||||
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": "invalid_code",
|
||||||
|
"error_description": "The code is required",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hash := sha256.New()
|
||||||
|
hash.Write([]byte(codeVerifier))
|
||||||
|
encryptedCode := strings.ReplaceAll(base64.URLEncoding.EncodeToString(hash.Sum(nil)), "+", "-")
|
||||||
|
encryptedCode = strings.ReplaceAll(encryptedCode, "/", "_")
|
||||||
|
encryptedCode = strings.ReplaceAll(encryptedCode, "=", "")
|
||||||
|
sessionData := sessionstore.GetState(encryptedCode)
|
||||||
|
if sessionData == "" {
|
||||||
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": "invalid_code_verifier",
|
||||||
|
"error_description": "The code verifier is invalid",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// split session data
|
||||||
|
// it contains code@sessiontoken
|
||||||
|
sessionDataSplit := strings.Split(sessionData, "@")
|
||||||
|
|
||||||
|
if sessionDataSplit[0] != code {
|
||||||
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"error": "invalid_code_verifier",
|
||||||
|
"error_description": "The code verifier is invalid",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate session
|
||||||
|
claims, err := token.ValidateBrowserSession(gc, sessionDataSplit[1])
|
||||||
|
if err != nil {
|
||||||
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
|
"error": "unauthorized",
|
||||||
|
"error_description": "Invalid session data",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userID := claims.Subject
|
||||||
|
user, err := db.Provider.GetUserByID(userID)
|
||||||
|
if err != nil {
|
||||||
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
|
"error": "unauthorized",
|
||||||
|
"error_description": "User not found",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// rollover the session for security
|
||||||
|
sessionstore.RemoveState(sessionDataSplit[1])
|
||||||
|
authToken, err := token.CreateAuthToken(gc, user, claims.Roles, claims.Scope)
|
||||||
|
if err != nil {
|
||||||
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
|
"error": "unauthorized",
|
||||||
|
"error_description": "User not found",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
|
|
||||||
|
expiresIn := int64(1800)
|
||||||
|
res := map[string]interface{}{
|
||||||
|
"access_token": authToken.AccessToken.Token,
|
||||||
|
"id_token": authToken.IDToken.Token,
|
||||||
|
"scope": claims.Scope,
|
||||||
|
"expires_in": expiresIn,
|
||||||
|
}
|
||||||
|
|
||||||
|
if authToken.RefreshToken != nil {
|
||||||
|
res["refresh_token"] = authToken.RefreshToken.Token
|
||||||
|
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
gc.JSON(http.StatusOK, res)
|
||||||
|
}
|
||||||
|
}
|
40
server/handlers/userinfo.go
Normal file
40
server/handlers/userinfo.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UserInfoHandler() gin.HandlerFunc {
|
||||||
|
return func(gc *gin.Context) {
|
||||||
|
accessToken, err := token.GetAccessToken(gc)
|
||||||
|
if err != nil {
|
||||||
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
claims, err := token.ValidateAccessToken(gc, accessToken)
|
||||||
|
if err != nil {
|
||||||
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
userID := claims["sub"].(string)
|
||||||
|
user, err := db.Provider.GetUserByID(userID)
|
||||||
|
if err != nil {
|
||||||
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
gc.JSON(http.StatusOK, user.AsAPIUser())
|
||||||
|
}
|
||||||
|
}
|
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VerifyEmailHandler handles the verify email route.
|
// VerifyEmailHandler handles the verify email route.
|
||||||
@@ -18,7 +19,7 @@ import (
|
|||||||
func VerifyEmailHandler() gin.HandlerFunc {
|
func VerifyEmailHandler() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
errorRes := gin.H{
|
errorRes := gin.H{
|
||||||
"message": "invalid token",
|
"error": "invalid token",
|
||||||
}
|
}
|
||||||
tokenInQuery := c.Query("token")
|
tokenInQuery := c.Query("token")
|
||||||
if tokenInQuery == "" {
|
if tokenInQuery == "" {
|
||||||
@@ -33,13 +34,21 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// verify if token exists in db
|
// verify if token exists in db
|
||||||
claim, err := token.VerifyVerificationToken(tokenInQuery)
|
hostname := utils.GetHost(c)
|
||||||
|
encryptedNonce, err := utils.EncryptNonce(verificationRequest.Nonce)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(400, gin.H{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
claim, err := token.ParseJWTToken(tokenInQuery, hostname, encryptedNonce, verificationRequest.Email)
|
||||||
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["sub"].(string))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(400, gin.H{
|
c.JSON(400, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
@@ -57,17 +66,20 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||||||
db.Provider.DeleteVerificationRequest(verificationRequest)
|
db.Provider.DeleteVerificationRequest(verificationRequest)
|
||||||
|
|
||||||
roles := strings.Split(user.Roles, ",")
|
roles := strings.Split(user.Roles, ",")
|
||||||
authToken, err := token.CreateAuthToken(user, roles)
|
scope := []string{"openid", "email", "profile"}
|
||||||
|
nonce := uuid.New().String()
|
||||||
|
_, authToken, err := token.CreateSessionToken(user, nonce, roles, scope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(400, gin.H{
|
c.JSON(400, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sessionstore.SetUserSession(user.ID, authToken.FingerPrint, authToken.RefreshToken.Token)
|
sessionstore.SetState(authToken, nonce+"@"+user.ID)
|
||||||
cookie.SetCookie(c, authToken.AccessToken.Token, authToken.RefreshToken.Token, authToken.FingerPrintHash)
|
cookie.SetSession(c, authToken)
|
||||||
utils.SaveSessionInDB(user.ID, c)
|
|
||||||
|
|
||||||
c.Redirect(http.StatusTemporaryRedirect, claim.RedirectURL)
|
go utils.SaveSessionInDB(c, user.ID)
|
||||||
|
|
||||||
|
c.Redirect(http.StatusTemporaryRedirect, claim["redirect_url"].(string))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
@@ -20,16 +21,45 @@ func main() {
|
|||||||
envstore.ARG_ENV_FILE = flag.String("env_file", "", "Env file path")
|
envstore.ARG_ENV_FILE = flag.String("env_file", "", "Env file path")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyVersion, VERSION)
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyVersion, VERSION)
|
||||||
|
|
||||||
env.InitEnv()
|
// initialize required envs (mainly db & env file path)
|
||||||
db.InitDB()
|
err := env.InitRequiredEnv()
|
||||||
env.PersistEnv()
|
if err != nil {
|
||||||
|
log.Fatal("Error while initializing required envs:", err)
|
||||||
|
}
|
||||||
|
|
||||||
sessionstore.InitSession()
|
// initialize db provider
|
||||||
oauth.InitOAuth()
|
err = db.InitDB()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error while initializing db:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize all envs
|
||||||
|
// (get if present from db else construct from os env + defaults)
|
||||||
|
err = env.InitAllEnv()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error while initializing env: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// persist all envs
|
||||||
|
err = env.PersistEnv()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error while persisting env:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize session store (redis or in-memory based on env)
|
||||||
|
err = sessionstore.InitSession()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error while initializing session store:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize oauth providers based on env
|
||||||
|
err = oauth.InitOAuth()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error while initializing oauth:", err)
|
||||||
|
}
|
||||||
|
|
||||||
router := routes.InitRouter()
|
router := routes.InitRouter()
|
||||||
|
router.Run(":" + envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyPort))
|
||||||
router.Run(":" + envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyPort))
|
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,6 @@ package oauth
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
@@ -32,37 +31,39 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// InitOAuth initializes the OAuth providers based on EnvData
|
// InitOAuth initializes the OAuth providers based on EnvData
|
||||||
func InitOAuth() {
|
func InitOAuth() error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
if envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientID) != "" && envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientSecret) != "" {
|
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientID) != "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientSecret) != "" {
|
||||||
p, err := oidc.NewProvider(ctx, "https://accounts.google.com")
|
p, err := oidc.NewProvider(ctx, "https://accounts.google.com")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("error creating oidc provider for google:", err)
|
return err
|
||||||
}
|
}
|
||||||
OIDCProviders.GoogleOIDC = p
|
OIDCProviders.GoogleOIDC = p
|
||||||
OAuthProviders.GoogleConfig = &oauth2.Config{
|
OAuthProviders.GoogleConfig = &oauth2.Config{
|
||||||
ClientID: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientID),
|
ClientID: envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientID),
|
||||||
ClientSecret: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientSecret),
|
ClientSecret: envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientSecret),
|
||||||
RedirectURL: "/oauth_callback/google",
|
RedirectURL: "/oauth_callback/google",
|
||||||
Endpoint: OIDCProviders.GoogleOIDC.Endpoint(),
|
Endpoint: OIDCProviders.GoogleOIDC.Endpoint(),
|
||||||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGithubClientID) != "" && envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGithubClientSecret) != "" {
|
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGithubClientID) != "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGithubClientSecret) != "" {
|
||||||
OAuthProviders.GithubConfig = &oauth2.Config{
|
OAuthProviders.GithubConfig = &oauth2.Config{
|
||||||
ClientID: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGithubClientID),
|
ClientID: envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGithubClientID),
|
||||||
ClientSecret: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGithubClientSecret),
|
ClientSecret: envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGithubClientSecret),
|
||||||
RedirectURL: "/oauth_callback/github",
|
RedirectURL: "/oauth_callback/github",
|
||||||
Endpoint: githubOAuth2.Endpoint,
|
Endpoint: githubOAuth2.Endpoint,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyFacebookClientID) != "" && envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientID) != "" {
|
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyFacebookClientID) != "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyGoogleClientID) != "" {
|
||||||
OAuthProviders.FacebookConfig = &oauth2.Config{
|
OAuthProviders.FacebookConfig = &oauth2.Config{
|
||||||
ClientID: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyFacebookClientID),
|
ClientID: envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyFacebookClientID),
|
||||||
ClientSecret: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyFacebookClientSecret),
|
ClientSecret: envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyFacebookClientSecret),
|
||||||
RedirectURL: "/oauth_callback/facebook",
|
RedirectURL: "/oauth_callback/facebook",
|
||||||
Endpoint: facebookOAuth2.Endpoint,
|
Endpoint: facebookOAuth2.Endpoint,
|
||||||
Scopes: []string{"public_profile", "email"},
|
Scopes: []string{"public_profile", "email"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
@@ -20,12 +21,12 @@ func AdminLoginResolver(ctx context.Context, params model.AdminLoginInput) (*mod
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
adminSecret := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
adminSecret := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
||||||
if params.AdminSecret != adminSecret {
|
if params.AdminSecret != adminSecret {
|
||||||
return res, fmt.Errorf(`invalid admin secret`)
|
return res, fmt.Errorf(`invalid admin secret`)
|
||||||
}
|
}
|
||||||
|
|
||||||
hashedKey, err := utils.EncryptPassword(adminSecret)
|
hashedKey, err := crypto.EncryptPassword(adminSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
@@ -25,7 +26,7 @@ func AdminSessionResolver(ctx context.Context) (*model.Response, error) {
|
|||||||
return res, fmt.Errorf("unauthorized")
|
return res, fmt.Errorf("unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
hashedKey, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
hashedKey, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
@@ -33,18 +34,18 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
adminSecret := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
adminSecret := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
||||||
|
|
||||||
if adminSecret != "" {
|
if adminSecret != "" {
|
||||||
err = fmt.Errorf("admin sign up already completed")
|
err = fmt.Errorf("admin sign up already completed")
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyAdminSecret, params.AdminSecret)
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyAdminSecret, params.AdminSecret)
|
||||||
// consvert EnvData to JSON
|
// consvert EnvData to JSON
|
||||||
var storeData envstore.Store
|
var storeData envstore.Store
|
||||||
|
|
||||||
jsonBytes, err := json.Marshal(envstore.EnvInMemoryStoreObj.GetEnvStoreClone())
|
jsonBytes, err := json.Marshal(envstore.EnvStoreObj.GetEnvStoreClone())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
@@ -58,7 +59,7 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
envData, err := utils.EncryptEnvData(storeData)
|
envData, err := crypto.EncryptEnvData(storeData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
@@ -68,7 +69,7 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hashedKey, err := utils.EncryptPassword(params.AdminSecret)
|
hashedKey, err := crypto.EncryptPassword(params.AdminSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*mod
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionstore.DeleteAllUserSession(fmt.Sprintf("%x", user.ID))
|
go sessionstore.DeleteAllUserSession(fmt.Sprintf("%x", user.ID))
|
||||||
|
|
||||||
err = db.Provider.DeleteUser(user)
|
err = db.Provider.DeleteUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -26,8 +26,10 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get clone of store
|
// get clone of store
|
||||||
store := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
store := envstore.EnvStoreObj.GetEnvStoreClone()
|
||||||
adminSecret := store.StringEnv[constants.EnvKeyAdminSecret]
|
adminSecret := store.StringEnv[constants.EnvKeyAdminSecret]
|
||||||
|
clientID := store.StringEnv[constants.EnvKeyClientID]
|
||||||
|
clientSecret := store.StringEnv[constants.EnvKeyClientSecret]
|
||||||
databaseURL := store.StringEnv[constants.EnvKeyDatabaseURL]
|
databaseURL := store.StringEnv[constants.EnvKeyDatabaseURL]
|
||||||
databaseName := store.StringEnv[constants.EnvKeyDatabaseName]
|
databaseName := store.StringEnv[constants.EnvKeyDatabaseName]
|
||||||
databaseType := store.StringEnv[constants.EnvKeyDatabaseType]
|
databaseType := store.StringEnv[constants.EnvKeyDatabaseType]
|
||||||
@@ -40,6 +42,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]
|
||||||
@@ -63,9 +67,11 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
|
|||||||
|
|
||||||
res = &model.Env{
|
res = &model.Env{
|
||||||
AdminSecret: &adminSecret,
|
AdminSecret: &adminSecret,
|
||||||
DatabaseName: &databaseName,
|
DatabaseName: databaseName,
|
||||||
DatabaseURL: &databaseURL,
|
DatabaseURL: databaseURL,
|
||||||
DatabaseType: &databaseType,
|
DatabaseType: databaseType,
|
||||||
|
ClientID: clientID,
|
||||||
|
ClientSecret: clientSecret,
|
||||||
CustomAccessTokenScript: &customAccessTokenScript,
|
CustomAccessTokenScript: &customAccessTokenScript,
|
||||||
SMTPHost: &smtpHost,
|
SMTPHost: &smtpHost,
|
||||||
SMTPPort: &smtpPort,
|
SMTPPort: &smtpPort,
|
||||||
@@ -74,6 +80,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,
|
||||||
|
@@ -24,7 +24,7 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
if envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
||||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||||
}
|
}
|
||||||
params.Email = strings.ToLower(params.Email)
|
params.Email = strings.ToLower(params.Email)
|
||||||
@@ -39,7 +39,11 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
hostname := utils.GetHost(gc)
|
hostname := utils.GetHost(gc)
|
||||||
verificationToken, err := token.CreateVerificationToken(params.Email, constants.VerificationTypeForgotPassword, hostname)
|
nonce, nonceHash, err := utils.GenerateNonce()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
verificationToken, err := token.CreateVerificationToken(params.Email, constants.VerificationTypeForgotPassword, hostname, nonceHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error generating token`, err)
|
log.Println(`error generating token`, err)
|
||||||
}
|
}
|
||||||
@@ -48,12 +52,11 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
|
|||||||
Identifier: constants.VerificationTypeForgotPassword,
|
Identifier: constants.VerificationTypeForgotPassword,
|
||||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||||
Email: params.Email,
|
Email: params.Email,
|
||||||
|
Nonce: nonce,
|
||||||
})
|
})
|
||||||
|
|
||||||
// exec it as go routin so that we can reduce the api latency
|
// exec it as go routin so that we can reduce the api latency
|
||||||
go func() {
|
go email.SendForgotPasswordMail(params.Email, verificationToken, hostname)
|
||||||
email.SendForgotPasswordMail(params.Email, verificationToken, hostname)
|
|
||||||
}()
|
|
||||||
|
|
||||||
res = &model.Response{
|
res = &model.Response{
|
||||||
Message: `Please check your inbox! We have sent a password reset link.`,
|
Message: `Please check your inbox! We have sent a password reset link.`,
|
||||||
|
@@ -1,52 +0,0 @@
|
|||||||
package resolvers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
|
||||||
tokenHelper "github.com/authorizerdev/authorizer/server/token"
|
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsValidJwtResolver resolver to return if given jwt is valid
|
|
||||||
func IsValidJwtResolver(ctx context.Context, params *model.IsValidJWTQueryInput) (*model.ValidJWTResponse, error) {
|
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
token, err := token.GetAccessToken(gc)
|
|
||||||
|
|
||||||
if token == "" || err != nil {
|
|
||||||
if params != nil && *params.Jwt != "" {
|
|
||||||
token = *params.Jwt
|
|
||||||
} else {
|
|
||||||
return nil, errors.New("no jwt provided via cookie / header / params")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
claims, err := tokenHelper.VerifyJWTToken(token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
claimRoleInterface := claims[envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtRoleClaim)].([]interface{})
|
|
||||||
claimRoles := []string{}
|
|
||||||
for _, v := range claimRoleInterface {
|
|
||||||
claimRoles = append(claimRoles, v.(string))
|
|
||||||
}
|
|
||||||
|
|
||||||
if params != nil && params.Roles != nil && len(params.Roles) > 0 {
|
|
||||||
for _, v := range params.Roles {
|
|
||||||
if !utils.StringSliceContains(claimRoles, v) {
|
|
||||||
return nil, fmt.Errorf(`unauthorized`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &model.ValidJWTResponse{
|
|
||||||
Valid: true,
|
|
||||||
Message: "Valid JWT",
|
|
||||||
}, nil
|
|
||||||
}
|
|
@@ -25,7 +25,7 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
||||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
|||||||
log.Println("compare password error:", err)
|
log.Println("compare password error:", err)
|
||||||
return res, fmt.Errorf(`invalid password`)
|
return res, fmt.Errorf(`invalid password`)
|
||||||
}
|
}
|
||||||
roles := envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
roles := envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
||||||
currentRoles := strings.Split(user.Roles, ",")
|
currentRoles := strings.Split(user.Roles, ",")
|
||||||
if len(params.Roles) > 0 {
|
if len(params.Roles) > 0 {
|
||||||
if !utils.IsValidRoles(currentRoles, params.Roles) {
|
if !utils.IsValidRoles(currentRoles, params.Roles) {
|
||||||
@@ -59,20 +59,36 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
|||||||
roles = params.Roles
|
roles = params.Roles
|
||||||
}
|
}
|
||||||
|
|
||||||
authToken, err := token.CreateAuthToken(user, roles)
|
scope := []string{"openid", "email", "profile"}
|
||||||
|
if params.Scope != nil && len(scope) > 0 {
|
||||||
|
scope = params.Scope
|
||||||
|
}
|
||||||
|
|
||||||
|
authToken, err := token.CreateAuthToken(gc, user, roles, scope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
sessionstore.SetUserSession(user.ID, authToken.FingerPrint, authToken.RefreshToken.Token)
|
|
||||||
cookie.SetCookie(gc, authToken.AccessToken.Token, authToken.RefreshToken.Token, authToken.FingerPrintHash)
|
|
||||||
utils.SaveSessionInDB(user.ID, gc)
|
|
||||||
|
|
||||||
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
|
|
||||||
|
expiresIn := int64(1800)
|
||||||
res = &model.AuthResponse{
|
res = &model.AuthResponse{
|
||||||
Message: `Logged in successfully`,
|
Message: `Logged in successfully`,
|
||||||
AccessToken: &authToken.AccessToken.Token,
|
AccessToken: &authToken.AccessToken.Token,
|
||||||
ExpiresAt: &authToken.AccessToken.ExpiresAt,
|
IDToken: &authToken.IDToken.Token,
|
||||||
|
ExpiresIn: &expiresIn,
|
||||||
User: user.AsAPIUser(),
|
User: user.AsAPIUser(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
|
||||||
|
if authToken.RefreshToken != nil {
|
||||||
|
res.RefreshToken = &authToken.RefreshToken.Token
|
||||||
|
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
go utils.SaveSessionInDB(gc, user.ID)
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
@@ -4,9 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,34 +18,21 @@ func LogoutResolver(ctx context.Context) (*model.Response, error) {
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// get refresh token
|
|
||||||
refreshToken, err := token.GetRefreshToken(gc)
|
|
||||||
if err != nil {
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// get fingerprint hash
|
// get fingerprint hash
|
||||||
fingerprintHash, err := token.GetFingerPrint(gc)
|
fingerprintHash, err := cookie.GetSession(gc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptedFingerPrint, err := utils.DecryptAES([]byte(fingerprintHash))
|
decryptedFingerPrint, err := crypto.DecryptAES(fingerprintHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fingerPrint := string(decryptedFingerPrint)
|
fingerPrint := string(decryptedFingerPrint)
|
||||||
|
|
||||||
// verify refresh token and fingerprint
|
sessionstore.RemoveState(fingerPrint)
|
||||||
claims, err := token.VerifyJWTToken(refreshToken)
|
cookie.DeleteSession(gc)
|
||||||
if err != nil {
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
userID := claims["id"].(string)
|
|
||||||
sessionstore.DeleteUserSession(userID, fingerPrint)
|
|
||||||
cookie.DeleteCookie(gc)
|
|
||||||
|
|
||||||
res = &model.Response{
|
res = &model.Response{
|
||||||
Message: "Logged out successfully",
|
Message: "Logged out successfully",
|
||||||
|
@@ -25,7 +25,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin) {
|
||||||
return res, fmt.Errorf(`magic link login is disabled for this instance`)
|
return res, fmt.Errorf(`magic link login is disabled for this instance`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,13 +49,13 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
// define roles for new user
|
// define roles for new user
|
||||||
if len(params.Roles) > 0 {
|
if len(params.Roles) > 0 {
|
||||||
// check if roles exists
|
// check if roles exists
|
||||||
if !utils.IsValidRoles(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), params.Roles) {
|
if !utils.IsValidRoles(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), params.Roles) {
|
||||||
return res, fmt.Errorf(`invalid roles`)
|
return res, fmt.Errorf(`invalid roles`)
|
||||||
} else {
|
} else {
|
||||||
inputRoles = params.Roles
|
inputRoles = params.Roles
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
inputRoles = envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
inputRoles = envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Roles = strings.Join(inputRoles, ",")
|
user.Roles = strings.Join(inputRoles, ",")
|
||||||
@@ -80,7 +80,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
// check if it contains protected unassigned role
|
// check if it contains protected unassigned role
|
||||||
hasProtectedRole := false
|
hasProtectedRole := false
|
||||||
for _, ur := range unasignedRoles {
|
for _, ur := range unasignedRoles {
|
||||||
if utils.StringSliceContains(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles), ur) {
|
if utils.StringSliceContains(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles), ur) {
|
||||||
hasProtectedRole = true
|
hasProtectedRole = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,10 +107,14 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
hostname := utils.GetHost(gc)
|
hostname := utils.GetHost(gc)
|
||||||
if !envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
|
if !envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
|
||||||
// insert verification request
|
// insert verification request
|
||||||
|
nonce, nonceHash, err := utils.GenerateNonce()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
verificationType := constants.VerificationTypeMagicLinkLogin
|
verificationType := constants.VerificationTypeMagicLinkLogin
|
||||||
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname)
|
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname, nonceHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error generating token`, err)
|
log.Println(`error generating token`, err)
|
||||||
}
|
}
|
||||||
@@ -119,12 +123,11 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
Identifier: verificationType,
|
Identifier: verificationType,
|
||||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||||
Email: params.Email,
|
Email: params.Email,
|
||||||
|
Nonce: nonce,
|
||||||
})
|
})
|
||||||
|
|
||||||
// exec it as go routin so that we can reduce the api latency
|
// exec it as go routin so that we can reduce the api latency
|
||||||
go func() {
|
go email.SendVerificationMail(params.Email, verificationToken, hostname)
|
||||||
email.SendVerificationMail(params.Email, verificationToken, hostname)
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = &model.Response{
|
res = &model.Response{
|
||||||
|
@@ -2,7 +2,6 @@ package resolvers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
@@ -18,13 +17,17 @@ func ProfileResolver(ctx context.Context) (*model.User, error) {
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
claims, err := token.ValidateAccessToken(gc)
|
accessToken, err := token.GetAccessToken(gc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
userID := fmt.Sprintf("%v", claims["id"])
|
claims, err := token.ValidateAccessToken(gc, accessToken)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userID := claims["sub"].(string)
|
||||||
user, err := db.Provider.GetUserByID(userID)
|
user, err := db.Provider.GetUserByID(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
|
@@ -44,7 +44,11 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
|
|||||||
}
|
}
|
||||||
|
|
||||||
hostname := utils.GetHost(gc)
|
hostname := utils.GetHost(gc)
|
||||||
verificationToken, err := token.CreateVerificationToken(params.Email, params.Identifier, hostname)
|
nonce, nonceHash, err := utils.GenerateNonce()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
verificationToken, err := token.CreateVerificationToken(params.Email, params.Identifier, hostname, nonceHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error generating token`, err)
|
log.Println(`error generating token`, err)
|
||||||
}
|
}
|
||||||
@@ -53,12 +57,11 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
|
|||||||
Identifier: params.Identifier,
|
Identifier: params.Identifier,
|
||||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||||
Email: params.Email,
|
Email: params.Email,
|
||||||
|
Nonce: nonce,
|
||||||
})
|
})
|
||||||
|
|
||||||
// exec it as go routin so that we can reduce the api latency
|
// exec it as go routin so that we can reduce the api latency
|
||||||
go func() {
|
go email.SendVerificationMail(params.Email, verificationToken, hostname)
|
||||||
email.SendVerificationMail(params.Email, verificationToken, hostname)
|
|
||||||
}()
|
|
||||||
|
|
||||||
res = &model.Response{
|
res = &model.Response{
|
||||||
Message: `Verification email has been sent. Please check your inbox`,
|
Message: `Verification email has been sent. Please check your inbox`,
|
||||||
|
@@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
@@ -17,7 +18,11 @@ import (
|
|||||||
// ResetPasswordResolver is a resolver for reset password mutation
|
// ResetPasswordResolver is a resolver for reset password mutation
|
||||||
func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error) {
|
func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error) {
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
if envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
||||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,17 +36,22 @@ 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)
|
hostname := utils.GetHost(gc)
|
||||||
|
encryptedNonce, err := utils.EncryptNonce(verificationRequest.Nonce)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
claim, err := token.ParseJWTToken(params.Token, hostname, encryptedNonce, verificationRequest.Email)
|
||||||
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["sub"].(string))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
password, _ := utils.EncryptPassword(params.Password)
|
password, _ := crypto.EncryptPassword(params.Password)
|
||||||
user.Password = &password
|
user.Password = &password
|
||||||
|
|
||||||
signupMethod := user.SignupMethods
|
signupMethod := user.SignupMethods
|
||||||
|
@@ -13,6 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// SessionResolver is a resolver for session query
|
// SessionResolver is a resolver for session query
|
||||||
|
// TODO allow validating with code and code verifier instead of cookie (PKCE flow)
|
||||||
func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*model.AuthResponse, error) {
|
func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*model.AuthResponse, error) {
|
||||||
var res *model.AuthResponse
|
var res *model.AuthResponse
|
||||||
|
|
||||||
@@ -21,48 +22,27 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// get refresh token
|
sessionToken, err := cookie.GetSession(gc)
|
||||||
refreshToken, err := token.GetRefreshToken(gc)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// get fingerprint hash
|
// get session from cookie
|
||||||
fingerprintHash, err := token.GetFingerPrint(gc)
|
claims, err := token.ValidateBrowserSession(gc, sessionToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
userID := claims.Subject
|
||||||
decryptedFingerPrint, err := utils.DecryptAES([]byte(fingerprintHash))
|
|
||||||
if err != nil {
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fingerPrint := string(decryptedFingerPrint)
|
|
||||||
|
|
||||||
// verify refresh token and fingerprint
|
|
||||||
claims, err := token.VerifyJWTToken(refreshToken)
|
|
||||||
if err != nil {
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
userID := claims["id"].(string)
|
|
||||||
|
|
||||||
persistedRefresh := sessionstore.GetUserSession(userID, fingerPrint)
|
|
||||||
if refreshToken != persistedRefresh {
|
|
||||||
return res, fmt.Errorf(`unauthorized`)
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := db.Provider.GetUserByID(userID)
|
user, err := db.Provider.GetUserByID(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// refresh token has "roles" as claim
|
// refresh token has "roles" as claim
|
||||||
claimRoleInterface := claims["roles"].([]interface{})
|
claimRoleInterface := claims.Roles
|
||||||
claimRoles := []string{}
|
claimRoles := []string{}
|
||||||
for _, v := range claimRoleInterface {
|
for _, v := range claimRoleInterface {
|
||||||
claimRoles = append(claimRoles, v.(string))
|
claimRoles = append(claimRoles, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if params != nil && params.Roles != nil && len(params.Roles) > 0 {
|
if params != nil && params.Roles != nil && len(params.Roles) > 0 {
|
||||||
@@ -73,22 +53,35 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete older session
|
scope := []string{"openid", "email", "profile"}
|
||||||
sessionstore.DeleteUserSession(userID, fingerPrint)
|
if params != nil && params.Scope != nil && len(scope) > 0 {
|
||||||
|
scope = params.Scope
|
||||||
|
}
|
||||||
|
|
||||||
authToken, err := token.CreateAuthToken(user, claimRoles)
|
authToken, err := token.CreateAuthToken(gc, user, claimRoles, scope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
sessionstore.SetUserSession(user.ID, authToken.FingerPrint, authToken.RefreshToken.Token)
|
|
||||||
cookie.SetCookie(gc, authToken.AccessToken.Token, authToken.RefreshToken.Token, authToken.FingerPrintHash)
|
|
||||||
|
|
||||||
|
// rollover the session for security
|
||||||
|
sessionstore.RemoveState(sessionToken)
|
||||||
|
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
|
|
||||||
|
expiresIn := int64(1800)
|
||||||
res = &model.AuthResponse{
|
res = &model.AuthResponse{
|
||||||
Message: `Session token refreshed`,
|
Message: `Session token refreshed`,
|
||||||
AccessToken: &authToken.AccessToken.Token,
|
AccessToken: &authToken.AccessToken.Token,
|
||||||
ExpiresAt: &authToken.AccessToken.ExpiresAt,
|
ExpiresIn: &expiresIn,
|
||||||
|
IDToken: &authToken.IDToken.Token,
|
||||||
User: user.AsAPIUser(),
|
User: user.AsAPIUser(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if authToken.RefreshToken != nil {
|
||||||
|
res.RefreshToken = &authToken.RefreshToken.Token
|
||||||
|
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
}
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/email"
|
"github.com/authorizerdev/authorizer/server/email"
|
||||||
@@ -27,7 +28,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
||||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||||
}
|
}
|
||||||
if params.ConfirmPassword != params.Password {
|
if params.ConfirmPassword != params.Password {
|
||||||
@@ -57,13 +58,13 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||||||
|
|
||||||
if len(params.Roles) > 0 {
|
if len(params.Roles) > 0 {
|
||||||
// check if roles exists
|
// check if roles exists
|
||||||
if !utils.IsValidRoles(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), params.Roles) {
|
if !utils.IsValidRoles(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), params.Roles) {
|
||||||
return res, fmt.Errorf(`invalid roles`)
|
return res, fmt.Errorf(`invalid roles`)
|
||||||
} else {
|
} else {
|
||||||
inputRoles = params.Roles
|
inputRoles = params.Roles
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
inputRoles = envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
inputRoles = envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
||||||
}
|
}
|
||||||
|
|
||||||
user := models.User{
|
user := models.User{
|
||||||
@@ -72,7 +73,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||||||
|
|
||||||
user.Roles = strings.Join(inputRoles, ",")
|
user.Roles = strings.Join(inputRoles, ",")
|
||||||
|
|
||||||
password, _ := utils.EncryptPassword(params.Password)
|
password, _ := crypto.EncryptPassword(params.Password)
|
||||||
user.Password = &password
|
user.Password = &password
|
||||||
|
|
||||||
if params.GivenName != nil {
|
if params.GivenName != nil {
|
||||||
@@ -108,7 +109,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||||||
}
|
}
|
||||||
|
|
||||||
user.SignupMethods = constants.SignupMethodBasicAuth
|
user.SignupMethods = constants.SignupMethodBasicAuth
|
||||||
if envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
user.EmailVerifiedAt = &now
|
user.EmailVerifiedAt = &now
|
||||||
}
|
}
|
||||||
@@ -120,43 +121,50 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||||||
userToReturn := user.AsAPIUser()
|
userToReturn := user.AsAPIUser()
|
||||||
|
|
||||||
hostname := utils.GetHost(gc)
|
hostname := utils.GetHost(gc)
|
||||||
if !envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
|
if !envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
|
||||||
// insert verification request
|
// insert verification request
|
||||||
verificationType := constants.VerificationTypeBasicAuthSignup
|
nonce, nonceHash, err := utils.GenerateNonce()
|
||||||
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error generating token`, err)
|
return res, err
|
||||||
|
}
|
||||||
|
verificationType := constants.VerificationTypeBasicAuthSignup
|
||||||
|
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname, nonceHash)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
}
|
}
|
||||||
db.Provider.AddVerificationRequest(models.VerificationRequest{
|
db.Provider.AddVerificationRequest(models.VerificationRequest{
|
||||||
Token: verificationToken,
|
Token: verificationToken,
|
||||||
Identifier: verificationType,
|
Identifier: verificationType,
|
||||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||||
Email: params.Email,
|
Email: params.Email,
|
||||||
|
Nonce: nonce,
|
||||||
})
|
})
|
||||||
|
|
||||||
// exec it as go routin so that we can reduce the api latency
|
// exec it as go routin so that we can reduce the api latency
|
||||||
go func() {
|
go email.SendVerificationMail(params.Email, verificationToken, hostname)
|
||||||
email.SendVerificationMail(params.Email, verificationToken, hostname)
|
|
||||||
}()
|
|
||||||
|
|
||||||
res = &model.AuthResponse{
|
res = &model.AuthResponse{
|
||||||
Message: `Verification email has been sent. Please check your inbox`,
|
Message: `Verification email has been sent. Please check your inbox`,
|
||||||
User: userToReturn,
|
User: userToReturn,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
scope := []string{"openid", "email", "profile"}
|
||||||
|
|
||||||
authToken, err := token.CreateAuthToken(user, roles)
|
authToken, err := token.CreateAuthToken(gc, user, roles, scope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
sessionstore.SetUserSession(user.ID, authToken.FingerPrint, authToken.RefreshToken.Token)
|
|
||||||
cookie.SetCookie(gc, authToken.AccessToken.Token, authToken.RefreshToken.Token, authToken.FingerPrintHash)
|
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
|
||||||
utils.SaveSessionInDB(user.ID, gc)
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
|
go utils.SaveSessionInDB(gc, user.ID)
|
||||||
|
|
||||||
|
expiresIn := int64(1800)
|
||||||
|
|
||||||
res = &model.AuthResponse{
|
res = &model.AuthResponse{
|
||||||
Message: `Signed up successfully.`,
|
Message: `Signed up successfully.`,
|
||||||
AccessToken: &authToken.AccessToken.Token,
|
AccessToken: &authToken.AccessToken.Token,
|
||||||
ExpiresAt: &authToken.AccessToken.ExpiresAt,
|
ExpiresIn: &expiresIn,
|
||||||
User: userToReturn,
|
User: userToReturn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
@@ -33,6 +34,66 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
|
|||||||
return res, fmt.Errorf("unauthorized")
|
return res, fmt.Errorf("unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updatedData := envstore.EnvStoreObj.GetEnvStoreClone()
|
||||||
|
|
||||||
|
isJWTUpdated := false
|
||||||
|
algo := updatedData.StringEnv[constants.EnvKeyJwtType]
|
||||||
|
if params.JwtType != nil {
|
||||||
|
algo = *params.JwtType
|
||||||
|
if !crypto.IsHMACA(algo) && !crypto.IsECDSA(algo) && !crypto.IsRSA(algo) {
|
||||||
|
return res, fmt.Errorf("invalid jwt type")
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedData.StringEnv[constants.EnvKeyJwtType] = algo
|
||||||
|
isJWTUpdated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.JwtSecret != nil || params.JwtPublicKey != nil || params.JwtPrivateKey != nil {
|
||||||
|
isJWTUpdated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if isJWTUpdated {
|
||||||
|
// check if jwt secret is provided
|
||||||
|
if crypto.IsHMACA(algo) {
|
||||||
|
if params.JwtSecret == nil {
|
||||||
|
return res, fmt.Errorf("jwt secret is required for HMAC algorithm")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if crypto.IsRSA(algo) {
|
||||||
|
if params.JwtPrivateKey == nil || params.JwtPublicKey == nil {
|
||||||
|
return res, fmt.Errorf("jwt private and public key is required for RSA (PKCS1) / ECDSA algorithm")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = crypto.ParseRsaPrivateKeyFromPemStr(*params.JwtPrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := crypto.ParseRsaPublicKeyFromPemStr(*params.JwtPublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if crypto.IsECDSA(algo) {
|
||||||
|
if params.JwtPrivateKey == nil || params.JwtPublicKey == nil {
|
||||||
|
return res, fmt.Errorf("jwt private and public key is required for RSA (PKCS1) / ECDSA algorithm")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = crypto.ParseEcdsaPrivateKeyFromPemStr(*params.JwtPrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := crypto.ParseEcdsaPublicKeyFromPemStr(*params.JwtPublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
var data map[string]interface{}
|
var data map[string]interface{}
|
||||||
byteData, err := json.Marshal(params)
|
byteData, err := json.Marshal(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -50,7 +111,7 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
|
|||||||
return res, errors.New("admin secret and old admin secret are required for secret change")
|
return res, errors.New("admin secret and old admin secret are required for secret change")
|
||||||
}
|
}
|
||||||
|
|
||||||
if *params.OldAdminSecret != envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) {
|
if *params.OldAdminSecret != envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) {
|
||||||
return res, errors.New("old admin secret is not correct")
|
return res, errors.New("old admin secret is not correct")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +122,6 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedData := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
|
||||||
for key, value := range data {
|
for key, value := range data {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
fieldType := reflect.TypeOf(value).String()
|
fieldType := reflect.TypeOf(value).String()
|
||||||
@@ -116,9 +176,21 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update local store
|
// Update local store
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvStore(updatedData)
|
envstore.EnvStoreObj.UpdateEnvStore(updatedData)
|
||||||
sessionstore.InitSession()
|
jwk, err := crypto.GenerateJWKBasedOnEnv()
|
||||||
oauth.InitOAuth()
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
// updating jwk
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJWK, jwk)
|
||||||
|
err = sessionstore.InitSession()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
err = oauth.InitOAuth()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch the current db store and update it
|
// Fetch the current db store and update it
|
||||||
env, err := db.Provider.GetEnv()
|
env, err := db.Provider.GetEnv()
|
||||||
@@ -127,14 +199,14 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
|
|||||||
}
|
}
|
||||||
|
|
||||||
if params.AdminSecret != nil {
|
if params.AdminSecret != nil {
|
||||||
hashedKey, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
hashedKey, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
cookie.SetAdminCookie(gc, hashedKey)
|
cookie.SetAdminCookie(gc, hashedKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedConfig, err := utils.EncryptEnvData(updatedData)
|
encryptedConfig, err := crypto.EncryptEnvData(updatedData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
@@ -9,9 +9,11 @@ import (
|
|||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/email"
|
"github.com/authorizerdev/authorizer/server/email"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
@@ -27,7 +29,11 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
claims, err := token.ValidateAccessToken(gc)
|
accessToken, err := token.GetAccessToken(gc)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
claims, err := token.ValidateAccessToken(gc, accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
@@ -37,8 +43,8 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
|||||||
return res, fmt.Errorf("please enter at least one param to update")
|
return res, fmt.Errorf("please enter at least one param to update")
|
||||||
}
|
}
|
||||||
|
|
||||||
userEmail := fmt.Sprintf("%v", claims["email"])
|
userID := claims["sub"].(string)
|
||||||
user, err := db.Provider.GetUserByEmail(userEmail)
|
user, err := db.Provider.GetUserByID(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
@@ -92,7 +98,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
|||||||
return res, fmt.Errorf(`password and confirm password does not match`)
|
return res, fmt.Errorf(`password and confirm password does not match`)
|
||||||
}
|
}
|
||||||
|
|
||||||
password, _ := utils.EncryptPassword(*params.NewPassword)
|
password, _ := crypto.EncryptPassword(*params.NewPassword)
|
||||||
|
|
||||||
user.Password = &password
|
user.Password = &password
|
||||||
}
|
}
|
||||||
@@ -107,38 +113,44 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
|||||||
newEmail := strings.ToLower(*params.Email)
|
newEmail := strings.ToLower(*params.Email)
|
||||||
// check if user with new email exists
|
// check if user with new email exists
|
||||||
_, err := db.Provider.GetUserByEmail(newEmail)
|
_, err := db.Provider.GetUserByEmail(newEmail)
|
||||||
|
|
||||||
// err = nil means user exists
|
// err = nil means user exists
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return res, fmt.Errorf("user with this email address already exists")
|
return res, fmt.Errorf("user with this email address already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionstore.DeleteAllUserSession(fmt.Sprintf("%v", user.ID))
|
// TODO figure out how to delete all user sessions
|
||||||
cookie.DeleteCookie(gc)
|
go sessionstore.DeleteAllUserSession(user.ID)
|
||||||
|
|
||||||
hostname := utils.GetHost(gc)
|
cookie.DeleteSession(gc)
|
||||||
user.Email = newEmail
|
user.Email = newEmail
|
||||||
user.EmailVerifiedAt = nil
|
|
||||||
hasEmailChanged = true
|
if !envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
|
||||||
// insert verification request
|
hostname := utils.GetHost(gc)
|
||||||
verificationType := constants.VerificationTypeUpdateEmail
|
user.EmailVerifiedAt = nil
|
||||||
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname)
|
hasEmailChanged = true
|
||||||
if err != nil {
|
// insert verification request
|
||||||
log.Println(`error generating token`, err)
|
nonce, nonceHash, err := utils.GenerateNonce()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
verificationType := constants.VerificationTypeUpdateEmail
|
||||||
|
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname, nonceHash)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(`error generating token`, err)
|
||||||
|
}
|
||||||
|
db.Provider.AddVerificationRequest(models.VerificationRequest{
|
||||||
|
Token: verificationToken,
|
||||||
|
Identifier: verificationType,
|
||||||
|
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||||
|
Email: newEmail,
|
||||||
|
Nonce: nonce,
|
||||||
|
})
|
||||||
|
|
||||||
|
// exec it as go routin so that we can reduce the api latency
|
||||||
|
go email.SendVerificationMail(newEmail, verificationToken, hostname)
|
||||||
|
|
||||||
}
|
}
|
||||||
db.Provider.AddVerificationRequest(models.VerificationRequest{
|
|
||||||
Token: verificationToken,
|
|
||||||
Identifier: verificationType,
|
|
||||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
|
||||||
Email: newEmail,
|
|
||||||
})
|
|
||||||
|
|
||||||
// exec it as go routin so that we can reduce the api latency
|
|
||||||
go func() {
|
|
||||||
email.SendVerificationMail(newEmail, verificationToken, hostname)
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = db.Provider.UpdateUser(user)
|
_, err = db.Provider.UpdateUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating user:", err)
|
log.Println("error updating user:", err)
|
||||||
|
@@ -8,7 +8,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/email"
|
"github.com/authorizerdev/authorizer/server/email"
|
||||||
@@ -95,15 +94,19 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
|||||||
return res, fmt.Errorf("user with this email address already exists")
|
return res, fmt.Errorf("user with this email address already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionstore.DeleteAllUserSession(fmt.Sprintf("%v", user.ID))
|
// TODO figure out how to do this
|
||||||
cookie.DeleteCookie(gc)
|
go sessionstore.DeleteAllUserSession(user.ID)
|
||||||
|
|
||||||
hostname := utils.GetHost(gc)
|
hostname := utils.GetHost(gc)
|
||||||
user.Email = newEmail
|
user.Email = newEmail
|
||||||
user.EmailVerifiedAt = nil
|
user.EmailVerifiedAt = nil
|
||||||
// insert verification request
|
// insert verification request
|
||||||
|
nonce, nonceHash, err := utils.GenerateNonce()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
verificationType := constants.VerificationTypeUpdateEmail
|
verificationType := constants.VerificationTypeUpdateEmail
|
||||||
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname)
|
verificationToken, err := token.CreateVerificationToken(newEmail, verificationType, hostname, nonceHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error generating token`, err)
|
log.Println(`error generating token`, err)
|
||||||
}
|
}
|
||||||
@@ -112,12 +115,12 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
|||||||
Identifier: verificationType,
|
Identifier: verificationType,
|
||||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||||
Email: newEmail,
|
Email: newEmail,
|
||||||
|
Nonce: nonce,
|
||||||
})
|
})
|
||||||
|
|
||||||
// exec it as go routin so that we can reduce the api latency
|
// exec it as go routin so that we can reduce the api latency
|
||||||
go func() {
|
go email.SendVerificationMail(newEmail, verificationToken, hostname)
|
||||||
email.SendVerificationMail(newEmail, verificationToken, hostname)
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rolesToSave := ""
|
rolesToSave := ""
|
||||||
@@ -128,7 +131,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
|||||||
inputRoles = append(inputRoles, *item)
|
inputRoles = append(inputRoles, *item)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !utils.IsValidRoles(inputRoles, append([]string{}, append(envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles)...)...)) {
|
if !utils.IsValidRoles(inputRoles, append([]string{}, append(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles)...)...)) {
|
||||||
return res, fmt.Errorf("invalid list of roles")
|
return res, fmt.Errorf("invalid list of roles")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,8 +139,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
|||||||
rolesToSave = strings.Join(inputRoles, ",")
|
rolesToSave = strings.Join(inputRoles, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionstore.DeleteAllUserSession(fmt.Sprintf("%v", user.ID))
|
go sessionstore.DeleteAllUserSession(user.ID)
|
||||||
cookie.DeleteCookie(gc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if rolesToSave != "" {
|
if rolesToSave != "" {
|
||||||
|
@@ -24,16 +24,21 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
|
|||||||
|
|
||||||
verificationRequest, err := db.Provider.GetVerificationRequestByToken(params.Token)
|
verificationRequest, err := db.Provider.GetVerificationRequestByToken(params.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, fmt.Errorf(`invalid token`)
|
return res, fmt.Errorf(`invalid token: %s`, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify if token exists in db
|
// verify if token exists in db
|
||||||
claim, err := token.VerifyVerificationToken(params.Token)
|
hostname := utils.GetHost(gc)
|
||||||
|
encryptedNonce, err := utils.EncryptNonce(verificationRequest.Nonce)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, fmt.Errorf(`invalid token`)
|
return res, err
|
||||||
|
}
|
||||||
|
claim, err := token.ParseJWTToken(params.Token, hostname, encryptedNonce, verificationRequest.Email)
|
||||||
|
if err != nil {
|
||||||
|
return res, fmt.Errorf(`invalid token: %s`, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := db.Provider.GetUserByEmail(claim.Email)
|
user, err := db.Provider.GetUserByEmail(claim["sub"].(string))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
@@ -41,25 +46,35 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
|
|||||||
// update email_verified_at in users table
|
// update email_verified_at in users table
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
user.EmailVerifiedAt = &now
|
user.EmailVerifiedAt = &now
|
||||||
db.Provider.UpdateUser(user)
|
user, err = db.Provider.UpdateUser(user)
|
||||||
// delete from verification table
|
if err != nil {
|
||||||
db.Provider.DeleteVerificationRequest(verificationRequest)
|
return res, err
|
||||||
|
}
|
||||||
roles := strings.Split(user.Roles, ",")
|
// delete from verification table
|
||||||
authToken, err := token.CreateAuthToken(user, roles)
|
err = db.Provider.DeleteVerificationRequest(verificationRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
sessionstore.SetUserSession(user.ID, authToken.FingerPrint, authToken.RefreshToken.Token)
|
|
||||||
cookie.SetCookie(gc, authToken.AccessToken.Token, authToken.RefreshToken.Token, authToken.FingerPrintHash)
|
|
||||||
utils.SaveSessionInDB(user.ID, gc)
|
|
||||||
|
|
||||||
|
roles := strings.Split(user.Roles, ",")
|
||||||
|
scope := []string{"openid", "email", "profile"}
|
||||||
|
authToken, err := token.CreateAuthToken(gc, user, roles, scope)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
|
||||||
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
|
go utils.SaveSessionInDB(gc, user.ID)
|
||||||
|
|
||||||
|
expiresIn := int64(1800)
|
||||||
res = &model.AuthResponse{
|
res = &model.AuthResponse{
|
||||||
Message: `Email verified successfully.`,
|
Message: `Email verified successfully.`,
|
||||||
AccessToken: &authToken.AccessToken.Token,
|
AccessToken: &authToken.AccessToken.Token,
|
||||||
ExpiresAt: &authToken.AccessToken.ExpiresAt,
|
IDToken: &authToken.IDToken.Token,
|
||||||
|
ExpiresIn: &expiresIn,
|
||||||
User: user.AsAPIUser(),
|
User: user.AsAPIUser(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,13 @@ func InitRouter() *gin.Engine {
|
|||||||
router.GET("/oauth_login/:oauth_provider", handlers.OAuthLoginHandler())
|
router.GET("/oauth_login/:oauth_provider", handlers.OAuthLoginHandler())
|
||||||
router.GET("/oauth_callback/:oauth_provider", handlers.OAuthCallbackHandler())
|
router.GET("/oauth_callback/:oauth_provider", handlers.OAuthCallbackHandler())
|
||||||
router.GET("/verify_email", handlers.VerifyEmailHandler())
|
router.GET("/verify_email", handlers.VerifyEmailHandler())
|
||||||
|
// OPEN ID routes
|
||||||
|
router.GET("/.well-known/openid-configuration", handlers.OpenIDConfigurationHandler())
|
||||||
|
router.GET("/.well-known/jwks.json", handlers.JWKsHandler())
|
||||||
|
router.GET("/authorize", handlers.AuthorizeHandler())
|
||||||
|
router.GET("/userinfo", handlers.UserInfoHandler())
|
||||||
|
router.GET("/logout", handlers.LogoutHandler())
|
||||||
|
router.POST("/oauth/token", handlers.TokenHandler())
|
||||||
|
|
||||||
router.LoadHTMLGlob("templates/*")
|
router.LoadHTMLGlob("templates/*")
|
||||||
// login page app related routes.
|
// login page app related routes.
|
||||||
|
@@ -1,112 +1,74 @@
|
|||||||
package sessionstore
|
package sessionstore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InMemoryStore is a simple in-memory store for sessions.
|
// InMemoryStore is a simple in-memory store for sessions.
|
||||||
type InMemoryStore struct {
|
type InMemoryStore struct {
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
store map[string]map[string]string
|
sessionStore map[string]map[string]string
|
||||||
socialLoginState map[string]string
|
stateStore map[string]string
|
||||||
}
|
|
||||||
|
|
||||||
// AddUserSession adds a user session to the in-memory store.
|
|
||||||
func (c *InMemoryStore) AddUserSession(userId, accessToken, refreshToken string) {
|
|
||||||
c.mutex.Lock()
|
|
||||||
defer c.mutex.Unlock()
|
|
||||||
// delete sessions > 500 // not recommended for production
|
|
||||||
if len(c.store) >= 500 {
|
|
||||||
c.store = map[string]map[string]string{}
|
|
||||||
}
|
|
||||||
// check if entry exists in map
|
|
||||||
_, exists := c.store[userId]
|
|
||||||
if exists {
|
|
||||||
tempMap := c.store[userId]
|
|
||||||
tempMap[accessToken] = refreshToken
|
|
||||||
c.store[userId] = tempMap
|
|
||||||
} else {
|
|
||||||
tempMap := map[string]string{
|
|
||||||
accessToken: refreshToken,
|
|
||||||
}
|
|
||||||
c.store[userId] = tempMap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteAllUserSession deletes all the user sessions from in-memory store.
|
|
||||||
func (c *InMemoryStore) DeleteAllUserSession(userId string) {
|
|
||||||
c.mutex.Lock()
|
|
||||||
defer c.mutex.Unlock()
|
|
||||||
delete(c.store, userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteUserSession deletes the particular user session from in-memory store.
|
|
||||||
func (c *InMemoryStore) DeleteUserSession(userId, accessToken string) {
|
|
||||||
c.mutex.Lock()
|
|
||||||
defer c.mutex.Unlock()
|
|
||||||
delete(c.store[userId], accessToken)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearStore clears the in-memory store.
|
// ClearStore clears the in-memory store.
|
||||||
func (c *InMemoryStore) ClearStore() {
|
func (c *InMemoryStore) ClearStore() {
|
||||||
c.mutex.Lock()
|
c.mutex.Lock()
|
||||||
defer c.mutex.Unlock()
|
defer c.mutex.Unlock()
|
||||||
c.store = map[string]map[string]string{}
|
c.sessionStore = map[string]map[string]string{}
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserSession returns the user session token from the in-memory store.
|
|
||||||
func (c *InMemoryStore) GetUserSession(userId, accessToken string) string {
|
|
||||||
// c.mutex.Lock()
|
|
||||||
// defer c.mutex.Unlock()
|
|
||||||
|
|
||||||
token := ""
|
|
||||||
if sessionMap, ok := c.store[userId]; ok {
|
|
||||||
if val, ok := sessionMap[accessToken]; ok {
|
|
||||||
token = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return token
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserSessions returns all the user session token from the in-memory store.
|
// GetUserSessions returns all the user session token from the in-memory store.
|
||||||
func (c *InMemoryStore) GetUserSessions(userId string) map[string]string {
|
func (c *InMemoryStore) GetUserSessions(userId string) map[string]string {
|
||||||
// c.mutex.Lock()
|
// c.mutex.Lock()
|
||||||
// defer c.mutex.Unlock()
|
// defer c.mutex.Unlock()
|
||||||
|
res := map[string]string{}
|
||||||
sessionMap, ok := c.store[userId]
|
for k, v := range c.stateStore {
|
||||||
if !ok {
|
split := strings.Split(v, "@")
|
||||||
return nil
|
if split[1] == userId {
|
||||||
|
res[k] = split[0]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sessionMap
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetSocialLoginState sets the social login state in the in-memory store.
|
// DeleteAllUserSession deletes all the user sessions from in-memory store.
|
||||||
func (c *InMemoryStore) SetSocialLoginState(key, state string) {
|
func (c *InMemoryStore) DeleteAllUserSession(userId string) {
|
||||||
|
// c.mutex.Lock()
|
||||||
|
// defer c.mutex.Unlock()
|
||||||
|
sessions := GetUserSessions(userId)
|
||||||
|
for k := range sessions {
|
||||||
|
RemoveState(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetState sets the state in the in-memory store.
|
||||||
|
func (c *InMemoryStore) SetState(key, state string) {
|
||||||
c.mutex.Lock()
|
c.mutex.Lock()
|
||||||
defer c.mutex.Unlock()
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
c.socialLoginState[key] = state
|
c.stateStore[key] = state
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSocialLoginState gets the social login state from the in-memory store.
|
// GetState gets the state from the in-memory store.
|
||||||
func (c *InMemoryStore) GetSocialLoginState(key string) string {
|
func (c *InMemoryStore) GetState(key string) string {
|
||||||
c.mutex.Lock()
|
c.mutex.Lock()
|
||||||
defer c.mutex.Unlock()
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
state := ""
|
state := ""
|
||||||
if stateVal, ok := c.socialLoginState[key]; ok {
|
if stateVal, ok := c.stateStore[key]; ok {
|
||||||
state = stateVal
|
state = stateVal
|
||||||
}
|
}
|
||||||
|
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveSocialLoginState removes the social login state from the in-memory store.
|
// RemoveState removes the state from the in-memory store.
|
||||||
func (c *InMemoryStore) RemoveSocialLoginState(key string) {
|
func (c *InMemoryStore) RemoveState(key string) {
|
||||||
c.mutex.Lock()
|
c.mutex.Lock()
|
||||||
defer c.mutex.Unlock()
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
delete(c.socialLoginState, key)
|
delete(c.stateStore, key)
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
}
|
@@ -2,41 +2,13 @@ package sessionstore
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
|
"strings"
|
||||||
"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
|
|
||||||
func (c *RedisStore) AddUserSession(userId, accessToken, refreshToken string) {
|
|
||||||
err := c.store.HMSet(c.ctx, "authorizer_"+userId, map[string]string{
|
|
||||||
accessToken: refreshToken,
|
|
||||||
}).Err()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("Error saving redis token:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteAllUserSession deletes all the user session from redis
|
|
||||||
func (c *RedisStore) DeleteAllUserSession(userId string) {
|
|
||||||
err := c.store.Del(c.ctx, "authorizer_"+userId).Err()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("Error deleting redis token:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteUserSession deletes the particular user session from redis
|
|
||||||
func (c *RedisStore) DeleteUserSession(userId, accessToken string) {
|
|
||||||
err := c.store.HDel(c.ctx, "authorizer_"+userId, accessToken).Err()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("Error deleting redis token:", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearStore clears the redis store for authorizer related tokens
|
// ClearStore clears the redis store for authorizer related tokens
|
||||||
@@ -47,41 +19,49 @@ func (c *RedisStore) ClearStore() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserSession returns the user session token from the redis store.
|
|
||||||
func (c *RedisStore) GetUserSession(userId, accessToken string) string {
|
|
||||||
token := ""
|
|
||||||
res, err := c.store.HMGet(c.ctx, "authorizer_"+userId, accessToken).Result()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("error getting token from redis store:", err)
|
|
||||||
}
|
|
||||||
if len(res) > 0 && res[0] != nil {
|
|
||||||
token = fmt.Sprintf("%v", res[0])
|
|
||||||
}
|
|
||||||
return token
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserSessions returns all the user session token from the redis store.
|
// GetUserSessions returns all the user session token from the redis store.
|
||||||
func (c *RedisStore) GetUserSessions(userID string) map[string]string {
|
func (c *RedisStore) GetUserSessions(userID string) map[string]string {
|
||||||
res, err := c.store.HGetAll(c.ctx, "authorizer_"+userID).Result()
|
data, err := c.store.HGetAll(c.ctx, "*").Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error getting token from redis store:", err)
|
log.Println("error getting token from redis store:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res := map[string]string{}
|
||||||
|
for k, v := range data {
|
||||||
|
split := strings.Split(v, "@")
|
||||||
|
if split[1] == userID {
|
||||||
|
res[k] = split[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetSocialLoginState sets the social login state in redis store.
|
// DeleteAllUserSession deletes all the user session from redis
|
||||||
func (c *RedisStore) SetSocialLoginState(key, state string) {
|
func (c *RedisStore) DeleteAllUserSession(userId string) {
|
||||||
err := c.store.Set(c.ctx, key, state, 0).Err()
|
sessions := GetUserSessions(userId)
|
||||||
|
for k, v := range sessions {
|
||||||
|
if k == "token" {
|
||||||
|
err := c.store.Del(c.ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error deleting redis token:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetState sets the state in redis store.
|
||||||
|
func (c *RedisStore) SetState(key, value string) {
|
||||||
|
err := c.store.Set(c.ctx, "authorizer_"+key, value, 0).Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Error saving redis token:", err)
|
log.Fatalln("Error saving redis token:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSocialLoginState gets the social login state from redis store.
|
// GetState gets the state from redis store.
|
||||||
func (c *RedisStore) GetSocialLoginState(key string) string {
|
func (c *RedisStore) GetState(key string) string {
|
||||||
state := ""
|
state := ""
|
||||||
state, err := c.store.Get(c.ctx, key).Result()
|
state, err := c.store.Get(c.ctx, "authorizer_"+key).Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error getting token from redis store:", err)
|
log.Println("error getting token from redis store:", err)
|
||||||
}
|
}
|
||||||
@@ -89,9 +69,9 @@ func (c *RedisStore) GetSocialLoginState(key string) string {
|
|||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveSocialLoginState removes the social login state from redis store.
|
// RemoveState removes the state from redis store.
|
||||||
func (c *RedisStore) RemoveSocialLoginState(key string) {
|
func (c *RedisStore) RemoveState(key string) {
|
||||||
err := c.store.Del(c.ctx, key).Err()
|
err := c.store.Del(c.ctx, "authorizer_"+key).Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Error deleting redis token:", err)
|
log.Fatalln("Error deleting redis token:", err)
|
||||||
}
|
}
|
||||||
|
@@ -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"
|
||||||
@@ -21,26 +22,6 @@ type SessionStore struct {
|
|||||||
// reference to various session store instances
|
// reference to various session store instances
|
||||||
var SessionStoreObj SessionStore
|
var SessionStoreObj SessionStore
|
||||||
|
|
||||||
// SetUserSession sets the user session in the session store
|
|
||||||
func SetUserSession(userId, fingerprint, refreshToken string) {
|
|
||||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
|
||||||
SessionStoreObj.RedisMemoryStoreObj.AddUserSession(userId, fingerprint, refreshToken)
|
|
||||||
}
|
|
||||||
if SessionStoreObj.InMemoryStoreObj != nil {
|
|
||||||
SessionStoreObj.InMemoryStoreObj.AddUserSession(userId, fingerprint, refreshToken)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteUserSession deletes the particular user session from the session store
|
|
||||||
func DeleteUserSession(userId, fingerprint string) {
|
|
||||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
|
||||||
SessionStoreObj.RedisMemoryStoreObj.DeleteUserSession(userId, fingerprint)
|
|
||||||
}
|
|
||||||
if SessionStoreObj.InMemoryStoreObj != nil {
|
|
||||||
SessionStoreObj.InMemoryStoreObj.DeleteUserSession(userId, fingerprint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteAllSessions deletes all the sessions from the session store
|
// DeleteAllSessions deletes all the sessions from the session store
|
||||||
func DeleteAllUserSession(userId string) {
|
func DeleteAllUserSession(userId string) {
|
||||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
||||||
@@ -51,18 +32,6 @@ func DeleteAllUserSession(userId string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserSession returns the user session from the session store
|
|
||||||
func GetUserSession(userId, fingerprint string) string {
|
|
||||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
|
||||||
return SessionStoreObj.RedisMemoryStoreObj.GetUserSession(userId, fingerprint)
|
|
||||||
}
|
|
||||||
if SessionStoreObj.InMemoryStoreObj != nil {
|
|
||||||
return SessionStoreObj.InMemoryStoreObj.GetUserSession(userId, fingerprint)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserSessions returns all the user sessions from the session store
|
// GetUserSessions returns all the user sessions from the session store
|
||||||
func GetUserSessions(userId string) map[string]string {
|
func GetUserSessions(userId string) map[string]string {
|
||||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
||||||
@@ -85,62 +54,97 @@ func ClearStore() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetSocialLoginState sets the social login state in the session store
|
// SetState sets the login state (key, value form) in the session store
|
||||||
func SetSocailLoginState(key, state string) {
|
func SetState(key, state string) {
|
||||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
||||||
SessionStoreObj.RedisMemoryStoreObj.SetSocialLoginState(key, state)
|
SessionStoreObj.RedisMemoryStoreObj.SetState(key, state)
|
||||||
}
|
}
|
||||||
if SessionStoreObj.InMemoryStoreObj != nil {
|
if SessionStoreObj.InMemoryStoreObj != nil {
|
||||||
SessionStoreObj.InMemoryStoreObj.SetSocialLoginState(key, state)
|
SessionStoreObj.InMemoryStoreObj.SetState(key, state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSocialLoginState returns the social login state from the session store
|
// GetState returns the state from the session store
|
||||||
func GetSocailLoginState(key string) string {
|
func GetState(key string) string {
|
||||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
||||||
return SessionStoreObj.RedisMemoryStoreObj.GetSocialLoginState(key)
|
return SessionStoreObj.RedisMemoryStoreObj.GetState(key)
|
||||||
}
|
}
|
||||||
if SessionStoreObj.InMemoryStoreObj != nil {
|
if SessionStoreObj.InMemoryStoreObj != nil {
|
||||||
return SessionStoreObj.InMemoryStoreObj.GetSocialLoginState(key)
|
return SessionStoreObj.InMemoryStoreObj.GetState(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveSocialLoginState removes the social login state from the session store
|
// RemoveState removes the social login state from the session store
|
||||||
func RemoveSocialLoginState(key string) {
|
func RemoveState(key string) {
|
||||||
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
if SessionStoreObj.RedisMemoryStoreObj != nil {
|
||||||
SessionStoreObj.RedisMemoryStoreObj.RemoveSocialLoginState(key)
|
SessionStoreObj.RedisMemoryStoreObj.RemoveState(key)
|
||||||
}
|
}
|
||||||
if SessionStoreObj.InMemoryStoreObj != nil {
|
if SessionStoreObj.InMemoryStoreObj != nil {
|
||||||
SessionStoreObj.InMemoryStoreObj.RemoveSocialLoginState(key)
|
SessionStoreObj.InMemoryStoreObj.RemoveState(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitializeSessionStore initializes the SessionStoreObj based on environment variables
|
// InitializeSessionStore initializes the SessionStoreObj based on environment variables
|
||||||
func InitSession() {
|
func InitSession() error {
|
||||||
if envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL) != "" {
|
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL) != "" {
|
||||||
log.Println("using redis store to save sessions")
|
log.Println("using redis store to save sessions")
|
||||||
opt, err := redis.ParseURL(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL))
|
|
||||||
if err != nil {
|
redisURL := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL)
|
||||||
log.Fatalln("Error parsing redis url:", err)
|
redisURLHostPortsList := strings.Split(redisURL, ",")
|
||||||
|
|
||||||
|
if len(redisURLHostPortsList) > 1 {
|
||||||
|
opt, err := redis.ParseURL(redisURLHostPortsList[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
urls := []string{opt.Addr}
|
||||||
|
urlList := redisURLHostPortsList[1:]
|
||||||
|
urls = append(urls, urlList...)
|
||||||
|
clusterOpt := &redis.ClusterOptions{Addrs: urls}
|
||||||
|
|
||||||
|
rdb := redis.NewClusterClient(clusterOpt)
|
||||||
|
ctx := context.Background()
|
||||||
|
_, err = rdb.Ping(ctx).Result()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
SessionStoreObj.RedisMemoryStoreObj = &RedisStore{
|
||||||
|
ctx: ctx,
|
||||||
|
store: rdb,
|
||||||
|
}
|
||||||
|
|
||||||
|
// return on successful initialization
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opt, err := redis.ParseURL(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyRedisURL))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
rdb := redis.NewClient(opt)
|
rdb := redis.NewClient(opt)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
_, err = rdb.Ping(ctx).Result()
|
_, err = rdb.Ping(ctx).Result()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Error connecting to redis server", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionStoreObj.RedisMemoryStoreObj = &RedisStore{
|
SessionStoreObj.RedisMemoryStoreObj = &RedisStore{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
store: rdb,
|
store: rdb,
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
// return on successful initialization
|
||||||
SessionStoreObj.InMemoryStoreObj = &InMemoryStore{
|
return nil
|
||||||
store: map[string]map[string]string{},
|
|
||||||
socialLoginState: map[string]string{},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if redis url is not set use in memory store
|
||||||
|
SessionStoreObj.InMemoryStoreObj = &InMemoryStore{
|
||||||
|
sessionStore: map[string]map[string]string{},
|
||||||
|
stateStore: map[string]string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,7 @@ func adminLoginTests(t *testing.T, s TestSetup) {
|
|||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
_, err = resolvers.AdminLoginResolver(ctx, model.AdminLoginInput{
|
_, err = resolvers.AdminLoginResolver(ctx, model.AdminLoginInput{
|
||||||
AdminSecret: envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret),
|
AdminSecret: envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret),
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
@@ -5,9 +5,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,9 +18,9 @@ func adminLogoutTests(t *testing.T, s TestSetup) {
|
|||||||
_, err := resolvers.AdminLogoutResolver(ctx)
|
_, err := resolvers.AdminLogoutResolver(ctx)
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
h, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
||||||
_, err = resolvers.AdminLogoutResolver(ctx)
|
_, err = resolvers.AdminLogoutResolver(ctx)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
@@ -5,9 +5,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,9 +18,9 @@ func adminSessionTests(t *testing.T, s TestSetup) {
|
|||||||
_, err := resolvers.AdminSessionResolver(ctx)
|
_, err := resolvers.AdminSessionResolver(ctx)
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
h, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
||||||
_, err = resolvers.AdminSessionResolver(ctx)
|
_, err = resolvers.AdminSessionResolver(ctx)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
@@ -20,7 +20,7 @@ func adminSignupTests(t *testing.T, s TestSetup) {
|
|||||||
|
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
// reset env for test to pass
|
// reset env for test to pass
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyAdminSecret, "")
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyAdminSecret, "")
|
||||||
|
|
||||||
_, err = resolvers.AdminSignupResolver(ctx, model.AdminSignupInput{
|
_, err = resolvers.AdminSignupResolver(ctx, model.AdminSignupInput{
|
||||||
AdminSecret: "admin123",
|
AdminSecret: "admin123",
|
||||||
|
@@ -5,10 +5,10 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,9 +28,9 @@ func deleteUserTest(t *testing.T, s TestSetup) {
|
|||||||
})
|
})
|
||||||
assert.NotNil(t, err, "unauthorized")
|
assert.NotNil(t, err, "unauthorized")
|
||||||
|
|
||||||
h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
h, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
||||||
|
|
||||||
_, err = resolvers.DeleteUserResolver(ctx, model.DeleteUserInput{
|
_, err = resolvers.DeleteUserResolver(ctx, model.DeleteUserInput{
|
||||||
Email: email,
|
Email: email,
|
||||||
|
@@ -10,15 +10,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestEnvs(t *testing.T) {
|
func TestEnvs(t *testing.T) {
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEnvPath, "../../.env.sample")
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEnvPath, "../../.env.sample")
|
||||||
env.InitEnv()
|
env.InitAllEnv()
|
||||||
store := envstore.EnvInMemoryStoreObj.GetEnvStoreClone()
|
store := envstore.EnvStoreObj.GetEnvStoreClone()
|
||||||
|
|
||||||
assert.Equal(t, store.StringEnv[constants.EnvKeyEnv], "production")
|
assert.Equal(t, store.StringEnv[constants.EnvKeyEnv], "production")
|
||||||
assert.False(t, store.BoolEnv[constants.EnvKeyDisableEmailVerification])
|
assert.False(t, store.BoolEnv[constants.EnvKeyDisableEmailVerification])
|
||||||
assert.False(t, store.BoolEnv[constants.EnvKeyDisableMagicLinkLogin])
|
assert.False(t, store.BoolEnv[constants.EnvKeyDisableMagicLinkLogin])
|
||||||
assert.False(t, store.BoolEnv[constants.EnvKeyDisableBasicAuthentication])
|
assert.False(t, store.BoolEnv[constants.EnvKeyDisableBasicAuthentication])
|
||||||
assert.Equal(t, store.StringEnv[constants.EnvKeyJwtType], "HS256")
|
assert.Equal(t, store.StringEnv[constants.EnvKeyJwtType], "RS256")
|
||||||
assert.Equal(t, store.StringEnv[constants.EnvKeyJwtRoleClaim], "role")
|
assert.Equal(t, store.StringEnv[constants.EnvKeyJwtRoleClaim], "role")
|
||||||
assert.EqualValues(t, store.SliceEnv[constants.EnvKeyRoles], []string{"user"})
|
assert.EqualValues(t, store.SliceEnv[constants.EnvKeyRoles], []string{"user"})
|
||||||
assert.EqualValues(t, store.SliceEnv[constants.EnvKeyDefaultRoles], []string{"user"})
|
assert.EqualValues(t, store.SliceEnv[constants.EnvKeyDefaultRoles], []string{"user"})
|
||||||
|
@@ -5,9 +5,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,12 +18,12 @@ func envTests(t *testing.T, s TestSetup) {
|
|||||||
_, err := resolvers.EnvResolver(ctx)
|
_, err := resolvers.EnvResolver(ctx)
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
h, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
||||||
res, err := resolvers.EnvResolver(ctx)
|
res, err := resolvers.EnvResolver(ctx)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, *res.AdminSecret, envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
assert.Equal(t, *res.AdminSecret, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -1,38 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func isValidJWTTests(t *testing.T, s TestSetup) {
|
|
||||||
t.Helper()
|
|
||||||
_, ctx := createContext(s)
|
|
||||||
expiredToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbGxvd2VkX3JvbGVzIjpbIiJdLCJiaXJ0aGRhdGUiOm51bGwsImNyZWF0ZWRfYXQiOjAsImVtYWlsIjoiam9obi5kb2VAZ21haWwuY29tIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJleHAiOjE2NDI5NjEwMTEsImV4dHJhIjp7IngtZXh0cmEtaWQiOiJkMmNhMjQwNy05MzZmLTQwYzQtOTQ2NS05Y2M5MWYxZTJhNDQifSwiZmFtaWx5X25hbWUiOm51bGwsImdlbmRlciI6bnVsbCwiZ2l2ZW5fbmFtZSI6bnVsbCwiaWF0IjoxNjQyOTYwOTgxLCJpZCI6ImQyY2EyNDA3LTkzNmYtNDBjNC05NDY1LTljYzkxZjFlMmE0NCIsIm1pZGRsZV9uYW1lIjpudWxsLCJuaWNrbmFtZSI6bnVsbCwicGhvbmVfbnVtYmVyIjpudWxsLCJwaG9uZV9udW1iZXJfdmVyaWZpZWQiOmZhbHNlLCJwaWN0dXJlIjpudWxsLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJqb2huLmRvZUBnbWFpbC5jb20iLCJyb2xlIjpbXSwic2lnbnVwX21ldGhvZHMiOiIiLCJ0b2tlbl90eXBlIjoiYWNjZXNzX3Rva2VuIiwidXBkYXRlZF9hdCI6MH0.FrdyeOC5e8uU1SowGj0omFJuwRnh4BrEk89S_fbEkzs"
|
|
||||||
|
|
||||||
t.Run(`should fail for invalid jwt`, func(t *testing.T) {
|
|
||||||
_, err := resolvers.IsValidJwtResolver(ctx, &model.IsValidJWTQueryInput{
|
|
||||||
Jwt: &expiredToken,
|
|
||||||
})
|
|
||||||
assert.NotNil(t, err)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run(`should pass with valid jwt`, func(t *testing.T) {
|
|
||||||
authToken, err := token.CreateAuthToken(models.User{
|
|
||||||
ID: uuid.New().String(),
|
|
||||||
Email: "john.doe@gmail.com",
|
|
||||||
}, []string{})
|
|
||||||
assert.Nil(t, err)
|
|
||||||
res, err := resolvers.IsValidJwtResolver(ctx, &model.IsValidJWTQueryInput{
|
|
||||||
Jwt: &authToken.AccessToken.Token,
|
|
||||||
})
|
|
||||||
assert.Nil(t, err)
|
|
||||||
assert.True(t, res.Valid)
|
|
||||||
})
|
|
||||||
}
|
|
172
server/test/jwt_test.go
Normal file
172
server/test/jwt_test.go
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
|
"github.com/golang-jwt/jwt"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestJwt(t *testing.T) {
|
||||||
|
// persist older data till test is done and then reset it
|
||||||
|
jwtType := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
|
||||||
|
publicKey := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)
|
||||||
|
privateKey := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJwtPrivateKey)
|
||||||
|
clientID := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyClientID)
|
||||||
|
nonce := uuid.New().String()
|
||||||
|
hostname := "localhost"
|
||||||
|
subject := "test"
|
||||||
|
claims := jwt.MapClaims{
|
||||||
|
"exp": time.Now().Add(time.Minute * 30).Unix(),
|
||||||
|
"iat": time.Now().Unix(),
|
||||||
|
"email": "test@yopmail.com",
|
||||||
|
"sub": subject,
|
||||||
|
"aud": clientID,
|
||||||
|
"nonce": nonce,
|
||||||
|
"iss": hostname,
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("invalid jwt type", func(t *testing.T) {
|
||||||
|
envstore.EnvStoreObj.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.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "HS256")
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtSecret, "test")
|
||||||
|
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, hostname, nonce, subject)
|
||||||
|
assert.Error(t, err, err.Error(), "Token is expired")
|
||||||
|
})
|
||||||
|
t.Run("HMAC algorithms", func(t *testing.T) {
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtSecret, "test")
|
||||||
|
t.Run("HS256", func(t *testing.T) {
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "HS256")
|
||||||
|
jwtToken, err := token.SignJWTToken(claims)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, jwtToken)
|
||||||
|
c, err := token.ParseJWTToken(jwtToken, hostname, nonce, subject)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, c["email"].(string), claims["email"])
|
||||||
|
})
|
||||||
|
t.Run("HS384", func(t *testing.T) {
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "HS384")
|
||||||
|
jwtToken, err := token.SignJWTToken(claims)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, jwtToken)
|
||||||
|
c, err := token.ParseJWTToken(jwtToken, hostname, nonce, subject)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, c["email"].(string), claims["email"])
|
||||||
|
})
|
||||||
|
t.Run("HS512", func(t *testing.T) {
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "HS512")
|
||||||
|
jwtToken, err := token.SignJWTToken(claims)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, jwtToken)
|
||||||
|
c, err := token.ParseJWTToken(jwtToken, hostname, nonce, subject)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, c["email"].(string), claims["email"])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("RSA algorithms", func(t *testing.T) {
|
||||||
|
t.Run("RS256", func(t *testing.T) {
|
||||||
|
_, privateKey, publickKey, _, err := crypto.NewRSAKey("RS256", clientID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "RS256")
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, privateKey)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, publickKey)
|
||||||
|
jwtToken, err := token.SignJWTToken(claims)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, jwtToken)
|
||||||
|
c, err := token.ParseJWTToken(jwtToken, hostname, nonce, subject)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, c["email"].(string), claims["email"])
|
||||||
|
})
|
||||||
|
t.Run("RS384", func(t *testing.T) {
|
||||||
|
_, privateKey, publickKey, _, err := crypto.NewRSAKey("RS384", clientID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "RS384")
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, privateKey)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, publickKey)
|
||||||
|
jwtToken, err := token.SignJWTToken(claims)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, jwtToken)
|
||||||
|
c, err := token.ParseJWTToken(jwtToken, hostname, nonce, subject)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, c["email"].(string), claims["email"])
|
||||||
|
})
|
||||||
|
t.Run("RS512", func(t *testing.T) {
|
||||||
|
_, privateKey, publickKey, _, err := crypto.NewRSAKey("RS512", clientID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "RS512")
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, privateKey)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, publickKey)
|
||||||
|
jwtToken, err := token.SignJWTToken(claims)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, jwtToken)
|
||||||
|
c, err := token.ParseJWTToken(jwtToken, hostname, nonce, subject)
|
||||||
|
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) {
|
||||||
|
_, privateKey, publickKey, _, err := crypto.NewECDSAKey("ES256", clientID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "ES256")
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, privateKey)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, publickKey)
|
||||||
|
jwtToken, err := token.SignJWTToken(claims)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, jwtToken)
|
||||||
|
c, err := token.ParseJWTToken(jwtToken, hostname, nonce, subject)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, c["email"].(string), claims["email"])
|
||||||
|
})
|
||||||
|
t.Run("ES384", func(t *testing.T) {
|
||||||
|
_, privateKey, publickKey, _, err := crypto.NewECDSAKey("ES384", clientID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "ES384")
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, privateKey)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, publickKey)
|
||||||
|
jwtToken, err := token.SignJWTToken(claims)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, jwtToken)
|
||||||
|
c, err := token.ParseJWTToken(jwtToken, hostname, nonce, subject)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, c["email"].(string), claims["email"])
|
||||||
|
})
|
||||||
|
t.Run("ES512", func(t *testing.T) {
|
||||||
|
_, privateKey, publickKey, _, err := crypto.NewECDSAKey("ES512", clientID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, "ES512")
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, privateKey)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, publickKey)
|
||||||
|
jwtToken, err := token.SignJWTToken(claims)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, jwtToken)
|
||||||
|
c, err := token.ParseJWTToken(jwtToken, hostname, nonce, subject)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, c["email"].(string), claims["email"])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtType, jwtType)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPublicKey, publicKey)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyJwtPrivateKey, privateKey)
|
||||||
|
}
|
@@ -5,14 +5,17 @@ import (
|
|||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func loginTests(t *testing.T, s TestSetup) {
|
func loginTests(t *testing.T, s TestSetup) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
t.Run(`should login`, func(t *testing.T) {
|
t.Run(`should login`, func(t *testing.T) {
|
||||||
|
t.Logf("=> is enabled: %v", envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification))
|
||||||
_, ctx := createContext(s)
|
_, ctx := createContext(s)
|
||||||
email := "login." + s.TestInfo.Email
|
email := "login." + s.TestInfo.Email
|
||||||
_, err := resolvers.SignupResolver(ctx, model.SignUpInput{
|
_, err := resolvers.SignupResolver(ctx, model.SignUpInput{
|
||||||
@@ -21,18 +24,23 @@ func loginTests(t *testing.T, s TestSetup) {
|
|||||||
ConfirmPassword: s.TestInfo.Password,
|
ConfirmPassword: s.TestInfo.Password,
|
||||||
})
|
})
|
||||||
|
|
||||||
_, err = resolvers.LoginResolver(ctx, model.LoginInput{
|
res, err := resolvers.LoginResolver(ctx, model.LoginInput{
|
||||||
Email: email,
|
Email: email,
|
||||||
Password: s.TestInfo.Password,
|
Password: s.TestInfo.Password,
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.NotNil(t, err, "should fail because email is not verified")
|
assert.NotNil(t, err, "should fail because email is not verified")
|
||||||
|
assert.Nil(t, res)
|
||||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||||
resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
n, err := utils.EncryptNonce(verificationRequest.Nonce)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, n)
|
||||||
|
assert.NotNil(t, verificationRequest)
|
||||||
|
res, err = resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||||
Token: verificationRequest.Token,
|
Token: verificationRequest.Token,
|
||||||
})
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, res)
|
||||||
_, err = resolvers.LoginResolver(ctx, model.LoginInput{
|
_, err = resolvers.LoginResolver(ctx, model.LoginInput{
|
||||||
Email: email,
|
Email: email,
|
||||||
Password: s.TestInfo.Password,
|
Password: s.TestInfo.Password,
|
||||||
|
@@ -2,7 +2,6 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
@@ -11,7 +10,6 @@ import (
|
|||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,18 +28,15 @@ func logoutTests(t *testing.T, s TestSetup) {
|
|||||||
Token: verificationRequest.Token,
|
Token: verificationRequest.Token,
|
||||||
})
|
})
|
||||||
|
|
||||||
sessions := sessionstore.GetUserSessions(verifyRes.User.ID)
|
|
||||||
fingerPrint := ""
|
|
||||||
refreshToken := ""
|
|
||||||
for key, val := range sessions {
|
|
||||||
fingerPrint = key
|
|
||||||
refreshToken = val
|
|
||||||
}
|
|
||||||
|
|
||||||
fingerPrintHash, _ := utils.EncryptAES([]byte(fingerPrint))
|
|
||||||
|
|
||||||
token := *verifyRes.AccessToken
|
token := *verifyRes.AccessToken
|
||||||
cookie := fmt.Sprintf("%s=%s;%s=%s;%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".fingerprint", url.QueryEscape(string(fingerPrintHash)), envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".refresh_token", refreshToken, envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".access_token", token)
|
sessions := sessionstore.GetUserSessions(verifyRes.User.ID)
|
||||||
|
cookie := ""
|
||||||
|
// set all they keys in cookie one of them should be session cookie
|
||||||
|
for key := range sessions {
|
||||||
|
if key != token {
|
||||||
|
cookie += fmt.Sprintf("%s=%s;", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+"_session", key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
req.Header.Set("Cookie", cookie)
|
req.Header.Set("Cookie", cookie)
|
||||||
_, err = resolvers.LogoutResolver(ctx)
|
_, err = resolvers.LogoutResolver(ctx)
|
||||||
|
@@ -1,12 +1,11 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -27,12 +26,13 @@ func magicLinkLoginTests(t *testing.T, s TestSetup) {
|
|||||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||||
Token: verificationRequest.Token,
|
Token: verificationRequest.Token,
|
||||||
})
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
token := *verifyRes.AccessToken
|
assert.NotNil(t, verifyRes.AccessToken)
|
||||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".access_token", token))
|
s.GinContext.Request.Header.Set("Authorization", "Bearer "+*verifyRes.AccessToken)
|
||||||
|
ctx = context.WithValue(req.Context(), "GinContextKey", s.GinContext)
|
||||||
_, err = resolvers.ProfileResolver(ctx)
|
_, err = resolvers.ProfileResolver(ctx)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
s.GinContext.Request.Header.Set("Authorization", "")
|
||||||
cleanData(email)
|
cleanData(email)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,11 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -14,7 +13,7 @@ import (
|
|||||||
|
|
||||||
func profileTests(t *testing.T, s TestSetup) {
|
func profileTests(t *testing.T, s TestSetup) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
t.Run(`should get profile only with token`, func(t *testing.T) {
|
t.Run(`should get profile only access_token token`, func(t *testing.T) {
|
||||||
req, ctx := createContext(s)
|
req, ctx := createContext(s)
|
||||||
email := "profile." + s.TestInfo.Email
|
email := "profile." + s.TestInfo.Email
|
||||||
|
|
||||||
@@ -31,11 +30,14 @@ func profileTests(t *testing.T, s TestSetup) {
|
|||||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||||
Token: verificationRequest.Token,
|
Token: verificationRequest.Token,
|
||||||
})
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, verifyRes.AccessToken)
|
||||||
|
|
||||||
token := *verifyRes.AccessToken
|
s.GinContext.Request.Header.Set("Authorization", "Bearer "+*verifyRes.AccessToken)
|
||||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".access_token", token))
|
ctx = context.WithValue(req.Context(), "GinContextKey", s.GinContext)
|
||||||
profileRes, err := resolvers.ProfileResolver(ctx)
|
profileRes, err := resolvers.ProfileResolver(ctx)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
s.GinContext.Request.Header.Set("Authorization", "")
|
||||||
|
|
||||||
newEmail := *&profileRes.Email
|
newEmail := *&profileRes.Email
|
||||||
assert.Equal(t, email, newEmail, "emails should be equal")
|
assert.Equal(t, email, newEmail, "emails should be equal")
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
@@ -12,29 +11,31 @@ import (
|
|||||||
|
|
||||||
func TestResolvers(t *testing.T) {
|
func TestResolvers(t *testing.T) {
|
||||||
databases := map[string]string{
|
databases := map[string]string{
|
||||||
constants.DbTypeSqlite: "../../data.db",
|
constants.DbTypeSqlite: "../../data.db",
|
||||||
constants.DbTypeArangodb: "http://localhost:8529",
|
// constants.DbTypeArangodb: "http://localhost:8529",
|
||||||
constants.DbTypeMongodb: "mongodb://localhost:27017",
|
// constants.DbTypeMongodb: "mongodb://localhost:27017",
|
||||||
}
|
}
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyVersion, "test")
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyVersion, "test")
|
||||||
for dbType, dbURL := range databases {
|
for dbType, dbURL := range databases {
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseURL, dbURL)
|
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseType, dbType)
|
|
||||||
|
|
||||||
s := testSetup()
|
s := testSetup()
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseURL, dbURL)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseType, dbType)
|
||||||
defer s.Server.Close()
|
defer s.Server.Close()
|
||||||
|
err := db.InitDB()
|
||||||
db.InitDB()
|
if err != nil {
|
||||||
|
t.Errorf("Error initializing database: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
// clean the persisted config for test to use fresh config
|
// clean the persisted config for test to use fresh config
|
||||||
envData, err := db.Provider.GetEnv()
|
envData, err := db.Provider.GetEnv()
|
||||||
log.Println("=> envData:", envstore.EnvInMemoryStoreObj.GetEnvStoreClone())
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
envData.EnvData = ""
|
envData.EnvData = ""
|
||||||
db.Provider.UpdateEnv(envData)
|
db.Provider.UpdateEnv(envData)
|
||||||
}
|
}
|
||||||
env.PersistEnv()
|
env.PersistEnv()
|
||||||
|
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEnv, "test")
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.BoolStoreIdentifier, constants.EnvKeyIsProd, false)
|
||||||
t.Run("should pass tests for "+dbType, func(t *testing.T) {
|
t.Run("should pass tests for "+dbType, func(t *testing.T) {
|
||||||
// admin tests
|
// admin tests
|
||||||
adminSignupTests(t, s)
|
adminSignupTests(t, s)
|
||||||
@@ -61,7 +62,6 @@ func TestResolvers(t *testing.T) {
|
|||||||
magicLinkLoginTests(t, s)
|
magicLinkLoginTests(t, s)
|
||||||
logoutTests(t, s)
|
logoutTests(t, s)
|
||||||
metaTests(t, s)
|
metaTests(t, s)
|
||||||
isValidJWTTests(t, s)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,17 +35,15 @@ func sessionTests(t *testing.T, s TestSetup) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
sessions := sessionstore.GetUserSessions(verifyRes.User.ID)
|
sessions := sessionstore.GetUserSessions(verifyRes.User.ID)
|
||||||
fingerPrint := ""
|
cookie := ""
|
||||||
refreshToken := ""
|
|
||||||
for key, val := range sessions {
|
|
||||||
fingerPrint = key
|
|
||||||
refreshToken = val
|
|
||||||
}
|
|
||||||
|
|
||||||
fingerPrintHash, _ := utils.EncryptAES([]byte(fingerPrint))
|
|
||||||
|
|
||||||
token := *verifyRes.AccessToken
|
token := *verifyRes.AccessToken
|
||||||
cookie := fmt.Sprintf("%s=%s;%s=%s;%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".fingerprint", url.QueryEscape(string(fingerPrintHash)), envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".refresh_token", refreshToken, envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".access_token", token)
|
// set all they keys in cookie one of them should be session cookie
|
||||||
|
for key := range sessions {
|
||||||
|
if key != token {
|
||||||
|
cookie += fmt.Sprintf("%s=%s;", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+"_session", key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cookie = strings.TrimSuffix(cookie, ";")
|
||||||
|
|
||||||
req.Header.Set("Cookie", cookie)
|
req.Header.Set("Cookie", cookie)
|
||||||
|
|
||||||
|
@@ -71,14 +71,16 @@ func testSetup() TestSetup {
|
|||||||
Password: "test",
|
Password: "test",
|
||||||
}
|
}
|
||||||
|
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEnvPath, "../../.env.sample")
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyEnvPath, "../../.env.sample")
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpHost, "smtp.yopmail.com")
|
env.InitRequiredEnv()
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpPort, "2525")
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpHost, "smtp.yopmail.com")
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpUsername, "lakhan@yopmail.com")
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpPort, "2525")
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpPassword, "test")
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpUsername, "lakhan@yopmail.com")
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySenderEmail, "info@yopmail.com")
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySmtpPassword, "test")
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.SliceStoreIdentifier, constants.EnvKeyProtectedRoles, []string{"admin"})
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeySenderEmail, "info@yopmail.com")
|
||||||
env.InitEnv()
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.SliceStoreIdentifier, constants.EnvKeyProtectedRoles, []string{"admin"})
|
||||||
|
db.InitDB()
|
||||||
|
env.InitAllEnv()
|
||||||
sessionstore.InitSession()
|
sessionstore.InitSession()
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
@@ -5,10 +5,10 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,16 +16,16 @@ func updateEnvTests(t *testing.T, s TestSetup) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
t.Run(`should update envs`, func(t *testing.T) {
|
t.Run(`should update envs`, func(t *testing.T) {
|
||||||
req, ctx := createContext(s)
|
req, ctx := createContext(s)
|
||||||
originalAppURL := envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAppURL)
|
originalAppURL := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAppURL)
|
||||||
|
|
||||||
data := model.UpdateEnvInput{}
|
data := model.UpdateEnvInput{}
|
||||||
_, err := resolvers.UpdateEnvResolver(ctx, data)
|
_, err := resolvers.UpdateEnvResolver(ctx, data)
|
||||||
|
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
h, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
||||||
newURL := "https://test.com"
|
newURL := "https://test.com"
|
||||||
disableLoginPage := true
|
disableLoginPage := true
|
||||||
allowedOrigins := []string{"http://localhost:8080"}
|
allowedOrigins := []string{"http://localhost:8080"}
|
||||||
@@ -37,9 +37,9 @@ func updateEnvTests(t *testing.T, s TestSetup) {
|
|||||||
_, err = resolvers.UpdateEnvResolver(ctx, data)
|
_, err = resolvers.UpdateEnvResolver(ctx, data)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAppURL), newURL)
|
assert.Equal(t, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAppURL), newURL)
|
||||||
assert.True(t, envstore.EnvInMemoryStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableLoginPage))
|
assert.True(t, envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableLoginPage))
|
||||||
assert.Equal(t, envstore.EnvInMemoryStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyAllowedOrigins), allowedOrigins)
|
assert.Equal(t, envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyAllowedOrigins), allowedOrigins)
|
||||||
|
|
||||||
disableLoginPage = false
|
disableLoginPage = false
|
||||||
data = model.UpdateEnvInput{
|
data = model.UpdateEnvInput{
|
||||||
|
@@ -1,12 +1,11 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -34,18 +33,16 @@ func updateProfileTests(t *testing.T, s TestSetup) {
|
|||||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||||
Token: verificationRequest.Token,
|
Token: verificationRequest.Token,
|
||||||
})
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
token := *verifyRes.AccessToken
|
s.GinContext.Request.Header.Set("Authorization", "Bearer "+*verifyRes.AccessToken)
|
||||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCookieName)+".access_token", token))
|
ctx = context.WithValue(req.Context(), "GinContextKey", s.GinContext)
|
||||||
_, err = resolvers.UpdateProfileResolver(ctx, model.UpdateProfileInput{
|
|
||||||
FamilyName: &fName,
|
|
||||||
})
|
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
newEmail := "new_" + email
|
newEmail := "new_" + email
|
||||||
_, err = resolvers.UpdateProfileResolver(ctx, model.UpdateProfileInput{
|
_, err = resolvers.UpdateProfileResolver(ctx, model.UpdateProfileInput{
|
||||||
Email: &newEmail,
|
Email: &newEmail,
|
||||||
})
|
})
|
||||||
|
s.GinContext.Request.Header.Set("Authorization", "")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
_, err = resolvers.ProfileResolver(ctx)
|
_, err = resolvers.ProfileResolver(ctx)
|
||||||
assert.NotNil(t, err, "unauthorized")
|
assert.NotNil(t, err, "unauthorized")
|
||||||
|
@@ -5,10 +5,10 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,9 +33,9 @@ func updateUserTest(t *testing.T, s TestSetup) {
|
|||||||
})
|
})
|
||||||
assert.NotNil(t, err, "unauthorized")
|
assert.NotNil(t, err, "unauthorized")
|
||||||
|
|
||||||
h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
h, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
||||||
_, err = resolvers.UpdateUserResolver(ctx, model.UpdateUserInput{
|
_, err = resolvers.UpdateUserResolver(ctx, model.UpdateUserInput{
|
||||||
ID: user.ID,
|
ID: user.ID,
|
||||||
Roles: newRoles,
|
Roles: newRoles,
|
||||||
|
@@ -2,14 +2,13 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,13 +35,12 @@ func usersTest(t *testing.T, s TestSetup) {
|
|||||||
usersRes, err := resolvers.UsersResolver(ctx, pagination)
|
usersRes, err := resolvers.UsersResolver(ctx, pagination)
|
||||||
assert.NotNil(t, err, "unauthorized")
|
assert.NotNil(t, err, "unauthorized")
|
||||||
|
|
||||||
h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
h, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h))
|
||||||
|
|
||||||
usersRes, err = resolvers.UsersResolver(ctx, pagination)
|
usersRes, err = resolvers.UsersResolver(ctx, pagination)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
log.Println("=> userRes:", usersRes)
|
|
||||||
rLen := len(usersRes.Users)
|
rLen := len(usersRes.Users)
|
||||||
assert.GreaterOrEqual(t, rLen, 1)
|
assert.GreaterOrEqual(t, rLen, 1)
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@ func TestIsValidEmail(t *testing.T) {
|
|||||||
func TestIsValidOrigin(t *testing.T) {
|
func TestIsValidOrigin(t *testing.T) {
|
||||||
// don't use portocal(http/https) for ALLOWED_ORIGINS while testing,
|
// don't use portocal(http/https) for ALLOWED_ORIGINS while testing,
|
||||||
// as we trim them off while running the main function
|
// as we trim them off while running the main function
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.SliceStoreIdentifier, constants.EnvKeyAllowedOrigins, []string{"localhost:8080", "*.google.com", "*.google.in", "*abc.*"})
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.SliceStoreIdentifier, constants.EnvKeyAllowedOrigins, []string{"localhost:8080", "*.google.com", "*.google.in", "*abc.*"})
|
||||||
assert.False(t, utils.IsValidOrigin("http://myapp.com"), "it should be invalid origin")
|
assert.False(t, utils.IsValidOrigin("http://myapp.com"), "it should be invalid origin")
|
||||||
assert.False(t, utils.IsValidOrigin("http://appgoogle.com"), "it should be invalid origin")
|
assert.False(t, utils.IsValidOrigin("http://appgoogle.com"), "it should be invalid origin")
|
||||||
assert.True(t, utils.IsValidOrigin("http://app.google.com"), "it should be valid origin")
|
assert.True(t, utils.IsValidOrigin("http://app.google.com"), "it should be valid origin")
|
||||||
@@ -32,7 +32,7 @@ func TestIsValidOrigin(t *testing.T) {
|
|||||||
assert.True(t, utils.IsValidOrigin("http://xyx.abc.in"), "it should be valid origin")
|
assert.True(t, utils.IsValidOrigin("http://xyx.abc.in"), "it should be valid origin")
|
||||||
assert.True(t, utils.IsValidOrigin("http://xyxabc.in"), "it should be valid origin")
|
assert.True(t, utils.IsValidOrigin("http://xyxabc.in"), "it should be valid origin")
|
||||||
assert.True(t, utils.IsValidOrigin("http://localhost:8080"), "it should be valid origin")
|
assert.True(t, utils.IsValidOrigin("http://localhost:8080"), "it should be valid origin")
|
||||||
envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.SliceStoreIdentifier, constants.EnvKeyAllowedOrigins, []string{"*"})
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.SliceStoreIdentifier, constants.EnvKeyAllowedOrigins, []string{"*"})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsValidIdentifier(t *testing.T) {
|
func TestIsValidIdentifier(t *testing.T) {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user