Skip to content

Commit a203b85

Browse files
Merge branch 'authorizerdev:main' into main
2 parents fbb4975 + 109b38e commit a203b85

File tree

28 files changed

+721
-146
lines changed

28 files changed

+721
-146
lines changed

app/package-lock.json

Lines changed: 20 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"author": "Lakhan Samani",
1313
"license": "ISC",
1414
"dependencies": {
15-
"@authorizerdev/authorizer-react": "^1.1.13",
15+
"@authorizerdev/authorizer-react": "^1.1.18",
1616
"@types/react": "^17.0.15",
1717
"@types/react-dom": "^17.0.9",
1818
"esbuild": "^0.12.17",

app/src/pages/login.tsx

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,29 +32,34 @@ const FooterContent = styled.div`
3232
export default function Login({ urlProps }: { urlProps: Record<string, any> }) {
3333
const { config } = useAuthorizer();
3434
const [view, setView] = useState<VIEW_TYPES>(VIEW_TYPES.LOGIN);
35+
const isBasicAuth = config.is_basic_authentication_enabled;
3536
return (
3637
<Fragment>
3738
{view === VIEW_TYPES.LOGIN && (
3839
<Fragment>
3940
<h1 style={{ textAlign: 'center' }}>Login</h1>
40-
<br />
4141
<AuthorizerSocialLogin urlProps={urlProps} />
42-
{config.is_basic_authentication_enabled &&
42+
<br />
43+
{(config.is_basic_authentication_enabled ||
44+
config.is_mobile_basic_authentication_enabled) &&
4345
!config.is_magic_link_login_enabled && (
4446
<AuthorizerBasicAuthLogin urlProps={urlProps} />
4547
)}
4648
{config.is_magic_link_login_enabled && (
4749
<AuthorizerMagicLinkLogin urlProps={urlProps} />
4850
)}
49-
<Footer>
50-
<Link
51-
to="#"
52-
onClick={() => setView(VIEW_TYPES.FORGOT_PASSWORD)}
53-
style={{ marginBottom: 10 }}
54-
>
55-
Forgot Password?
56-
</Link>
57-
</Footer>
51+
{(config.is_basic_authentication_enabled ||
52+
config.is_mobile_basic_authentication_enabled) && (
53+
<Footer>
54+
<Link
55+
to="#"
56+
onClick={() => setView(VIEW_TYPES.FORGOT_PASSWORD)}
57+
style={{ marginBottom: 10 }}
58+
>
59+
Forgot Password?
60+
</Link>
61+
</Footer>
62+
)}
5863
</Fragment>
5964
)}
6065
{view === VIEW_TYPES.FORGOT_PASSWORD && (
@@ -81,7 +86,7 @@ export default function Login({ urlProps }: { urlProps: Record<string, any> }) {
8186
!config.is_magic_link_login_enabled &&
8287
config.is_sign_up_enabled && (
8388
<FooterContent>
84-
Don't have an account? <Link to="/app/signup"> Sign Up</Link>
89+
Don't have an account? &nbsp; <Link to="/app/signup"> Sign Up</Link>
8590
</FooterContent>
8691
)}
8792
</Fragment>

app/yarn.lock

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@
22
# yarn lockfile v1
33

44

5-
"@authorizerdev/authorizer-js@^1.2.6":
6-
version "1.2.6"
7-
resolved "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-1.2.6.tgz"
8-
integrity sha512-9+9phHUMF+AeDM0y+XQvIRDoerOXnQ1vfTfYN6KxWN1apdrkAd9nzS1zUsA2uJSnX3fFZOErn83GjbYYCYF1BA==
5+
"@authorizerdev/authorizer-js@^1.2.18":
6+
version "1.2.18"
7+
resolved "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-1.2.18.tgz"
8+
integrity sha512-9j5U/4lqaaEcG78Zli+TtLJ0migSKhFwnXXunulAGTZOzQSTCJ/CSSPip5wWNa/Mkr6gdEMwk1HYfhIdk2A9Mg==
99
dependencies:
1010
cross-fetch "^3.1.5"
1111

12-
"@authorizerdev/authorizer-react@^1.1.13":
13-
version "1.1.13"
14-
resolved "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-1.1.13.tgz"
15-
integrity sha512-LmpzyfR0+nEn+bjUrb/QU9b3kiVoYzMBIvcQ1nV4TNvrvVSqbLPKk+GmoIPkiBEtfy/QSM6XFLkiGNGD9BRP+g==
12+
"@authorizerdev/authorizer-react@^1.1.18":
13+
version "1.1.18"
14+
resolved "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-1.1.18.tgz"
15+
integrity sha512-5SgFzG1VatmrMpl9XKwPcoVmCayA4Hn+sd2I9CwRlCWkdcna4pGJL8kYesuIGjGagS9394qp4ICRLRZ35wXj8A==
1616
dependencies:
17-
"@authorizerdev/authorizer-js" "^1.2.6"
17+
"@authorizerdev/authorizer-js" "^1.2.18"
18+
validator "^13.11.0"
1819

1920
"@babel/code-frame@^7.22.13":
2021
version "7.22.13"
@@ -420,9 +421,9 @@ [email protected]:
420421
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
421422

422423
node-fetch@^2.6.12:
423-
version "2.6.12"
424-
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz"
425-
integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==
424+
version "2.7.0"
425+
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz"
426+
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
426427
dependencies:
427428
whatwg-url "^5.0.0"
428429

@@ -594,6 +595,11 @@ typescript@^4.3.5:
594595
resolved "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz"
595596
integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==
596597

598+
validator@^13.11.0:
599+
version "13.11.0"
600+
resolved "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz"
601+
integrity sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==
602+
597603
value-equal@^1.0.1:
598604
version "1.0.1"
599605
resolved "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz"

dashboard/src/components/EnvComponents/OAuthConfig.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
FaApple,
1818
FaTwitter,
1919
FaMicrosoft,
20+
FaTwitch,
2021
} from 'react-icons/fa';
2122
import {
2223
TextInputType,
@@ -397,6 +398,44 @@ const OAuthConfig = ({
397398
/>
398399
</Center>
399400
</Flex>
401+
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
402+
<Center
403+
w={isNotSmallerScreen ? '55px' : '35px'}
404+
h="35px"
405+
marginRight="1.5%"
406+
border="1px solid #3b5998"
407+
borderRadius="5px"
408+
>
409+
<FaTwitch />
410+
</Center>
411+
<Center
412+
w={isNotSmallerScreen ? '70%' : '100%'}
413+
mt={isNotSmallerScreen ? '0' : '3'}
414+
marginRight="1.5%"
415+
>
416+
<InputField
417+
borderRadius={5}
418+
variables={envVariables}
419+
setVariables={setVariables}
420+
inputType={TextInputType.TWITCH_CLIENT_ID}
421+
placeholder="Twitch Client ID"
422+
/>
423+
</Center>
424+
<Center
425+
w={isNotSmallerScreen ? '70%' : '100%'}
426+
mt={isNotSmallerScreen ? '0' : '3'}
427+
>
428+
<InputField
429+
borderRadius={5}
430+
variables={envVariables}
431+
setVariables={setVariables}
432+
fieldVisibility={fieldVisibility}
433+
setFieldVisibility={setFieldVisibility}
434+
inputType={HiddenInputType.TWITCH_CLIENT_SECRET}
435+
placeholder="Twitch Client Secret"
436+
/>
437+
</Center>
438+
</Flex>
400439
</Stack>
401440
</Box>
402441
</div>

dashboard/src/constants.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const TextInputType = {
1212
TWITTER_CLIENT_ID: 'TWITTER_CLIENT_ID',
1313
MICROSOFT_CLIENT_ID: 'MICROSOFT_CLIENT_ID',
1414
MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID: 'MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID',
15+
TWITCH_CLIENT_ID: 'TWITCH_CLIENT_ID',
1516
JWT_ROLE_CLAIM: 'JWT_ROLE_CLAIM',
1617
REDIS_URL: 'REDIS_URL',
1718
SMTP_HOST: 'SMTP_HOST',
@@ -42,6 +43,7 @@ export const HiddenInputType = {
4243
APPLE_CLIENT_SECRET: 'APPLE_CLIENT_SECRET',
4344
TWITTER_CLIENT_SECRET: 'TWITTER_CLIENT_SECRET',
4445
MICROSOFT_CLIENT_SECRET: 'MICROSOFT_CLIENT_SECRET',
46+
TWITCH_CLIENT_SECRET: 'TWITCH_CLIENT_SECRET',
4547
JWT_SECRET: 'JWT_SECRET',
4648
SMTP_PASSWORD: 'SMTP_PASSWORD',
4749
ADMIN_SECRET: 'ADMIN_SECRET',
@@ -132,6 +134,8 @@ export interface envVarTypes {
132134
MICROSOFT_CLIENT_ID: string;
133135
MICROSOFT_CLIENT_SECRET: string;
134136
MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID: string;
137+
TWITCH_CLIENT_ID: string;
138+
TWITCH_CLIENT_SECRET: string;
135139
ROLES: [string] | [];
136140
DEFAULT_ROLES: [string] | [];
137141
PROTECTED_ROLES: [string] | [];

dashboard/src/graphql/queries/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ export const EnvVariablesQuery = `
3535
MICROSOFT_CLIENT_ID
3636
MICROSOFT_CLIENT_SECRET
3737
MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID
38+
TWITCH_CLIENT_ID
39+
TWITCH_CLIENT_SECRET
3840
DEFAULT_ROLES
3941
PROTECTED_ROLES
4042
ROLES

dashboard/src/pages/Environment.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ const Environment = () => {
5555
MICROSOFT_CLIENT_ID: '',
5656
MICROSOFT_CLIENT_SECRET: '',
5757
MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID: '',
58+
TWITCH_CLIENT_ID: '',
59+
TWITCH_CLIENT_SECRET: '',
5860
ROLES: [],
5961
DEFAULT_ROLES: [],
6062
PROTECTED_ROLES: [],
@@ -107,6 +109,7 @@ const Environment = () => {
107109
LINKEDIN_CLIENT_SECRET: false,
108110
APPLE_CLIENT_SECRET: false,
109111
TWITTER_CLIENT_SECRET: false,
112+
TWITCH_CLIENT_SECRET: false,
110113
JWT_SECRET: false,
111114
SMTP_PASSWORD: false,
112115
ADMIN_SECRET: false,

server/authenticators/providers/providers.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type Provider interface {
1919
// Generate totp: to generate totp, store secret into db and returns base64 of QR code image
2020
Generate(ctx context.Context, id string) (*AuthenticatorConfig, error)
2121
// Validate totp: user passcode with secret stored in our db
22-
Validate(ctx context.Context, passcode string, id string) (bool, error)
23-
// RecoveryCode totp: gives a recovery code for first time user
24-
RecoveryCode(ctx context.Context, id string) (*string, error)
22+
Validate(ctx context.Context, passcode string, userID string) (bool, error)
23+
// ValidateRecoveryCode totp: allows user to validate using recovery code incase if they lost their device
24+
ValidateRecoveryCode(ctx context.Context, recoveryCode, userID string) (bool, error)
2525
}

server/authenticators/providers/totp/totp.go

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"context"
66
"encoding/json"
7+
"fmt"
78
"image/png"
89
"time"
910

@@ -113,24 +114,38 @@ func (p *provider) Validate(ctx context.Context, passcode string, userID string)
113114
return status, nil
114115
}
115116

116-
// RecoveryCode generates a recovery code for a user's TOTP authentication, if not already verified.
117-
func (p *provider) RecoveryCode(ctx context.Context, id string) (*string, error) {
117+
// ValidateRecoveryCode validates a Time-Based One-Time Password (TOTP) recovery code against the stored TOTP recovery code for a user.
118+
func (p *provider) ValidateRecoveryCode(ctx context.Context, recoveryCode, userID string) (bool, error) {
118119
// get totp details
119-
// totpModel, err := db.Provider.GetAuthenticatorDetailsByUserId(ctx, id, constants.EnvKeyTOTPAuthenticator)
120-
// if err != nil {
121-
// return nil, fmt.Errorf("error while getting totp details from authenticators")
122-
// }
123-
// //TODO *totpModel.RecoveryCode == "null" used to just verify couchbase recoveryCode value to be nil
124-
// // have to find another way round
125-
// if totpModel.RecoveryCode == nil || *totpModel.RecoveryCode == "null" {
126-
// recoveryCode := utils.GenerateTOTPRecoveryCode()
127-
// totpModel.RecoveryCode = &recoveryCode
128-
129-
// _, err = db.Provider.UpdateAuthenticator(ctx, totpModel)
130-
// if err != nil {
131-
// return nil, fmt.Errorf("error while updaing authenticator table for totp")
132-
// }
133-
// return &recoveryCode, nil
134-
// }
135-
return nil, nil
120+
totpModel, err := db.Provider.GetAuthenticatorDetailsByUserId(ctx, userID, constants.EnvKeyTOTPAuthenticator)
121+
if err != nil {
122+
return false, err
123+
}
124+
// convert recoveryCodes to map
125+
recoveryCodesMap := map[string]bool{}
126+
err = json.Unmarshal([]byte(refs.StringValue(totpModel.RecoveryCodes)), &recoveryCodesMap)
127+
if err != nil {
128+
return false, err
129+
}
130+
// check if recovery code is valid
131+
if val, ok := recoveryCodesMap[recoveryCode]; !ok {
132+
return false, fmt.Errorf("invalid recovery code")
133+
} else if val {
134+
return false, fmt.Errorf("recovery code already used")
135+
}
136+
// update recovery code map
137+
recoveryCodesMap[recoveryCode] = true
138+
// convert recoveryCodesMap to string
139+
jsonData, err := json.Marshal(recoveryCodesMap)
140+
if err != nil {
141+
return false, err
142+
}
143+
recoveryCodesString := string(jsonData)
144+
totpModel.RecoveryCodes = refs.NewStringRef(recoveryCodesString)
145+
// update recovery code map in db
146+
_, err = db.Provider.UpdateAuthenticator(ctx, totpModel)
147+
if err != nil {
148+
return false, err
149+
}
150+
return true, nil
136151
}

0 commit comments

Comments
 (0)