Skip to content

Commit

Permalink
Add Fake IdP SAML App tokens: Frontend (#623)
Browse files Browse the repository at this point in the history
* Add Idp App tokens to frontend

* Idp token Preview component (#603)

* Add animation to Download button

---------

Co-authored-by: vittoriaThinkst <[email protected]>
Co-authored-by: Vittoria Toso <[email protected]>
  • Loading branch information
3 people authored Dec 7, 2024
1 parent 8dee4db commit 29817b0
Show file tree
Hide file tree
Showing 49 changed files with 496 additions and 15 deletions.
1 change: 1 addition & 0 deletions frontend_vue/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ declare module 'vue' {
BaseCodeSnippet: typeof import('./src/components/base/BaseCodeSnippet.vue')['default']
BaseContentBlock: typeof import('./src/components/base/BaseContentBlock.vue')['default']
BaseCopyButton: typeof import('./src/components/base/BaseCopyButton.vue')['default']
BaseDownloadIconButton: typeof import('./src/components/base/BaseDownloadIconButton.vue')['default']
BaseFormImageSelect: typeof import('./src/components/base/BaseFormImageSelect.vue')['default']
BaseFormSelect: typeof import('./src/components/base/BaseFormSelect.vue')['default']
BaseFormTextField: typeof import('./src/components/base/BaseFormTextField.vue')['default']
Expand Down
Binary file added frontend_vue/src/assets/idp_icons/aws.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/azure.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/dropbox.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/duo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/freshbooks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/gcloud.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/gdrive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/github.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/gitlab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/gmail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/intune.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/jamf.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/jira.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/kibana.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/lastpass.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/ms365.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/msteams.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/onedrive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/onepassword.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/outlook.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/pagerduty.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/sage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/salesforce.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend_vue/src/assets/idp_icons/sap.png
Binary file added frontend_vue/src/assets/idp_icons/slack.png
Binary file added frontend_vue/src/assets/idp_icons/virtru.png
Binary file added frontend_vue/src/assets/idp_icons/zendesk.png
Binary file added frontend_vue/src/assets/idp_icons/zoho.png
Binary file added frontend_vue/src/assets/idp_icons/zoom.png
Binary file added frontend_vue/src/assets/token_icons/idp_app.png
3 changes: 2 additions & 1 deletion frontend_vue/src/components/SettingsToken.vue
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ const props = defineProps<{
function isSupportBrowserScan() {
return (
props.tokenBackendResponse.canarydrop.type === TOKENS_TYPE.WEB_BUG ||
props.tokenBackendResponse.canarydrop.type === TOKENS_TYPE.WEB_IMAGE
props.tokenBackendResponse.canarydrop.type === TOKENS_TYPE.WEB_IMAGE ||
props.tokenBackendResponse.canarydrop.type === TOKENS_TYPE.IDP_APP
);
}
Expand Down
108 changes: 108 additions & 0 deletions frontend_vue/src/components/base/BaseDownloadIconButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<template>
<div
:class="props.disabled ? 'hover:brightness-100' : 'hover:brightness-110'"
class="relative flex items-center justify-center p-8 duration-100 bg-white border cursor-pointer rounded-2xl border-grey-200"
>
<a
v-bind="$attrs"
class="bg-cover min-w-[2.5rem] min-h-[2.2rem] duration-100 aspect-square"
:class="{ 'bg-grey-200 cursor-default': props.disabled }"
:style="
!props.disabled && props.url
? { backgroundImage: `url(${props.url})` }
: ''
"
:disabled="props.disabled"
download
:href="props.url"
@click="downloadContent"
>
<span class="sr-only">{{ props.alt }} Download</span>

<span
v-tooltip="{
content: tooltipText,
shown: isTriggered,
triggers: tooltipTriggers,
}"
:class="{ hidden: props.disabled }"
class="absolute w-[1.5rem] rounded-full h-[1.5rem] bg-green top-[-.5rem] right-[-.5rem] flex items-center justify-center text-white"
>
<Transition
name="fade"
mode="out-in"
>
<font-awesome-icon
v-if="!isTriggered"
icon="arrow-down"
></font-awesome-icon>
<font-awesome-icon
v-else
aria-hidden="true"
icon="check"
></font-awesome-icon>
</Transition>
</span>
</a>
</div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
const props = defineProps<{
url?: string;
alt?: string;
disabled?: boolean;
}>();
const tooltipText = ref('Download');
const isTriggered = ref(false);
const tooltipTriggers = ref(['hover', 'focus']);
function delay(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// 1. prevents UI from jumping when tooltip content changes
// 2. shows tooltip when content is downloaded
async function showTooltip() {
await delay(150);
tooltipTriggers.value = [];
isTriggered.value = true;
tooltipText.value = 'Download started!';
// vTooltip sets a default delay of 1.5s
await delay(1500);
isTriggered.value = false;
tooltipTriggers.value = ['hover', 'focus'];
await delay(150);
tooltipText.value = 'Download';
}
function downloadContent() {
showTooltip();
}
</script>

<style scoped>
@keyframes bounce {
40% {
transform: scale(1.2);
}
80% {
transform: scale(0.8);
}
100% {
transform: scale(1);
}
}
.fade-enter-active,
.fade-leave-active {
animation: bounce 350ms;
}
.fade-enter,
.fade-leave-to {
transform: scale(1);
}
</style>
1 change: 1 addition & 0 deletions frontend_vue/src/components/base/BaseLabelArrow.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<!-- eslint-disable vue/no-v-html -->
<template>
<BaseLabel
v-bind="$attrs"
:id="id"
class="container relative mb-8"
>
Expand Down
132 changes: 131 additions & 1 deletion frontend_vue/src/components/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const TOKENS_TYPE = {
PWA: 'pwa',
CREDIT_CARD_V2: 'credit_card_v2',
WEBDAV: 'webdav',
IDP_APP: 'idp_app',
};

// unique keys to use in the frontend
Expand Down Expand Up @@ -158,5 +159,134 @@ export const TOKEN_COLOR_PALETTES: { [key: string]: Array<string> } = {
cc: ['#C6C7C7', '#E3E5E7', '#38897F', '#38D47F', '#414241'],
pwa: ['#1AABEE', '#026696', '#9CE5FD'],
credit_card_v2: ['#C6C7C7', '#E3E5E7', '#38897F', '#38D47F', '#414241'],
windows_fake_fs: ['#2DCA6E', '#93EE7C', '#A2EAC1', '#D2FAC4', '#43CC5F']
windows_fake_fs: ['#2DCA6E', '#93EE7C', '#A2EAC1', '#D2FAC4', '#43CC5F'],
idp_app: ['#1AABEE', '#026696', '#9CE5FD'],
};


export const IDP_OPTIONS: { value: string; label: string }[]= [
{
value: 'gmail',
label: 'Gmail'
},
{
value: 'outlook',
label: 'Outlook'
},
{
value: 'gdrive',
label: 'Google Drive'
},
{
value: 'onedrive',
label: 'OneDrive'
},
{
value: 'aws',
label: 'AWS'
},
{
value: 'azure',
label: 'Azure'
},
{
value: 'gcloud',
label: 'Google Cloud'
},
{
value: 'zoho',
label: 'Zoho'
},
{
value: 'salesforce',
label: 'Salesforce'
},
{
value: 'zendesk',
label: 'Zendesk'
},
{
value: 'freshbooks',
label: 'Freshbooks'
},
{
value: 'elasticsearch',
label: 'Elasticsearch'
},
{
value: 'kibana',
label: 'Kibana'
},
{
value: 'onepassword',
label: '1Password'
},
{
value: 'lastpass',
label: 'LastPass'
},
{
value: 'bitwarden',
label: 'Bitwarden'
},
{
value: 'sap',
label: 'SAP'
},
{
value: 'jira',
label: 'Jira'
},
{
value: 'jamf',
label: 'JAMF'
},
{
value: 'duo',
label: 'Duo'
},
{
value: 'intune',
label: 'Intune'
},
{
value: 'zoom',
label: 'Zoom'
},
{
value: 'dropbox',
label: 'Dropbox'
},
{
value: 'github',
label: 'GitHub'
},
{
value: 'slack',
label: 'Slack'
},
{
value: 'msteams',
label: 'MS Teams'
},
{
value: 'ms365',
label: 'Microsoft 365'
},
{
value: 'gitlab',
label: 'GitLab'
},
{
value: 'pagerduty',
label: 'PagerDuty'
},
{
value: 'sage',
label: 'Sage'
},
{
value: 'virtru',
label: 'Virtru'
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<BaseFormTextField
id="redirect_url"
type="text"
placeholder="Redirect URL"
placeholder="https://www.example.com"
label="Redirect URL"
full-width
required
Expand Down
28 changes: 28 additions & 0 deletions frontend_vue/src/components/tokens/idp_app/ActivatedToken.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<template>
<TokenDisplay
:token-url="tokenUrl"
:entity-id="entityId"
:app-type="appType"
/>
<p class="mt-16 text-sm">
When the fake app is opened from your IdP dashboard you receive an alert.
<ButtonActivateTokenTips @how-to-use="$emit('howToUse')" />
</p>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import TokenDisplay from './TokenDisplay.vue';
import type { NewTokenBackendType } from '@/components/tokens/types';
import ButtonActivateTokenTips from '@/components/ui/ButtonActivateTokenTips.vue';
const props = defineProps<{
tokenData: NewTokenBackendType;
}>();
defineEmits(['howToUse']);
const tokenUrl = ref(props.tokenData.token_url || '');
const entityId = ref(props.tokenData.entity_id || '');
const appType = ref(props.tokenData.app_type || '');
</script>
70 changes: 70 additions & 0 deletions frontend_vue/src/components/tokens/idp_app/GenerateTokenForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<template>
<BaseGenerateTokenSettings setting-type="Canarytoken">
<div class="flex flex-col gap-8">
<BaseFormSelect
id="app_type"
label="The App I want my Canarytoken to look like"
placeholder="Select an app"
required
:options="IDP_OPTIONS"
:searchable="true"
height="220px"
@select-option="handleSelectedApp"
>
<template #option="{ option }">
<div class="flex flex-row items-center gap-16">
<div
alt="icon"
:style="{
backgroundImage: `url(${getImageUrl('idp_icons/' + option.value + '.png')})`,
}"
class="bg-cover w-[2rem] h-[2rem] duration-100"
></div>
{{ option.label }}
</div>
</template>

<template #selected-option="{ option }">
<div class="flex flex-row items-center gap-8">
<div
alt="icon"
:style="{
backgroundImage: `url(${getImageUrl('idp_icons/' + option.value + '.png')})`,
}"
class="bg-cover w-[1.5rem] h-[1.5rem] duration-100"
></div>
{{ option.label }}
</div>
</template>
</BaseFormSelect>
<BaseFormTextField
id="redirect_url"
type="text"
label="Send the user to this URL on login (Optional)"
placeholder="https://www.example.com"
full-width
/>
</div>
</BaseGenerateTokenSettings>
<GenerateTokenSettingsNotifications
memo-helper-example="Fake Salesforce app in Okta"
/>
</template>

<script setup lang="ts">
import GenerateTokenSettingsNotifications from '@/components/ui/GenerateTokenSettingsNotifications.vue';
import getImageUrl from '@/utils/getImageUrl';
import { IDP_OPTIONS } from '@/components/constants';
import { ref } from 'vue';
type SelectedAppType = {
value: string;
label: string;
};
const selectedApp = ref<SelectedAppType>();
function handleSelectedApp(selected: string) {
selectedApp.value = IDP_OPTIONS.find((o) => o.value === selected);
}
</script>
Loading

0 comments on commit 29817b0

Please sign in to comment.