diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/AuthMode/index.js b/packages/bruno-app/src/components/CollectionSettings/Auth/AuthMode/index.js
index 5cf3a5f7a..747ee4d61 100644
--- a/packages/bruno-app/src/components/CollectionSettings/Auth/AuthMode/index.js
+++ b/packages/bruno-app/src/components/CollectionSettings/Auth/AuthMode/index.js
@@ -61,6 +61,15 @@ const AuthMode = ({ collection }) => {
>
Bearer Token
+
{
+ dropdownTippyRef.current.hide();
+ onModeChange('digest');
+ }}
+ >
+ Digest Auth
+
{
diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/DigestAuth/StyledWrapper.js b/packages/bruno-app/src/components/CollectionSettings/Auth/DigestAuth/StyledWrapper.js
new file mode 100644
index 000000000..c2bb5d207
--- /dev/null
+++ b/packages/bruno-app/src/components/CollectionSettings/Auth/DigestAuth/StyledWrapper.js
@@ -0,0 +1,16 @@
+import styled from 'styled-components';
+
+const Wrapper = styled.div`
+ label {
+ font-size: 0.8125rem;
+ }
+
+ .single-line-editor-wrapper {
+ padding: 0.15rem 0.4rem;
+ border-radius: 3px;
+ border: solid 1px ${(props) => props.theme.input.border};
+ background-color: ${(props) => props.theme.input.bg};
+ }
+`;
+
+export default Wrapper;
diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/DigestAuth/index.js b/packages/bruno-app/src/components/CollectionSettings/Auth/DigestAuth/index.js
new file mode 100644
index 000000000..3e084c06d
--- /dev/null
+++ b/packages/bruno-app/src/components/CollectionSettings/Auth/DigestAuth/index.js
@@ -0,0 +1,71 @@
+import React from 'react';
+import get from 'lodash/get';
+import { useTheme } from 'providers/Theme';
+import { useDispatch } from 'react-redux';
+import SingleLineEditor from 'components/SingleLineEditor';
+import { updateCollectionAuth } from 'providers/ReduxStore/slices/collections';
+import { saveCollectionRoot } from 'providers/ReduxStore/slices/collections/actions';
+import StyledWrapper from './StyledWrapper';
+
+const DigestAuth = ({ collection }) => {
+ const dispatch = useDispatch();
+ const { storedTheme } = useTheme();
+
+ const digestAuth = get(collection, 'root.request.auth.digest', {});
+
+ const handleSave = () => dispatch(saveCollectionRoot(collection.uid));
+
+ const handleUsernameChange = (username) => {
+ dispatch(
+ updateCollectionAuth({
+ mode: 'digest',
+ collectionUid: collection.uid,
+ content: {
+ username: username,
+ password: digestAuth.password
+ }
+ })
+ );
+ };
+
+ const handlePasswordChange = (password) => {
+ dispatch(
+ updateCollectionAuth({
+ mode: 'digest',
+ collectionUid: collection.uid,
+ content: {
+ username: digestAuth.username,
+ password: password
+ }
+ })
+ );
+ };
+
+ return (
+
+
+
+ handleUsernameChange(val)}
+ collection={collection}
+ />
+
+
+
+
+ handlePasswordChange(val)}
+ collection={collection}
+ />
+
+
+ );
+};
+
+export default DigestAuth;
diff --git a/packages/bruno-app/src/components/CollectionSettings/Auth/index.js b/packages/bruno-app/src/components/CollectionSettings/Auth/index.js
index d9e80358b..7873cfcd0 100644
--- a/packages/bruno-app/src/components/CollectionSettings/Auth/index.js
+++ b/packages/bruno-app/src/components/CollectionSettings/Auth/index.js
@@ -5,6 +5,7 @@ import AuthMode from './AuthMode';
import AwsV4Auth from './AwsV4Auth';
import BearerAuth from './BearerAuth';
import BasicAuth from './BasicAuth';
+import DigestAuth from './DigestAuth';
import { saveCollectionRoot } from 'providers/ReduxStore/slices/collections/actions';
import StyledWrapper from './StyledWrapper';
@@ -25,6 +26,9 @@ const Auth = ({ collection }) => {
case 'bearer': {
return
;
}
+ case 'digest': {
+ return
;
+ }
}
};
diff --git a/packages/bruno-app/src/components/RequestPane/Auth/AuthMode/index.js b/packages/bruno-app/src/components/RequestPane/Auth/AuthMode/index.js
index 10130c3a9..8eb4fee90 100644
--- a/packages/bruno-app/src/components/RequestPane/Auth/AuthMode/index.js
+++ b/packages/bruno-app/src/components/RequestPane/Auth/AuthMode/index.js
@@ -62,6 +62,15 @@ const AuthMode = ({ item, collection }) => {
>
Bearer Token
+ {
+ dropdownTippyRef.current.hide();
+ onModeChange('digest');
+ }}
+ >
+ Digest Auth
+
{
diff --git a/packages/bruno-app/src/components/RequestPane/Auth/DigestAuth/StyledWrapper.js b/packages/bruno-app/src/components/RequestPane/Auth/DigestAuth/StyledWrapper.js
new file mode 100644
index 000000000..c2bb5d207
--- /dev/null
+++ b/packages/bruno-app/src/components/RequestPane/Auth/DigestAuth/StyledWrapper.js
@@ -0,0 +1,16 @@
+import styled from 'styled-components';
+
+const Wrapper = styled.div`
+ label {
+ font-size: 0.8125rem;
+ }
+
+ .single-line-editor-wrapper {
+ padding: 0.15rem 0.4rem;
+ border-radius: 3px;
+ border: solid 1px ${(props) => props.theme.input.border};
+ background-color: ${(props) => props.theme.input.bg};
+ }
+`;
+
+export default Wrapper;
diff --git a/packages/bruno-app/src/components/RequestPane/Auth/DigestAuth/index.js b/packages/bruno-app/src/components/RequestPane/Auth/DigestAuth/index.js
new file mode 100644
index 000000000..e43f18c46
--- /dev/null
+++ b/packages/bruno-app/src/components/RequestPane/Auth/DigestAuth/index.js
@@ -0,0 +1,76 @@
+import React from 'react';
+import get from 'lodash/get';
+import { useTheme } from 'providers/Theme';
+import { useDispatch } from 'react-redux';
+import SingleLineEditor from 'components/SingleLineEditor';
+import { updateAuth } from 'providers/ReduxStore/slices/collections';
+import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions';
+import StyledWrapper from './StyledWrapper';
+
+const DigestAuth = ({ item, collection }) => {
+ const dispatch = useDispatch();
+ const { storedTheme } = useTheme();
+
+ const digestAuth = item.draft ? get(item, 'draft.request.auth.digest', {}) : get(item, 'request.auth.digest', {});
+
+ const handleRun = () => dispatch(sendRequest(item, collection.uid));
+ const handleSave = () => dispatch(saveRequest(item.uid, collection.uid));
+
+ const handleUsernameChange = (username) => {
+ dispatch(
+ updateAuth({
+ mode: 'digest',
+ collectionUid: collection.uid,
+ itemUid: item.uid,
+ content: {
+ username: username,
+ password: digestAuth.password
+ }
+ })
+ );
+ };
+
+ const handlePasswordChange = (password) => {
+ dispatch(
+ updateAuth({
+ mode: 'digest',
+ collectionUid: collection.uid,
+ itemUid: item.uid,
+ content: {
+ username: digestAuth.username,
+ password: password
+ }
+ })
+ );
+ };
+
+ return (
+
+
+
+ handleUsernameChange(val)}
+ onRun={handleRun}
+ collection={collection}
+ />
+
+
+
+
+ handlePasswordChange(val)}
+ onRun={handleRun}
+ collection={collection}
+ />
+
+
+ );
+};
+
+export default DigestAuth;
diff --git a/packages/bruno-app/src/components/RequestPane/Auth/index.js b/packages/bruno-app/src/components/RequestPane/Auth/index.js
index 669f4a843..bd388737e 100644
--- a/packages/bruno-app/src/components/RequestPane/Auth/index.js
+++ b/packages/bruno-app/src/components/RequestPane/Auth/index.js
@@ -4,6 +4,7 @@ import AuthMode from './AuthMode';
import AwsV4Auth from './AwsV4Auth';
import BearerAuth from './BearerAuth';
import BasicAuth from './BasicAuth';
+import DigestAuth from './DigestAuth';
import StyledWrapper from './StyledWrapper';
const Auth = ({ item, collection }) => {
@@ -20,6 +21,9 @@ const Auth = ({ item, collection }) => {
case 'bearer': {
return
;
}
+ case 'digest': {
+ return
;
+ }
}
};
diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
index 4ad30d204..24655f4f0 100644
--- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
+++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
@@ -388,6 +388,10 @@ export const collectionsSlice = createSlice({
item.draft.request.auth.mode = 'basic';
item.draft.request.auth.basic = action.payload.content;
break;
+ case 'digest':
+ item.draft.request.auth.mode = 'digest';
+ item.draft.request.auth.digest = action.payload.content;
+ break;
}
}
}
@@ -976,6 +980,9 @@ export const collectionsSlice = createSlice({
case 'basic':
set(collection, 'root.request.auth.basic', action.payload.content);
break;
+ case 'digest':
+ set(collection, 'root.request.auth.digest', action.payload.content);
+ break;
}
}
},
diff --git a/packages/bruno-app/src/utils/collections/index.js b/packages/bruno-app/src/utils/collections/index.js
index 0b98fbc28..05dd0fb43 100644
--- a/packages/bruno-app/src/utils/collections/index.js
+++ b/packages/bruno-app/src/utils/collections/index.js
@@ -494,6 +494,10 @@ export const humanizeRequestAuthMode = (mode) => {
label = 'Bearer Token';
break;
}
+ case 'digest': {
+ label = 'Digest Auth';
+ break;
+ }
}
return label;
diff --git a/packages/bruno-app/src/utils/importers/insomnia-collection.js b/packages/bruno-app/src/utils/importers/insomnia-collection.js
index 8d8113b49..80e9bb0a0 100644
--- a/packages/bruno-app/src/utils/importers/insomnia-collection.js
+++ b/packages/bruno-app/src/utils/importers/insomnia-collection.js
@@ -80,7 +80,8 @@ const transformInsomniaRequestItem = (request, index, allRequests) => {
auth: {
mode: 'none',
basic: null,
- bearer: null
+ bearer: null,
+ digest: null
},
headers: [],
params: [],
diff --git a/packages/bruno-app/src/utils/importers/openapi-collection.js b/packages/bruno-app/src/utils/importers/openapi-collection.js
index 1ca6e25b7..20a915bd4 100644
--- a/packages/bruno-app/src/utils/importers/openapi-collection.js
+++ b/packages/bruno-app/src/utils/importers/openapi-collection.js
@@ -69,7 +69,8 @@ const transformOpenapiRequestItem = (request) => {
auth: {
mode: 'none',
basic: null,
- bearer: null
+ bearer: null,
+ digest: null
},
headers: [],
params: [],
diff --git a/packages/bruno-electron/src/ipc/network/digestauth-helper.js b/packages/bruno-electron/src/ipc/network/digestauth-helper.js
new file mode 100644
index 000000000..fdcf77cc2
--- /dev/null
+++ b/packages/bruno-electron/src/ipc/network/digestauth-helper.js
@@ -0,0 +1,79 @@
+const crypto = require('crypto');
+
+function isStrPresent(str) {
+ return str && str !== '' && str !== 'undefined';
+}
+
+function stripQuotes(str) {
+ return str.replace(/"/g, '');
+}
+
+function containsDigestHeader(response) {
+ const authHeader = response?.headers?.['www-authenticate'];
+ return authHeader ? authHeader.trim().toLowerCase().startsWith('digest') : false;
+}
+
+function containsAuthorizationHeader(originalRequest) {
+ return Boolean(originalRequest.headers['Authorization']);
+}
+
+function md5(input) {
+ return crypto.createHash('md5').update(input).digest('hex');
+}
+
+function addDigestInterceptor(axiosInstance, request) {
+ const { username, password } = request.digestConfig;
+
+ console.debug(request);
+
+ if (!isStrPresent(username) || !isStrPresent(password)) {
+ console.warn('Required Digest Auth fields are not present');
+ return;
+ }
+
+ axiosInstance.interceptors.response.use(
+ (response) => response,
+ (error) => {
+ const originalRequest = error.config;
+
+ if (
+ error.response?.status === 401 &&
+ containsDigestHeader(error.response) &&
+ !containsAuthorizationHeader(originalRequest)
+ ) {
+ console.debug(error.response.headers['www-authenticate']);
+
+ const authDetails = error.response.headers['www-authenticate']
+ .split(', ')
+ .map((v) => v.split('=').map(stripQuotes))
+ .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
+ console.debug(authDetails);
+
+ const nonceCount = '00000001';
+ const cnonce = crypto.randomBytes(24).toString('hex');
+
+ if (authDetails.algorithm.toUpperCase() !== 'MD5') {
+ console.warn(`Unsupported Digest algorithm: ${algo}`);
+ return Promise.reject(error);
+ }
+ const HA1 = md5(`${username}:${authDetails['Digest realm']}:${password}`);
+ const HA2 = md5(`${request.method}:${request.url}`);
+ const response = md5(`${HA1}:${authDetails.nonce}:${nonceCount}:${cnonce}:auth:${HA2}`);
+
+ const authorizationHeader =
+ `Digest username="${username}",realm="${authDetails['Digest realm']}",` +
+ `nonce="${authDetails.nonce}",uri="${request.url}",qop="auth",algorithm="${authDetails.algorithm}",` +
+ `response="${response}",nc="${nonceCount}",cnonce="${cnonce}"`;
+ originalRequest.headers['Authorization'] = authorizationHeader;
+ console.debug(`Authorization: ${originalRequest.headers['Authorization']}`);
+
+ delete originalRequest.digestConfig;
+ return axiosInstance(originalRequest);
+ }
+
+ return Promise.reject(error);
+ }
+ );
+}
+
+module.exports = { addDigestInterceptor };
diff --git a/packages/bruno-electron/src/ipc/network/index.js b/packages/bruno-electron/src/ipc/network/index.js
index daace4792..6a4969931 100644
--- a/packages/bruno-electron/src/ipc/network/index.js
+++ b/packages/bruno-electron/src/ipc/network/index.js
@@ -23,6 +23,7 @@ const { HttpProxyAgent } = require('http-proxy-agent');
const { SocksProxyAgent } = require('socks-proxy-agent');
const { makeAxiosInstance } = require('./axios-instance');
const { addAwsV4Interceptor, resolveAwsV4Credentials } = require('./awsv4auth-helper');
+const { addDigestInterceptor } = require('./digestauth-helper');
const { shouldUseProxy, PatchedHttpsProxyAgent } = require('../../utils/proxy-util');
// override the default escape function to prevent escaping
@@ -168,6 +169,10 @@ const configureRequest = async (collectionUid, request, envVars, collectionVaria
delete request.awsv4config;
}
+ if (request.digestConfig) {
+ addDigestInterceptor(axiosInstance, request);
+ }
+
request.timeout = preferencesUtil.getRequestTimeout();
return axiosInstance;
diff --git a/packages/bruno-electron/src/ipc/network/interpolate-vars.js b/packages/bruno-electron/src/ipc/network/interpolate-vars.js
index 31d5cab55..6df6a7c1a 100644
--- a/packages/bruno-electron/src/ipc/network/interpolate-vars.js
+++ b/packages/bruno-electron/src/ipc/network/interpolate-vars.js
@@ -131,6 +131,12 @@ const interpolateVars = (request, envVars = {}, collectionVariables = {}, proces
request.awsv4config.profileName = interpolate(request.awsv4config.profileName) || '';
}
+ // interpolate vars for digest auth
+ if (request.digestConfig) {
+ request.digestConfig.username = interpolate(request.digestConfig.username) || '';
+ request.digestConfig.password = interpolate(request.digestConfig.password) || '';
+ }
+
return request;
};
diff --git a/packages/bruno-electron/src/ipc/network/prepare-request.js b/packages/bruno-electron/src/ipc/network/prepare-request.js
index 6e3f123c1..d5e17a6fd 100644
--- a/packages/bruno-electron/src/ipc/network/prepare-request.js
+++ b/packages/bruno-electron/src/ipc/network/prepare-request.js
@@ -28,6 +28,12 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
case 'bearer':
axiosRequest.headers['authorization'] = `Bearer ${get(collectionAuth, 'bearer.token')}`;
break;
+ case 'digest':
+ axiosRequest.digestConfig = {
+ username: get(collectionAuth, 'digest.username'),
+ password: get(collectionAuth, 'digest.password')
+ };
+ break;
}
}
@@ -52,6 +58,11 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
case 'bearer':
axiosRequest.headers['authorization'] = `Bearer ${get(request, 'auth.bearer.token')}`;
break;
+ case 'digest':
+ axiosRequest.digestConfig = {
+ username: get(request, 'auth.digest.username'),
+ password: get(request, 'auth.digest.password')
+ };
}
}
diff --git a/packages/bruno-lang/v2/src/bruToJson.js b/packages/bruno-lang/v2/src/bruToJson.js
index d8d51d3b1..fbe289974 100644
--- a/packages/bruno-lang/v2/src/bruToJson.js
+++ b/packages/bruno-lang/v2/src/bruToJson.js
@@ -23,7 +23,7 @@ const { outdentString } = require('../../v1/src/utils');
*/
const grammar = ohm.grammar(`Bru {
BruFile = (meta | http | query | headers | auths | bodies | varsandassert | script | tests | docs)*
- auths = authawsv4 | authbasic | authbearer
+ auths = authawsv4 | authbasic | authbearer | authdigest
bodies = bodyjson | bodytext | bodyxml | bodysparql | bodygraphql | bodygraphqlvars | bodyforms | body
bodyforms = bodyformurlencoded | bodymultipart
@@ -79,6 +79,7 @@ const grammar = ohm.grammar(`Bru {
authawsv4 = "auth:awsv4" dictionary
authbasic = "auth:basic" dictionary
authbearer = "auth:bearer" dictionary
+ authdigest = "auth:digest" dictionary
body = "body" st* "{" nl* textblock tagend
bodyjson = "body:json" st* "{" nl* textblock tagend
@@ -350,6 +351,21 @@ const sem = grammar.createSemantics().addAttribute('ast', {
}
};
},
+ authdigest(_1, dictionary) {
+ const auth = mapPairListToKeyValPairs(dictionary.ast, false);
+ const usernameKey = _.find(auth, { name: 'username' });
+ const passwordKey = _.find(auth, { name: 'password' });
+ const username = usernameKey ? usernameKey.value : '';
+ const password = passwordKey ? passwordKey.value : '';
+ return {
+ auth: {
+ digest: {
+ username,
+ password
+ }
+ }
+ };
+ },
bodyformurlencoded(_1, dictionary) {
return {
body: {
diff --git a/packages/bruno-lang/v2/src/collectionBruToJson.js b/packages/bruno-lang/v2/src/collectionBruToJson.js
index 4569736f1..c24f6e6ae 100644
--- a/packages/bruno-lang/v2/src/collectionBruToJson.js
+++ b/packages/bruno-lang/v2/src/collectionBruToJson.js
@@ -4,7 +4,7 @@ const { outdentString } = require('../../v1/src/utils');
const grammar = ohm.grammar(`Bru {
BruFile = (meta | query | headers | auth | auths | vars | script | tests | docs)*
- auths = authawsv4 | authbasic | authbearer
+ auths = authawsv4 | authbasic | authbearer | authdigest
nl = "\\r"? "\\n"
st = " " | "\\t"
@@ -41,6 +41,7 @@ const grammar = ohm.grammar(`Bru {
authawsv4 = "auth:awsv4" dictionary
authbasic = "auth:basic" dictionary
authbearer = "auth:bearer" dictionary
+ authdigest = "auth:digest" dictionary
script = scriptreq | scriptres
scriptreq = "script:pre-request" st* "{" nl* textblock tagend
@@ -226,6 +227,21 @@ const sem = grammar.createSemantics().addAttribute('ast', {
}
};
},
+ authdigest(_1, dictionary) {
+ const auth = mapPairListToKeyValPairs(dictionary.ast, false);
+ const usernameKey = _.find(auth, { name: 'username' });
+ const passwordKey = _.find(auth, { name: 'password' });
+ const username = usernameKey ? usernameKey.value : '';
+ const password = passwordKey ? passwordKey.value : '';
+ return {
+ auth: {
+ digest: {
+ username,
+ password
+ }
+ }
+ };
+ },
varsreq(_1, dictionary) {
const vars = mapPairListToKeyValPairs(dictionary.ast);
_.each(vars, (v) => {
diff --git a/packages/bruno-lang/v2/src/jsonToBru.js b/packages/bruno-lang/v2/src/jsonToBru.js
index 56b5ec478..f4959500a 100644
--- a/packages/bruno-lang/v2/src/jsonToBru.js
+++ b/packages/bruno-lang/v2/src/jsonToBru.js
@@ -114,6 +114,15 @@ ${indentString(`password: ${auth.basic.password}`)}
${indentString(`token: ${auth.bearer.token}`)}
}
+`;
+ }
+
+ if (auth && auth.digest) {
+ bru += `auth:digest {
+${indentString(`username: ${auth.digest.username}`)}
+${indentString(`password: ${auth.digest.password}`)}
+}
+
`;
}
diff --git a/packages/bruno-lang/v2/src/jsonToCollectionBru.js b/packages/bruno-lang/v2/src/jsonToCollectionBru.js
index ea928a68f..08a3abad5 100644
--- a/packages/bruno-lang/v2/src/jsonToCollectionBru.js
+++ b/packages/bruno-lang/v2/src/jsonToCollectionBru.js
@@ -102,6 +102,15 @@ ${indentString(`password: ${auth.basic.password}`)}
${indentString(`token: ${auth.bearer.token}`)}
}
+`;
+ }
+
+ if (auth && auth.digest) {
+ bru += `auth:digest {
+${indentString(`username: ${auth.digest.username}`)}
+${indentString(`password: ${auth.digest.password}`)}
+}
+
`;
}
diff --git a/packages/bruno-lang/v2/tests/fixtures/collection.bru b/packages/bruno-lang/v2/tests/fixtures/collection.bru
index a02be30cb..44a66c8dc 100644
--- a/packages/bruno-lang/v2/tests/fixtures/collection.bru
+++ b/packages/bruno-lang/v2/tests/fixtures/collection.bru
@@ -21,6 +21,11 @@ auth:bearer {
token: 123
}
+auth:digest {
+ username: john
+ password: secret
+}
+
vars:pre-request {
departingDate: 2020-01-01
~returningDate: 2020-01-02
diff --git a/packages/bruno-lang/v2/tests/fixtures/collection.json b/packages/bruno-lang/v2/tests/fixtures/collection.json
index de827d11e..7bda2534d 100644
--- a/packages/bruno-lang/v2/tests/fixtures/collection.json
+++ b/packages/bruno-lang/v2/tests/fixtures/collection.json
@@ -27,6 +27,10 @@
},
"bearer": {
"token": "123"
+ },
+ "digest": {
+ "username": "john",
+ "password": "secret"
}
},
"vars": {
diff --git a/packages/bruno-lang/v2/tests/fixtures/request.bru b/packages/bruno-lang/v2/tests/fixtures/request.bru
index 22168b194..21b20477b 100644
--- a/packages/bruno-lang/v2/tests/fixtures/request.bru
+++ b/packages/bruno-lang/v2/tests/fixtures/request.bru
@@ -40,6 +40,11 @@ auth:bearer {
token: 123
}
+auth:digest {
+ username: john
+ password: secret
+}
+
body:json {
{
"hello": "world"
diff --git a/packages/bruno-lang/v2/tests/fixtures/request.json b/packages/bruno-lang/v2/tests/fixtures/request.json
index def7b5f08..c23c46474 100644
--- a/packages/bruno-lang/v2/tests/fixtures/request.json
+++ b/packages/bruno-lang/v2/tests/fixtures/request.json
@@ -59,6 +59,10 @@
},
"bearer": {
"token": "123"
+ },
+ "digest": {
+ "username": "john",
+ "password": "secret"
}
},
"body": {
diff --git a/packages/bruno-schema/src/collections/index.js b/packages/bruno-schema/src/collections/index.js
index e63d8c3d2..37e6629af 100644
--- a/packages/bruno-schema/src/collections/index.js
+++ b/packages/bruno-schema/src/collections/index.js
@@ -94,11 +94,19 @@ const authBearerSchema = Yup.object({
.noUnknown(true)
.strict();
+const authDigestSchema = Yup.object({
+ username: Yup.string().nullable(),
+ password: Yup.string().nullable()
+})
+ .noUnknown(true)
+ .strict();
+
const authSchema = Yup.object({
- mode: Yup.string().oneOf(['none', 'awsv4', 'basic', 'bearer']).required('mode is required'),
+ mode: Yup.string().oneOf(['none', 'awsv4', 'basic', 'bearer', 'digest']).required('mode is required'),
awsv4: authAwsV4Schema.nullable(),
basic: authBasicSchema.nullable(),
- bearer: authBearerSchema.nullable()
+ bearer: authBearerSchema.nullable(),
+ digest: authDigestSchema.nullable()
})
.noUnknown(true)
.strict();