Skip to content

Commit bbb61f5

Browse files
marckongjackkav
andcommitted
[INS-1805] Add Auth Header Tab (#5115)
* add minimal change to the auth flow * add disable state * adding dropdown disable * simplify reducer * fix lint Co-authored-by: jackkav <[email protected]>
1 parent 06ef212 commit bbb61f5

18 files changed

+217
-81
lines changed

packages/insomnia/src/common/constants.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,20 @@ export const isDevelopment = () => getAppEnvironment() === 'development';
2525
export const getSegmentWriteKey = () => appConfig.segmentWriteKeys[(isDevelopment() || env.PLAYWRIGHT) ? 'development' : 'production'];
2626
export const getSentryDsn = () => appConfig.sentryDsn;
2727
export const getAppBuildDate = () => new Date(process.env.BUILD_DATE ?? '').toLocaleDateString();
28-
28+
export type AuthType =
29+
| 'none'
30+
| 'oauth2'
31+
| 'oauth1'
32+
| 'basic'
33+
| 'digest'
34+
| 'bearer'
35+
| 'ntlm'
36+
| 'hawk'
37+
| 'iam'
38+
| 'netrc'
39+
| 'asap'
40+
| 'sha256'
41+
| 'sha1';
2942
export const getBrowserUserAgent = () => encodeURIComponent(
3043
String(window.navigator.userAgent)
3144
.replace(new RegExp(`${getAppId()}\\/\\d+\\.\\d+\\.\\d+ `), '')

packages/insomnia/src/models/websocket-request.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { database } from '../common/database';
22
import type { BaseModel } from '.';
3-
import { RequestHeader } from './request';
3+
import { RequestAuthentication, RequestHeader } from './request';
44

55
export const name = 'WebSocket Request';
66

@@ -18,6 +18,7 @@ export interface BaseWebSocketRequest {
1818
url: string;
1919
metaSortKey: number;
2020
headers: RequestHeader[];
21+
authentication: RequestAuthentication;
2122
}
2223

2324
export type WebSocketRequest = BaseModel & BaseWebSocketRequest & { type: typeof type };
@@ -35,6 +36,7 @@ export const init = (): BaseWebSocketRequest => ({
3536
url: '',
3637
metaSortKey: -1 * Date.now(),
3738
headers: [],
39+
authentication: {},
3840
});
3941

4042
export const migrate = (doc: WebSocketRequest) => doc;

packages/insomnia/src/ui/components/dropdowns/auth-dropdown.tsx

+136-45
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,14 @@ import React, { FC, useCallback } from 'react';
22
import { useSelector } from 'react-redux';
33

44
import {
5-
AUTH_ASAP,
6-
AUTH_AWS_IAM,
7-
AUTH_BASIC,
8-
AUTH_BEARER,
9-
AUTH_DIGEST,
10-
AUTH_HAWK,
11-
AUTH_NETRC,
12-
AUTH_NONE,
13-
AUTH_NTLM,
14-
AUTH_OAUTH_1,
15-
AUTH_OAUTH_2,
5+
AuthType,
166
getAuthTypeName,
7+
HAWK_ALGORITHM_SHA256,
178
} from '../../../common/constants';
18-
import * as models from '../../../models';
199
import { update } from '../../../models/helpers/request-operations';
20-
import { isRequest } from '../../../models/request';
10+
import { RequestAuthentication } from '../../../models/request';
11+
import { SIGNATURE_METHOD_HMAC_SHA1 } from '../../../network/o-auth-1/constants';
12+
import { GRANT_TYPE_AUTHORIZATION_CODE } from '../../../network/o-auth-2/constants';
2113
import { selectActiveRequest } from '../../redux/selectors';
2214
import { Dropdown } from '../base/dropdown/dropdown';
2315
import { DropdownButton } from '../base/dropdown/dropdown-button';
@@ -26,11 +18,110 @@ import { DropdownItem } from '../base/dropdown/dropdown-item';
2618
import { showModal } from '../modals';
2719
import { AlertModal } from '../modals/alert-modal';
2820

21+
const defaultTypes: AuthType[] = [
22+
'basic',
23+
'digest',
24+
'oauth1',
25+
'oauth2',
26+
'ntlm',
27+
'iam',
28+
'bearer',
29+
'hawk',
30+
'asap',
31+
'netrc',
32+
];
33+
34+
function makeNewAuth(type: string, oldAuth: RequestAuthentication = {}): RequestAuthentication {
35+
switch (type) {
36+
// No Auth
37+
case 'none':
38+
return {};
39+
40+
// HTTP Basic Authentication
41+
case 'basic':
42+
return {
43+
type,
44+
useISO88591: oldAuth.useISO88591 || false,
45+
disabled: oldAuth.disabled || false,
46+
username: oldAuth.username || '',
47+
password: oldAuth.password || '',
48+
};
49+
50+
case 'digest':
51+
case 'ntlm':
52+
return {
53+
type,
54+
disabled: oldAuth.disabled || false,
55+
username: oldAuth.username || '',
56+
password: oldAuth.password || '',
57+
};
58+
59+
case 'oauth1':
60+
return {
61+
type,
62+
disabled: false,
63+
signatureMethod: SIGNATURE_METHOD_HMAC_SHA1,
64+
consumerKey: '',
65+
consumerSecret: '',
66+
tokenKey: '',
67+
tokenSecret: '',
68+
privateKey: '',
69+
version: '1.0',
70+
nonce: '',
71+
timestamp: '',
72+
callback: '',
73+
};
74+
75+
// OAuth 2.0
76+
case 'oauth2':
77+
return {
78+
type,
79+
grantType: GRANT_TYPE_AUTHORIZATION_CODE,
80+
};
81+
82+
// Aws IAM
83+
case 'iam':
84+
return {
85+
type,
86+
disabled: oldAuth.disabled || false,
87+
accessKeyId: oldAuth.accessKeyId || '',
88+
secretAccessKey: oldAuth.secretAccessKey || '',
89+
sessionToken: oldAuth.sessionToken || '',
90+
};
91+
92+
// Hawk
93+
case 'hawk':
94+
return {
95+
type,
96+
algorithm: HAWK_ALGORITHM_SHA256,
97+
};
98+
99+
// Atlassian ASAP
100+
case 'asap':
101+
return {
102+
type,
103+
issuer: '',
104+
subject: '',
105+
audience: '',
106+
additionalClaims: '',
107+
keyId: '',
108+
privateKey: '',
109+
};
110+
111+
// Types needing no defaults
112+
case 'netrc':
113+
default:
114+
return {
115+
type,
116+
};
117+
}
118+
}
119+
29120
const AuthItem: FC<{
30-
type: string;
121+
type: AuthType;
31122
nameOverride?: string;
32-
isCurrent: (type: string) => boolean;
33-
onClick: (type: string) => void;
123+
isCurrent: (type: AuthType) => boolean;
124+
onClick: (type: AuthType) => void;
34125
}> = ({ type, nameOverride, isCurrent, onClick }) => (
35126
<DropdownItem onClick={onClick} value={type}>
36127
{<i className={`fa fa-${isCurrent(type) ? 'check' : 'empty'}`} />}{' '}
@@ -39,15 +130,15 @@ const AuthItem: FC<{
39130
);
40131
AuthItem.displayName = DropdownItem.name;
41132

42-
export const AuthDropdown: FC = () => {
133+
interface Props {
134+
authTypes?: AuthType[];
135+
disabled?: boolean;
136+
}
137+
export const AuthDropdown: FC<Props> = ({ authTypes = defaultTypes, disabled = false }) => {
43138
const activeRequest = useSelector(selectActiveRequest);
44139

45-
const onClick = useCallback(async (type: string) => {
46-
if (!activeRequest) {
47-
return;
48-
}
49-
50-
if (!isRequest(activeRequest)) {
140+
const onClick = useCallback(async (type: AuthType) => {
141+
if (!activeRequest || !('authentication' in activeRequest)) {
51142
return;
52143
}
53144

@@ -58,8 +149,8 @@ export const AuthDropdown: FC = () => {
58149
return;
59150
}
60151

61-
const newAuthentication = models.request.newAuth(type, authentication);
62-
const defaultAuthentication = models.request.newAuth(authentication.type);
152+
const newAuthentication = makeNewAuth(type, authentication);
153+
const defaultAuthentication = makeNewAuth(authentication.type);
63154

64155
// Prompt the user if fields will change between new and old
65156
for (const key of Object.keys(authentication)) {
@@ -80,16 +171,13 @@ export const AuthDropdown: FC = () => {
80171
break;
81172
}
82173
}
83-
update(activeRequest, { authentication:newAuthentication });
174+
update(activeRequest, { authentication: newAuthentication });
84175
}, [activeRequest]);
85-
const isCurrent = useCallback((type: string) => {
86-
if (!activeRequest) {
87-
return false;
88-
}
89-
if (!isRequest(activeRequest)) {
176+
const isCurrent = useCallback((type: AuthType) => {
177+
if (!activeRequest || !('authentication' in activeRequest)) {
90178
return false;
91179
}
92-
return type === (activeRequest.authentication.type || AUTH_NONE);
180+
return type === (activeRequest.authentication.type || 'none');
93181
}, [activeRequest]);
94182

95183
if (!activeRequest) {
@@ -101,22 +189,25 @@ export const AuthDropdown: FC = () => {
101189
return (
102190
<Dropdown beside>
103191
<DropdownDivider>Auth Types</DropdownDivider>
104-
<DropdownButton className="tall">
192+
<DropdownButton className="tall" disabled={disabled}>
105193
{'authentication' in activeRequest ? getAuthTypeName(activeRequest.authentication.type) || 'Auth' : 'Auth'}
106194
<i className="fa fa-caret-down space-left" />
107195
</DropdownButton>
108-
<AuthItem type={AUTH_BASIC} {...itemProps} />
109-
<AuthItem type={AUTH_DIGEST} {...itemProps} />
110-
<AuthItem type={AUTH_OAUTH_1} {...itemProps} />
111-
<AuthItem type={AUTH_OAUTH_2} {...itemProps} />
112-
<AuthItem type={AUTH_NTLM} {...itemProps} />
113-
<AuthItem type={AUTH_AWS_IAM} {...itemProps} />
114-
<AuthItem type={AUTH_BEARER} {...itemProps} />
115-
<AuthItem type={AUTH_HAWK} {...itemProps} />
116-
<AuthItem type={AUTH_ASAP} {...itemProps} />
117-
<AuthItem type={AUTH_NETRC} {...itemProps} />
118-
<DropdownDivider>Other</DropdownDivider>
119-
<AuthItem type={AUTH_NONE} nameOverride="No Authentication" {...itemProps} />
196+
{authTypes.map(authType =>
197+
<AuthItem
198+
key={authType}
199+
type={authType}
200+
{...itemProps}
201+
/>)}
202+
<DropdownDivider key="divider-other">
203+
Other
204+
</DropdownDivider>
205+
<AuthItem
206+
key="none"
207+
type="none"
208+
nameOverride="No Authentication"
209+
{...itemProps}
210+
/>
120211
</Dropdown>
121212
);
122213
};

packages/insomnia/src/ui/components/editors/auth/asap-auth.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import React, { FC } from 'react';
33
import { AuthInputRow } from './components/auth-input-row';
44
import { AuthPrivateKeyRow } from './components/auth-private-key-row';
55
import { AuthTableBody } from './components/auth-table-body';
6+
import { AuthToggleRow } from './components/auth-toggle-row';
67

78
export const AsapAuth: FC = () => (
89
<AuthTableBody>
10+
<AuthToggleRow label="Enabled" property="disabled" invert />
911
<AuthInputRow label='Issuer (iss)' property='issuer' />
1012
<AuthInputRow label='Subject (sub)' property='subject' />
1113
<AuthInputRow label='Audience (aud)' property='audience' />

packages/insomnia/src/ui/components/editors/auth/auth-wrapper.tsx

+5-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
AUTH_OAUTH_1,
1414
AUTH_OAUTH_2,
1515
} from '../../../../common/constants';
16-
import { isRequest } from '../../../../models/request';
1716
import { selectActiveRequest } from '../../../redux/selectors';
1817
import { AsapAuth } from './asap-auth';
1918
import { AWSAuth } from './aws-auth';
@@ -26,10 +25,10 @@ import { NTLMAuth } from './ntlm-auth';
2625
import { OAuth1Auth } from './o-auth-1-auth';
2726
import { OAuth2Auth } from './o-auth-2-auth';
2827

29-
export const AuthWrapper: FC = () => {
28+
export const AuthWrapper: FC<{ disabled?: boolean }> = ({ disabled = false }) => {
3029
const request = useSelector(selectActiveRequest);
3130

32-
if (!request || !isRequest(request)) {
31+
if (!request || !('authentication' in request)) {
3332
return null;
3433
}
3534

@@ -38,19 +37,19 @@ export const AuthWrapper: FC = () => {
3837
let authBody: ReactNode = null;
3938

4039
if (type === AUTH_BASIC) {
41-
authBody = <BasicAuth />;
40+
authBody = <BasicAuth disabled={disabled} />;
4241
} else if (type === AUTH_OAUTH_2) {
4342
authBody = <OAuth2Auth />;
4443
} else if (type === AUTH_HAWK) {
4544
authBody = <HawkAuth />;
4645
} else if (type === AUTH_OAUTH_1) {
4746
authBody = <OAuth1Auth />;
4847
} else if (type === AUTH_DIGEST) {
49-
authBody = <DigestAuth />;
48+
authBody = <DigestAuth disabled={disabled} />;
5049
} else if (type === AUTH_NTLM) {
5150
authBody = <NTLMAuth />;
5251
} else if (type === AUTH_BEARER) {
53-
authBody = <BearerAuth />;
52+
authBody = <BearerAuth disabled={disabled} />;
5453
} else if (type === AUTH_AWS_IAM) {
5554
authBody = <AWSAuth />;
5655
} else if (type === AUTH_NETRC) {

packages/insomnia/src/ui/components/editors/auth/aws-auth.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ import React, { FC } from 'react';
22

33
import { AuthInputRow } from './components/auth-input-row';
44
import { AuthTableBody } from './components/auth-table-body';
5+
import { AuthToggleRow } from './components/auth-toggle-row';
56

67
export const AWSAuth: FC = () => (
78
<AuthTableBody>
9+
<AuthToggleRow label="Enabled" property="disabled" invert />
810
<AuthInputRow
911
label="Access Key ID"
1012
property="accessKeyId"

packages/insomnia/src/ui/components/editors/auth/basic-auth.tsx

+5-3
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@ import { AuthInputRow } from './components/auth-input-row';
44
import { AuthTableBody } from './components/auth-table-body';
55
import { AuthToggleRow } from './components/auth-toggle-row';
66

7-
export const BasicAuth: FC = () => (
7+
export const BasicAuth: FC<{ disabled?: boolean }> = ({ disabled = false }) => (
88
<AuthTableBody>
9-
<AuthInputRow label="Username" property="username" />
10-
<AuthInputRow label="Password" property="password" mask />
9+
<AuthToggleRow label="Enabled" property="disabled" invert disabled={disabled} />
10+
<AuthInputRow label="Username" property="username" disabled={disabled} />
11+
<AuthInputRow label="Password" property="password" mask disabled={disabled} />
1112
<AuthToggleRow
1213
label="Use ISO 8859-1"
1314
help="Check this to use ISO-8859-1 encoding instead of default UTF-8"
1415
property='useISO88591'
16+
disabled={disabled}
1517
/>
1618
</AuthTableBody>
1719
);

packages/insomnia/src/ui/components/editors/auth/bearer-auth.tsx

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import React, { FC } from 'react';
22

33
import { AuthInputRow } from './components/auth-input-row';
44
import { AuthTableBody } from './components/auth-table-body';
5+
import { AuthToggleRow } from './components/auth-toggle-row';
56

6-
export const BearerAuth: FC = () => (
7+
export const BearerAuth: FC<{ disabled?: boolean }> = ({ disabled = false }) => (
78
<AuthTableBody>
8-
<AuthInputRow label='Token' property='token' />
9-
<AuthInputRow label='Prefix' property='prefix' />
9+
<AuthToggleRow label="Enabled" property="disabled" invert disabled={disabled} />
10+
<AuthInputRow label='Token' property='token' disabled={disabled} />
11+
<AuthInputRow label='Prefix' property='prefix' disabled={disabled} />
1012
</AuthTableBody>
1113
);

0 commit comments

Comments
 (0)