Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ed849fa6f6 | ||
![]() |
aec1f5df53 | ||
![]() |
45b4c41bca | ||
![]() |
63d486821e | ||
![]() |
4b56afdc98 | ||
![]() |
6455ff956a | ||
![]() |
3898e43fff | ||
![]() |
2c305e5bde | ||
![]() |
b8fd08e576 | ||
![]() |
6dafa45051 | ||
![]() |
ead3514113 | ||
![]() |
75a413e5f2 | ||
![]() |
91bf0e2478 | ||
![]() |
7a1305cf96 | ||
![]() |
ff5a6ec301 | ||
![]() |
b7b97b4f8d | ||
![]() |
d9bc989c74 |
@@ -7,7 +7,7 @@
|
||||
Authorizer
|
||||
</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 11+ databases including [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/), [YugaByte](https://www.yugabyte.com/), [MariaDB](https://mariadb.org/), [PlanetScale](https://planetscale.com/), [CassandraDB](https://cassandra.apache.org/_/index.html), [ScyllaDB](https://www.scylladb.com/), [MongoDB](https://mongodb.com/), [ArangoDB](https://www.arangodb.com/)).
|
||||
|
||||
## Table of contents
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
# Introduction
|
||||
|
||||
<img src="https://github.com/authorizerdev/authorizer/blob/main/assets/authorizer-architecture.png" style="height:20em"/>
|
||||
<img src="https://docs.authorizer.dev/images/authorizer-arch.png" style="height:20em"/>
|
||||
|
||||
#### We offer the following functionality
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
Deploy production ready Authorizer instance using one click deployment options available below
|
||||
|
||||
| **Infra provider** | **One-click link** | **Additional information** |
|
||||
| :----------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------: |
|
||||
| Railway.app | <a href="https://railway.app/new/template?template=https://github.com/authorizerdev/authorizer-railway&plugins=postgresql,redis"><img src="https://railway.app/button.svg" style="height: 44px" alt="Deploy on Railway"></a> | [docs](https://docs.authorizer.dev/deployment/railway) |
|
||||
| :----------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------: |
|
||||
| Railway.app | <a href="https://railway.app/new/template/nwXp1C?referralCode=FEF4uT"><img src="https://railway.app/button.svg" style="height: 44px" alt="Deploy on Railway"></a> | [docs](https://docs.authorizer.dev/deployment/railway) |
|
||||
| Heroku | <a href="https://heroku.com/deploy?template=https://github.com/authorizerdev/authorizer-heroku"><img src="https://www.herokucdn.com/deploy/button.svg" alt="Deploy to Heroku" style="height: 44px;"></a> | [docs](https://docs.authorizer.dev/deployment/heroku) |
|
||||
| Render | [](https://render.com/deploy?repo=https://github.com/authorizerdev/authorizer-render) | [docs](https://docs.authorizer.dev/deployment/render) |
|
||||
|
||||
|
@@ -4,6 +4,12 @@ import { AuthorizerProvider } from '@authorizerdev/authorizer-react';
|
||||
import Root from './Root';
|
||||
import { createRandomString } from './utils/common';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
__authorizer__: any;
|
||||
}
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
const state = searchParams.get('state') || createRandomString();
|
||||
@@ -24,7 +30,6 @@ export default function App() {
|
||||
urlProps.redirectURL = window.location.origin + '/app';
|
||||
}
|
||||
const globalState: Record<string, string> = {
|
||||
// @ts-ignore
|
||||
...window['__authorizer__'],
|
||||
...urlProps,
|
||||
};
|
||||
|
@@ -1,12 +1,21 @@
|
||||
import React from "react";
|
||||
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
||||
import React from 'react';
|
||||
import {
|
||||
Flex,
|
||||
Stack,
|
||||
Center,
|
||||
Text,
|
||||
useMediaQuery,
|
||||
Button,
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import {
|
||||
HiddenInputType,
|
||||
TextInputType,
|
||||
TextAreaInputType,
|
||||
} from "../../constants";
|
||||
import GenerateKeysModal from "../GenerateKeysModal";
|
||||
import InputField from "../InputField";
|
||||
} from '../../constants';
|
||||
import GenerateKeysModal from '../GenerateKeysModal';
|
||||
import InputField from '../InputField';
|
||||
import { copyTextToClipboard } from '../../utils';
|
||||
|
||||
const JSTConfigurations = ({
|
||||
variables,
|
||||
@@ -19,11 +28,40 @@ const JSTConfigurations = ({
|
||||
RSAEncryptionType,
|
||||
ECDSAEncryptionType,
|
||||
}: any) => {
|
||||
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||
const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
|
||||
const toast = useToast();
|
||||
|
||||
const copyJSON = async () => {
|
||||
try {
|
||||
await copyTextToClipboard(
|
||||
JSON.stringify({
|
||||
type: variables.JWT_TYPE,
|
||||
key: variables.JWT_PUBLIC_KEY || variables.JWT_SECRET,
|
||||
})
|
||||
);
|
||||
toast({
|
||||
title: `JWT config copied successfully`,
|
||||
isClosable: true,
|
||||
status: 'success',
|
||||
position: 'bottom-right',
|
||||
});
|
||||
} catch (err) {
|
||||
console.error({
|
||||
message: `Failed to copy JWT config`,
|
||||
error: err,
|
||||
});
|
||||
toast({
|
||||
title: `Failed to copy JWT config`,
|
||||
isClosable: true,
|
||||
status: 'error',
|
||||
position: 'bottom-right',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
{" "}
|
||||
{' '}
|
||||
<Flex
|
||||
borderRadius={5}
|
||||
width="100%"
|
||||
@@ -32,24 +70,33 @@ const JSTConfigurations = ({
|
||||
paddingTop="2%"
|
||||
>
|
||||
<Text
|
||||
fontSize={isNotSmallerScreen ? "md" : "sm"}
|
||||
fontSize={isNotSmallerScreen ? 'md' : 'sm'}
|
||||
fontWeight="bold"
|
||||
mb={5}
|
||||
>
|
||||
JWT (JSON Web Tokens) Configurations
|
||||
</Text>
|
||||
<Flex mb={7}>
|
||||
<Button
|
||||
colorScheme="blue"
|
||||
h="1.75rem"
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={copyJSON}
|
||||
>
|
||||
Copy As JSON Config
|
||||
</Button>
|
||||
<GenerateKeysModal jwtType={variables.JWT_TYPE} getData={getData} />
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Stack spacing={6} padding="2% 0%">
|
||||
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||
<Text fontSize="sm">JWT Type:</Text>
|
||||
</Flex>
|
||||
<Flex
|
||||
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||
mt={isNotSmallerScreen ? "0" : "2"}
|
||||
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||
mt={isNotSmallerScreen ? '0' : '2'}
|
||||
>
|
||||
<InputField
|
||||
borderRadius={5}
|
||||
@@ -66,13 +113,13 @@ const JSTConfigurations = ({
|
||||
</Flex>
|
||||
</Flex>
|
||||
{Object.values(HMACEncryptionType).includes(variables.JWT_TYPE) ? (
|
||||
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||
<Text fontSize="sm">JWT Secret</Text>
|
||||
</Flex>
|
||||
<Center
|
||||
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||
mt={isNotSmallerScreen ? "0" : "2"}
|
||||
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||
mt={isNotSmallerScreen ? '0' : '2'}
|
||||
>
|
||||
<InputField
|
||||
borderRadius={5}
|
||||
@@ -86,13 +133,13 @@ const JSTConfigurations = ({
|
||||
</Flex>
|
||||
) : (
|
||||
<>
|
||||
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||
<Text fontSize="sm">Public Key</Text>
|
||||
</Flex>
|
||||
<Center
|
||||
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||
mt={isNotSmallerScreen ? "0" : "2"}
|
||||
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||
mt={isNotSmallerScreen ? '0' : '2'}
|
||||
>
|
||||
<InputField
|
||||
borderRadius={5}
|
||||
@@ -104,13 +151,13 @@ const JSTConfigurations = ({
|
||||
/>
|
||||
</Center>
|
||||
</Flex>
|
||||
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||
<Text fontSize="sm">Private Key</Text>
|
||||
</Flex>
|
||||
<Center
|
||||
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||
mt={isNotSmallerScreen ? "0" : "2"}
|
||||
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||
mt={isNotSmallerScreen ? '0' : '2'}
|
||||
>
|
||||
<InputField
|
||||
borderRadius={5}
|
||||
@@ -124,9 +171,9 @@ const JSTConfigurations = ({
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||
<Flex
|
||||
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||
w={isNotSmallerScreen ? '30%' : '40%'}
|
||||
justifyContent="start"
|
||||
alignItems="center"
|
||||
>
|
||||
@@ -135,8 +182,8 @@ const JSTConfigurations = ({
|
||||
</Text>
|
||||
</Flex>
|
||||
<Center
|
||||
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||
mt={isNotSmallerScreen ? "0" : "2"}
|
||||
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||
mt={isNotSmallerScreen ? '0' : '2'}
|
||||
>
|
||||
<InputField
|
||||
borderRadius={5}
|
||||
|
@@ -29,6 +29,7 @@ import {
|
||||
MenuItem,
|
||||
useToast,
|
||||
Spinner,
|
||||
TableContainer
|
||||
} from '@chakra-ui/react';
|
||||
import {
|
||||
FaAngleLeft,
|
||||
@@ -262,8 +263,7 @@ export default function Users() {
|
||||
.toPromise();
|
||||
if (res.data?._update_user?.id) {
|
||||
toast({
|
||||
title: `Multi factor authentication ${
|
||||
user.is_multi_factor_auth_enabled ? 'disabled' : 'enabled'
|
||||
title: `Multi factor authentication ${user.is_multi_factor_auth_enabled ? 'disabled' : 'enabled'
|
||||
} for user`,
|
||||
isClosable: true,
|
||||
status: 'success',
|
||||
@@ -293,6 +293,7 @@ export default function Users() {
|
||||
</Flex>
|
||||
{!loading ? (
|
||||
userList.length > 0 ? (
|
||||
<TableContainer>
|
||||
<Table variant="simple">
|
||||
<Thead>
|
||||
<Tr>
|
||||
@@ -547,6 +548,7 @@ export default function Users() {
|
||||
</TableCaption>
|
||||
)}
|
||||
</Table>
|
||||
</TableContainer>
|
||||
) : (
|
||||
<Flex
|
||||
flexDirection="column"
|
||||
|
@@ -29,19 +29,16 @@ const fallbackCopyTextToClipboard = (text: string) => {
|
||||
document.body.removeChild(textArea);
|
||||
};
|
||||
|
||||
export const copyTextToClipboard = (text: string) => {
|
||||
export const copyTextToClipboard = async (text: string) => {
|
||||
if (!navigator.clipboard) {
|
||||
fallbackCopyTextToClipboard(text);
|
||||
return;
|
||||
}
|
||||
navigator.clipboard.writeText(text).then(
|
||||
() => {
|
||||
console.log('Async: Copying to clipboard was successful!');
|
||||
},
|
||||
(err) => {
|
||||
console.error('Async: Could not copy text: ', err);
|
||||
try {
|
||||
navigator.clipboard.writeText(text);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const getObjectDiff = (obj1: any, obj2: any) => {
|
||||
|
@@ -9,7 +9,7 @@ const (
|
||||
// Ref: https://docs.github.com/en/developers/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#3-your-github-app-accesses-the-api-with-the-users-access-token
|
||||
GithubUserInfoURL = "https://api.github.com/user"
|
||||
// Get github user emails when user info email is empty Ref: https://stackoverflow.com/a/35387123
|
||||
GithubUserEmails = "https://api/github.com/user/emails"
|
||||
GithubUserEmails = "https://api.github.com/user/emails"
|
||||
|
||||
// Ref: https://docs.microsoft.com/en-us/linkedin/shared/integrations/people/profile-api
|
||||
LinkedInUserInfoURL = "https://api.linkedin.com/v2/me?projection=(id,localizedFirstName,localizedLastName,emailAddress,profilePicture(displayImage~:playableStreams))"
|
||||
|
@@ -109,6 +109,7 @@ func main() {
|
||||
router := routes.InitRouter(log)
|
||||
log.Info("Starting Authorizer: ", VERSION)
|
||||
port, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyPort)
|
||||
log.Info("Authorizer running at PORT: ", port)
|
||||
if err != nil {
|
||||
log.Info("Error while getting port from env using default port 8080: ", err)
|
||||
port = "8080"
|
||||
|
@@ -50,7 +50,7 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
||||
user, err := db.Provider.GetUserByEmail(ctx, params.Email)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user by email: ", err)
|
||||
return res, fmt.Errorf(`user with this email not found`)
|
||||
return res, fmt.Errorf(`bad user credentials`)
|
||||
}
|
||||
|
||||
if user.RevokedTimestamp != nil {
|
||||
@@ -72,7 +72,7 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
||||
|
||||
if err != nil {
|
||||
log.Debug("Failed to compare password: ", err)
|
||||
return res, fmt.Errorf(`invalid password`)
|
||||
return res, fmt.Errorf(`bad user credentials`)
|
||||
}
|
||||
|
||||
defaultRolesString, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
||||
|
@@ -30,8 +30,8 @@ func IsValidOrigin(url string) bool {
|
||||
replacedString := origin
|
||||
// if has regex whitelisted domains
|
||||
if strings.Contains(origin, "*") {
|
||||
replacedString = strings.Replace(origin, ".", "\\.", -1)
|
||||
replacedString = strings.Replace(replacedString, "*", ".*", -1)
|
||||
replacedString = strings.ReplaceAll(origin, ".", "\\.")
|
||||
replacedString = strings.ReplaceAll(replacedString, "*", ".*")
|
||||
|
||||
if strings.HasPrefix(replacedString, ".*") {
|
||||
replacedString += "\\b"
|
||||
|
Reference in New Issue
Block a user