mirror of
https://github.com/Infisical/infisical.git
synced 2025-03-25 14:05:03 +00:00
Add integration auth revocation
This commit is contained in:
@ -5,7 +5,7 @@ import { readFileSync } from 'fs';
|
||||
import { IntegrationAuth, Integration } from '../models';
|
||||
import { INTEGRATION_SET, ENV_DEV } from '../variables';
|
||||
import { IntegrationService } from '../services';
|
||||
import { getApps } from '../integrations';
|
||||
import { getApps, revokeAccess } from '../integrations';
|
||||
|
||||
/**
|
||||
* Perform OAuth2 code-token exchange as part of integration [integration] for workspace with id [workspaceId]
|
||||
@ -74,46 +74,22 @@ export const getIntegrationAuthApps = async (req: Request, res: Response) => {
|
||||
* @returns
|
||||
*/
|
||||
export const deleteIntegrationAuth = async (req: Request, res: Response) => {
|
||||
// TODO: unfinished - disable application via Heroku API and make compatible with other integration types
|
||||
try {
|
||||
const { integrationAuthId } = req.params;
|
||||
|
||||
// TODO: disable application via Heroku API; figure out what authorization id is
|
||||
|
||||
const integrations = JSON.parse(
|
||||
readFileSync('./src/json/integrations.json').toString()
|
||||
);
|
||||
|
||||
let authorizationId;
|
||||
switch (req.integrationAuth.integration) {
|
||||
case 'heroku':
|
||||
authorizationId = integrations.heroku.clientId;
|
||||
}
|
||||
|
||||
// not sure what authorizationId is?
|
||||
// // revoke authorization
|
||||
// const res2 = await axios.delete(
|
||||
// `https://api.heroku.com/oauth/authorizations/${authorizationId}`,
|
||||
// {
|
||||
// headers: {
|
||||
// 'Accept': 'application/vnd.heroku+json; version=3',
|
||||
// 'Authorization': 'Bearer ' + req.accessToken
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
|
||||
const deletedIntegrationAuth = await IntegrationAuth.findOneAndDelete({
|
||||
_id: integrationAuthId
|
||||
await revokeAccess({
|
||||
integrationAuth: req.integrationAuth,
|
||||
accessToken: req.accessToken
|
||||
});
|
||||
|
||||
if (deletedIntegrationAuth) {
|
||||
await Integration.deleteMany({
|
||||
integrationAuth: deletedIntegrationAuth._id
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
return res.status(400).send({
|
||||
message: 'Failed to delete integration authorization'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return res.status(200).send({
|
||||
message: 'Successfully deleted integration authorization'
|
||||
});
|
||||
}
|
@ -2,10 +2,12 @@ import { exchangeCode } from './exchange';
|
||||
import { exchangeRefresh } from './refresh';
|
||||
import { getApps } from './apps';
|
||||
import { syncSecrets } from './sync';
|
||||
import { revokeAccess } from './revoke';
|
||||
|
||||
export {
|
||||
exchangeCode,
|
||||
exchangeRefresh,
|
||||
getApps,
|
||||
syncSecrets
|
||||
syncSecrets,
|
||||
revokeAccess
|
||||
}
|
50
backend/src/integrations/revoke.ts
Normal file
50
backend/src/integrations/revoke.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import axios from 'axios';
|
||||
import * as Sentry from '@sentry/node';
|
||||
import {
|
||||
IIntegrationAuth,
|
||||
IntegrationAuth,
|
||||
Integration
|
||||
} from '../models';
|
||||
import {
|
||||
INTEGRATION_HEROKU,
|
||||
INTEGRATION_VERCEL,
|
||||
INTEGRATION_NETLIFY
|
||||
} from '../variables';
|
||||
|
||||
const revokeAccess = async ({
|
||||
integrationAuth,
|
||||
accessToken
|
||||
}: {
|
||||
integrationAuth: IIntegrationAuth,
|
||||
accessToken: String
|
||||
}) => {
|
||||
try {
|
||||
// add any integration-specific revocation logic
|
||||
switch (integrationAuth.integration) {
|
||||
case INTEGRATION_HEROKU:
|
||||
break;
|
||||
case INTEGRATION_VERCEL:
|
||||
break;
|
||||
case INTEGRATION_NETLIFY:
|
||||
break;
|
||||
}
|
||||
|
||||
const deletedIntegrationAuth = await IntegrationAuth.findOneAndDelete({
|
||||
_id: integrationAuth._id
|
||||
});
|
||||
|
||||
if (deletedIntegrationAuth) {
|
||||
await Integration.deleteMany({
|
||||
integrationAuth: deletedIntegrationAuth._id
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
throw new Error('Failed to delete integration authorization');
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
revokeAccess
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import {
|
||||
faCheck,
|
||||
@ -33,6 +34,7 @@ const CloudIntegration = ({
|
||||
integrationOptionPress,
|
||||
integrationAuths
|
||||
}: Props) => {
|
||||
const router = useRouter();
|
||||
return integrationAuths ? (
|
||||
<div
|
||||
className={`relative ${
|
||||
@ -74,7 +76,8 @@ const CloudIntegration = ({
|
||||
.includes(cloudIntegrationOption.name.toLowerCase()) && (
|
||||
<div className="absolute group z-50 top-0 right-0 flex flex-row">
|
||||
<div
|
||||
onClick={() => {
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
deleteIntegrationAuth({
|
||||
integrationAuthId: integrationAuths
|
||||
.filter(
|
||||
|
@ -115,44 +115,24 @@ export default function Integrations() {
|
||||
* @returns
|
||||
*/
|
||||
const handleIntegrationOption = async ({ integrationOption }) => {
|
||||
// TODO: modularize and handle switch by slug
|
||||
|
||||
console.log('handle', integrationOption);
|
||||
|
||||
// generate CSRF token for OAuth2 code-token exchange integrations
|
||||
const state = crypto.randomBytes(16).toString("hex");
|
||||
localStorage.setItem('latestCSRFToken', state);
|
||||
|
||||
switch (integrationOption.name) {
|
||||
case 'Heroku':
|
||||
// console.log('Heroku integration ', integrationOption);
|
||||
window.location = `https://id.heroku.com/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=write-protected&state=${state}`;
|
||||
break;
|
||||
case 'Vercel':
|
||||
window.location = `https://vercel.com/integrations/infisical/new?state=${state}`;
|
||||
break;
|
||||
case 'Netlify':
|
||||
// window.location = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=token&redirect_uri=${integrationOption.redirectURL}&state=${state}`;
|
||||
window.location = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=code&redirect_uri=${integrationOption.redirectURL}&state=${state}`;
|
||||
// const res = await axios.post('https://api.netlify.com/api/v1/oauth/tickets' + '?client_id=' + integrationOption.clientId);
|
||||
|
||||
// window.location = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=ticket&redirect_uri=${integrationOption.redirectURL}&state=${state}&ticket=${res.data.id}`;
|
||||
// `https://app.netlify.com/authorize?response_type=ticket&ticket=${ticket.id}`
|
||||
try {
|
||||
// const res = await axios.post('https://api.netlify.com/api/v1/oauth/tickets' + '?client_id=' + integrationOption.clientId);
|
||||
// console.log('res response', res);
|
||||
// const res2 = await axios.get('https://api.netlify.com/api/v1/oauth/tickets/' + res.data.id);
|
||||
// console.log('res2 response', res2);
|
||||
// console.log('ticket_id', res.data.id);
|
||||
// // exchange ticket:
|
||||
// const res3 = await axios.get(`https://api.netlify.com/api/v1/oauth/tickets/${res.data.id}/exchange`);
|
||||
// console.log('res3 response', res3);
|
||||
|
||||
} catch (err) {
|
||||
console.error('Netlify ', err);
|
||||
}
|
||||
|
||||
break;
|
||||
try {
|
||||
// generate CSRF token for OAuth2 code-token exchange integrations
|
||||
const state = crypto.randomBytes(16).toString("hex");
|
||||
localStorage.setItem('latestCSRFToken', state);
|
||||
|
||||
switch (integrationOption.name) {
|
||||
case 'Heroku':
|
||||
window.location = `https://id.heroku.com/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=write-protected&state=${state}`;
|
||||
break;
|
||||
case 'Vercel':
|
||||
window.location = `https://vercel.com/integrations/infisical/new?state=${state}`;
|
||||
break;
|
||||
case 'Netlify':
|
||||
window.location = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=code&redirect_uri=${integrationOption.redirectURL}&state=${state}`;
|
||||
break;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user