mirror of
https://github.com/usebruno/bruno.git
synced 2024-11-25 01:14:23 +01:00
feat: add support for state param for OAuth2 Authorization Code flow (#2330)
* feat: add support for state param * chore: revert package-lock.json * test: update tests with state param * chore: revert package-lock.json * chore: add state to missing places * Adding state to PKCE toggle --------- Co-authored-by: Kadam Dhananjay <kadamdhananjay@johndeere.com>
This commit is contained in:
parent
3ded960938
commit
32b1ba1c92
@ -22,7 +22,7 @@ const OAuth2AuthorizationCode = ({ collection }) => {
|
|||||||
|
|
||||||
const handleSave = () => dispatch(saveCollectionRoot(collection.uid));
|
const handleSave = () => dispatch(saveCollectionRoot(collection.uid));
|
||||||
|
|
||||||
const { callbackUrl, authorizationUrl, accessTokenUrl, clientId, clientSecret, scope, pkce } = oAuth;
|
const { callbackUrl, authorizationUrl, accessTokenUrl, clientId, clientSecret, scope, state, pkce } = oAuth;
|
||||||
|
|
||||||
const handleChange = (key, value) => {
|
const handleChange = (key, value) => {
|
||||||
dispatch(
|
dispatch(
|
||||||
@ -37,6 +37,7 @@ const OAuth2AuthorizationCode = ({ collection }) => {
|
|||||||
clientId,
|
clientId,
|
||||||
clientSecret,
|
clientSecret,
|
||||||
scope,
|
scope,
|
||||||
|
state,
|
||||||
pkce,
|
pkce,
|
||||||
[key]: value
|
[key]: value
|
||||||
}
|
}
|
||||||
@ -57,6 +58,7 @@ const OAuth2AuthorizationCode = ({ collection }) => {
|
|||||||
clientId,
|
clientId,
|
||||||
clientSecret,
|
clientSecret,
|
||||||
scope,
|
scope,
|
||||||
|
state,
|
||||||
pkce: !Boolean(oAuth?.['pkce'])
|
pkce: !Boolean(oAuth?.['pkce'])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -22,6 +22,10 @@ const inputsConfig = [
|
|||||||
{
|
{
|
||||||
key: 'scope',
|
key: 'scope',
|
||||||
label: 'Scope'
|
label: 'Scope'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'state',
|
||||||
|
label: 'State'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
|
|||||||
|
|
||||||
const handleSave = () => dispatch(saveRequest(item.uid, collection.uid));
|
const handleSave = () => dispatch(saveRequest(item.uid, collection.uid));
|
||||||
|
|
||||||
const { callbackUrl, authorizationUrl, accessTokenUrl, clientId, clientSecret, scope, pkce } = oAuth;
|
const { callbackUrl, authorizationUrl, accessTokenUrl, clientId, clientSecret, scope, state, pkce } = oAuth;
|
||||||
|
|
||||||
const handleChange = (key, value) => {
|
const handleChange = (key, value) => {
|
||||||
dispatch(
|
dispatch(
|
||||||
@ -37,6 +37,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
|
|||||||
accessTokenUrl,
|
accessTokenUrl,
|
||||||
clientId,
|
clientId,
|
||||||
clientSecret,
|
clientSecret,
|
||||||
|
state,
|
||||||
scope,
|
scope,
|
||||||
pkce,
|
pkce,
|
||||||
[key]: value
|
[key]: value
|
||||||
@ -58,6 +59,7 @@ const OAuth2AuthorizationCode = ({ item, collection }) => {
|
|||||||
accessTokenUrl,
|
accessTokenUrl,
|
||||||
clientId,
|
clientId,
|
||||||
clientSecret,
|
clientSecret,
|
||||||
|
state,
|
||||||
scope,
|
scope,
|
||||||
pkce: !Boolean(oAuth?.['pkce'])
|
pkce: !Boolean(oAuth?.['pkce'])
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,10 @@ const inputsConfig = [
|
|||||||
{
|
{
|
||||||
key: 'scope',
|
key: 'scope',
|
||||||
label: 'Scope'
|
label: 'Scope'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'state',
|
||||||
|
label: 'State'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -169,6 +169,7 @@ const interpolateVars = (request, envVars = {}, collectionVariables = {}, proces
|
|||||||
request.oauth2.clientId = _interpolate(request.oauth2.clientId) || '';
|
request.oauth2.clientId = _interpolate(request.oauth2.clientId) || '';
|
||||||
request.oauth2.clientSecret = _interpolate(request.oauth2.clientSecret) || '';
|
request.oauth2.clientSecret = _interpolate(request.oauth2.clientSecret) || '';
|
||||||
request.oauth2.scope = _interpolate(request.oauth2.scope) || '';
|
request.oauth2.scope = _interpolate(request.oauth2.scope) || '';
|
||||||
|
request.oauth2.state = _interpolate(request.oauth2.state) || '';
|
||||||
request.oauth2.pkce = _interpolate(request.oauth2.pkce) || false;
|
request.oauth2.pkce = _interpolate(request.oauth2.pkce) || false;
|
||||||
break;
|
break;
|
||||||
case 'client_credentials':
|
case 'client_credentials':
|
||||||
|
@ -23,14 +23,15 @@ const resolveOAuth2AuthorizationCodeAccessToken = async (request, collectionUid)
|
|||||||
let requestCopy = cloneDeep(request);
|
let requestCopy = cloneDeep(request);
|
||||||
const { authorizationCode } = await getOAuth2AuthorizationCode(requestCopy, codeChallenge, collectionUid);
|
const { authorizationCode } = await getOAuth2AuthorizationCode(requestCopy, codeChallenge, collectionUid);
|
||||||
const oAuth = get(requestCopy, 'oauth2', {});
|
const oAuth = get(requestCopy, 'oauth2', {});
|
||||||
const { clientId, clientSecret, callbackUrl, scope, pkce } = oAuth;
|
const { clientId, clientSecret, callbackUrl, scope, state, pkce } = oAuth;
|
||||||
const data = {
|
const data = {
|
||||||
grant_type: 'authorization_code',
|
grant_type: 'authorization_code',
|
||||||
code: authorizationCode,
|
code: authorizationCode,
|
||||||
redirect_uri: callbackUrl,
|
redirect_uri: callbackUrl,
|
||||||
client_id: clientId,
|
client_id: clientId,
|
||||||
client_secret: clientSecret,
|
client_secret: clientSecret,
|
||||||
scope: scope
|
scope: scope,
|
||||||
|
state: state
|
||||||
};
|
};
|
||||||
if (pkce) {
|
if (pkce) {
|
||||||
data['code_verifier'] = codeVerifier;
|
data['code_verifier'] = codeVerifier;
|
||||||
@ -46,7 +47,7 @@ const resolveOAuth2AuthorizationCodeAccessToken = async (request, collectionUid)
|
|||||||
const getOAuth2AuthorizationCode = (request, codeChallenge, collectionUid) => {
|
const getOAuth2AuthorizationCode = (request, codeChallenge, collectionUid) => {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
const { oauth2 } = request;
|
const { oauth2 } = request;
|
||||||
const { callbackUrl, clientId, authorizationUrl, scope, pkce } = oauth2;
|
const { callbackUrl, clientId, authorizationUrl, scope, state, pkce } = oauth2;
|
||||||
|
|
||||||
let oauth2QueryParams =
|
let oauth2QueryParams =
|
||||||
(authorizationUrl.indexOf('?') > -1 ? '&' : '?') + `client_id=${clientId}&response_type=code`;
|
(authorizationUrl.indexOf('?') > -1 ? '&' : '?') + `client_id=${clientId}&response_type=code`;
|
||||||
@ -59,6 +60,10 @@ const getOAuth2AuthorizationCode = (request, codeChallenge, collectionUid) => {
|
|||||||
if (pkce) {
|
if (pkce) {
|
||||||
oauth2QueryParams += `&code_challenge=${codeChallenge}&code_challenge_method=S256`;
|
oauth2QueryParams += `&code_challenge=${codeChallenge}&code_challenge_method=S256`;
|
||||||
}
|
}
|
||||||
|
if (state) {
|
||||||
|
oauth2QueryParams += `&state=${state}`;
|
||||||
|
}
|
||||||
|
|
||||||
const authorizationUrlWithQueryParams = authorizationUrl + oauth2QueryParams;
|
const authorizationUrlWithQueryParams = authorizationUrl + oauth2QueryParams;
|
||||||
try {
|
try {
|
||||||
const oauth2Store = new Oauth2Store();
|
const oauth2Store = new Oauth2Store();
|
||||||
|
@ -112,6 +112,7 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => {
|
|||||||
clientId: get(request, 'auth.oauth2.clientId'),
|
clientId: get(request, 'auth.oauth2.clientId'),
|
||||||
clientSecret: get(request, 'auth.oauth2.clientSecret'),
|
clientSecret: get(request, 'auth.oauth2.clientSecret'),
|
||||||
scope: get(request, 'auth.oauth2.scope'),
|
scope: get(request, 'auth.oauth2.scope'),
|
||||||
|
state: get(request, 'auth.oauth2.state'),
|
||||||
pkce: get(request, 'auth.oauth2.pkce')
|
pkce: get(request, 'auth.oauth2.pkce')
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
@ -444,6 +444,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
|||||||
const clientIdKey = _.find(auth, { name: 'client_id' });
|
const clientIdKey = _.find(auth, { name: 'client_id' });
|
||||||
const clientSecretKey = _.find(auth, { name: 'client_secret' });
|
const clientSecretKey = _.find(auth, { name: 'client_secret' });
|
||||||
const scopeKey = _.find(auth, { name: 'scope' });
|
const scopeKey = _.find(auth, { name: 'scope' });
|
||||||
|
const stateKey = _.find(auth, { name: 'state' });
|
||||||
const pkceKey = _.find(auth, { name: 'pkce' });
|
const pkceKey = _.find(auth, { name: 'pkce' });
|
||||||
return {
|
return {
|
||||||
auth: {
|
auth: {
|
||||||
@ -467,6 +468,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
|||||||
clientId: clientIdKey ? clientIdKey.value : '',
|
clientId: clientIdKey ? clientIdKey.value : '',
|
||||||
clientSecret: clientSecretKey ? clientSecretKey.value : '',
|
clientSecret: clientSecretKey ? clientSecretKey.value : '',
|
||||||
scope: scopeKey ? scopeKey.value : '',
|
scope: scopeKey ? scopeKey.value : '',
|
||||||
|
state: stateKey ? stateKey.value : '',
|
||||||
pkce: pkceKey ? JSON.parse(pkceKey?.value || false) : false
|
pkce: pkceKey ? JSON.parse(pkceKey?.value || false) : false
|
||||||
}
|
}
|
||||||
: grantTypeKey?.value && grantTypeKey?.value == 'client_credentials'
|
: grantTypeKey?.value && grantTypeKey?.value == 'client_credentials'
|
||||||
|
@ -254,6 +254,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
|||||||
const clientIdKey = _.find(auth, { name: 'client_id' });
|
const clientIdKey = _.find(auth, { name: 'client_id' });
|
||||||
const clientSecretKey = _.find(auth, { name: 'client_secret' });
|
const clientSecretKey = _.find(auth, { name: 'client_secret' });
|
||||||
const scopeKey = _.find(auth, { name: 'scope' });
|
const scopeKey = _.find(auth, { name: 'scope' });
|
||||||
|
const stateKey = _.find(auth, { name: 'state' });
|
||||||
const pkceKey = _.find(auth, { name: 'pkce' });
|
const pkceKey = _.find(auth, { name: 'pkce' });
|
||||||
return {
|
return {
|
||||||
auth: {
|
auth: {
|
||||||
@ -277,6 +278,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
|||||||
clientId: clientIdKey ? clientIdKey.value : '',
|
clientId: clientIdKey ? clientIdKey.value : '',
|
||||||
clientSecret: clientSecretKey ? clientSecretKey.value : '',
|
clientSecret: clientSecretKey ? clientSecretKey.value : '',
|
||||||
scope: scopeKey ? scopeKey.value : '',
|
scope: scopeKey ? scopeKey.value : '',
|
||||||
|
state: stateKey ? stateKey.value : '',
|
||||||
pkce: pkceKey ? JSON.parse(pkceKey?.value || false) : false
|
pkce: pkceKey ? JSON.parse(pkceKey?.value || false) : false
|
||||||
}
|
}
|
||||||
: grantTypeKey?.value && grantTypeKey?.value == 'client_credentials'
|
: grantTypeKey?.value && grantTypeKey?.value == 'client_credentials'
|
||||||
|
@ -180,6 +180,7 @@ ${indentString(`access_token_url: ${auth?.oauth2?.accessTokenUrl || ''}`)}
|
|||||||
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
|
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
|
||||||
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
|
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
|
||||||
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
|
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
|
||||||
|
${indentString(`state: ${auth?.oauth2?.state || ''}`)}
|
||||||
${indentString(`pkce: ${(auth?.oauth2?.pkce || false).toString()}`)}
|
${indentString(`pkce: ${(auth?.oauth2?.pkce || false).toString()}`)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +138,7 @@ ${indentString(`access_token_url: ${auth?.oauth2?.accessTokenUrl || ''}`)}
|
|||||||
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
|
${indentString(`client_id: ${auth?.oauth2?.clientId || ''}`)}
|
||||||
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
|
${indentString(`client_secret: ${auth?.oauth2?.clientSecret || ''}`)}
|
||||||
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
|
${indentString(`scope: ${auth?.oauth2?.scope || ''}`)}
|
||||||
|
${indentString(`state: ${auth?.oauth2?.state || ''}`)}
|
||||||
${indentString(`pkce: ${(auth?.oauth2?.pkce || false).toString()}`)}
|
${indentString(`pkce: ${(auth?.oauth2?.pkce || false).toString()}`)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ auth:oauth2 {
|
|||||||
client_id: client_id_1
|
client_id: client_id_1
|
||||||
client_secret: client_secret_1
|
client_secret: client_secret_1
|
||||||
scope: read write
|
scope: read write
|
||||||
|
state: 807061d5f0be
|
||||||
pkce: false
|
pkce: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@
|
|||||||
"callbackUrl": "http://localhost:8080/api/auth/oauth2/authorization_code/callback",
|
"callbackUrl": "http://localhost:8080/api/auth/oauth2/authorization_code/callback",
|
||||||
"accessTokenUrl": "http://localhost:8080/api/auth/oauth2/authorization_code/token",
|
"accessTokenUrl": "http://localhost:8080/api/auth/oauth2/authorization_code/token",
|
||||||
"scope": "read write",
|
"scope": "read write",
|
||||||
|
"state": "807061d5f0be",
|
||||||
"pkce": false
|
"pkce": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -163,6 +163,11 @@ const oauth2Schema = Yup.object({
|
|||||||
then: Yup.string().nullable(),
|
then: Yup.string().nullable(),
|
||||||
otherwise: Yup.string().nullable().strip()
|
otherwise: Yup.string().nullable().strip()
|
||||||
}),
|
}),
|
||||||
|
state: Yup.string().when('grantType', {
|
||||||
|
is: (val) => ['authorization_code'].includes(val),
|
||||||
|
then: Yup.string().nullable(),
|
||||||
|
otherwise: Yup.string().nullable().strip()
|
||||||
|
}),
|
||||||
pkce: Yup.boolean().when('grantType', {
|
pkce: Yup.boolean().when('grantType', {
|
||||||
is: (val) => ['authorization_code'].includes(val),
|
is: (val) => ['authorization_code'].includes(val),
|
||||||
then: Yup.boolean().default(false),
|
then: Yup.boolean().default(false),
|
||||||
|
Loading…
Reference in New Issue
Block a user