24 September 2025
Sharokey enables creating self-destructing links to share credentials securely directly from your Jira tickets. This temporary secure sharing solution integrates seamlessly into your existing workflows.
// ==UserScript==
// @name Jira Sharokey Integration
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Sharokey integration for secure credential sharing
// @author Sharokey
// @match https://*.atlassian.net/*
// @match https://*/jira/*
// @grant none
// @require https://cdn.jsdelivr.net/gh/Sharokey/sharokey-cdn@latest/sharokey.js
// ==/UserScript==
(function() {
'use strict';
// Configuration - Replace with your Sharokey API token
const SHAROKEY_TOKEN = 'sk_live_YOUR_API_TOKEN';
// Sharokey configuration
if (typeof Sharokey !== 'undefined') {
Sharokey.config({token: SHAROKEY_TOKEN});
}
function getTicketInfo() {
const ticketKey = document.querySelector('[data-testid="issue.views.issue-base.foundation.breadcrumbs.current-issue.item"]')?.textContent?.trim()
|| document.querySelector('#key-val')?.textContent?.trim()
|| window.location.pathname.match(/([A-Z]+-\\\\d+)/)?.[1]
|| 'TICKET';
const ticketTitle = document.querySelector('[data-testid="issue.views.issue-base.foundation.summary.heading"]')?.textContent?.trim()
|| document.querySelector('#summary-val')?.textContent?.trim()
|| 'Support request';
return { key: ticketKey, title: ticketTitle };
}
function showSecretForm() {
return new Promise((resolve, reject) => {
const modal = document.createElement('div');
modal.innerHTML = \`
<div style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:10000;display:flex;justify-content:center;align-items:center;font-family:Arial,sans-serif;">
<div style="background:white;padding:30px;border-radius:8px;max-width:500px;width:90%;">
<h2 style="margin-top:0;color:#0052CC;">Create secure access</h2>
<form id="secretForm">
<div style="margin-bottom:15px;">
<label style="display:block;margin-bottom:5px;font-weight:bold;">Secret content:</label>
<textarea id="secretContent" required style="width:100%;height:150px;padding:8px;border:1px solid #ddd;border-radius:4px;resize:vertical;" placeholder="Enter credentials, passwords, or information to share securely..."></textarea>
</div>
<div style="margin-bottom:20px;">
<label style="display:block;margin-bottom:5px;font-weight:bold;">Instructions (optional):</label>
<input type="text" id="instructions" style="width:100%;padding:8px;border:1px solid #ddd;border-radius:4px;" placeholder="Usage instructions">
</div>
<div>
<button type="submit" style="background:#0052CC;color:white;border:none;padding:12px 20px;border-radius:4px;cursor:pointer;margin-right:10px;">Create secret</button>
<button type="button" id="cancelBtn" style="background:#666;color:white;border:none;padding:12px 20px;border-radius:4px;cursor:pointer;">Cancel</button>
</div>
</form>
</div>
</div>
\`;
document.body.appendChild(modal);
document.getElementById('secretContent').focus();
document.getElementById('secretForm').onsubmit = function(e) {
e.preventDefault();
const content = document.getElementById('secretContent').value.trim();
const instructions = document.getElementById('instructions').value.trim();
if (!content) {
alert('Secret content is required');
return;
}
document.body.removeChild(modal);
resolve({ content, instructions });
};
document.getElementById('cancelBtn').onclick = function() {
document.body.removeChild(modal);
reject(new Error('Cancelled'));
};
});
}
async function createSecret(ticketInfo, secretData) {
let content = \`Ticket: \${ticketInfo.key}
Context: \${ticketInfo.title}
\${secretData.content}\`;
if (secretData.instructions) {
content += \`\\n\\nInstructions: \${secretData.instructions}\`;
}
const secret = await Sharokey.create(content, 24, 2, {
description: \`Temporary access - \${ticketInfo.key}\`
});
return secret;
}
function showResult(shareUrl, ticketKey) {
const modal = document.createElement('div');
modal.innerHTML = \`
<div style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:10000;display:flex;justify-content:center;align-items:center;font-family:Arial,sans-serif;">
<div style="background:white;padding:30px;border-radius:8px;max-width:500px;">
<h2 style="color:#0052CC;margin-top:0;">Secret created successfully</h2>
<p><strong>Ticket:</strong> \${ticketKey}</p>
<p><strong>Secure link:</strong></p>
<div style="background:#f4f5f7;padding:15px;border-radius:4px;word-break:break-all;font-family:monospace;border:1px solid #ddd;">\${shareUrl}</div>
<div style="margin-top:20px;">
<button id="copyBtn" style="background:#0052CC;color:white;border:none;padding:10px 20px;border-radius:4px;cursor:pointer;margin-right:10px;">Copy link</button>
<button id="closeBtn" style="background:#666;color:white;border:none;padding:10px 20px;border-radius:4px;cursor:pointer;">Close</button>
</div>
<p style="font-size:12px;color:#666;margin-top:15px;">
Secret expires automatically<br>
Self-destructing link after viewing
</p>
</div>
</div>
\`;
document.body.appendChild(modal);
document.getElementById('copyBtn').onclick = function() {
navigator.clipboard.writeText(shareUrl).then(() => {
this.textContent = 'Copied!';
this.style.background = '#00C851';
setTimeout(() => {
this.textContent = 'Copy link';
this.style.background = '#0052CC';
}, 2000);
});
};
document.getElementById('closeBtn').onclick = function() {
document.body.removeChild(modal);
};
}
function createSharokeyButton() {
const ticketInfo = getTicketInfo();
if (!ticketInfo.key || ticketInfo.key === 'TICKET' || document.getElementById('sharokey-button')) {
return;
}
const targetElement = document.querySelector('[data-testid="issue.views.issue-base.foundation.summary.heading"]')
|| document.querySelector('#stalker')
|| document.querySelector('.aui-toolbar2-primary');
if (!targetElement) return;
const button = document.createElement('button');
button.id = 'sharokey-button';
button.innerHTML = '🔐 Create secure access';
button.style.cssText = \`
background:#0052CC;
color:white;
border:none;
padding:8px 16px;
border-radius:4px;
cursor:pointer;
font-size:14px;
margin-left:10px;
\`;
button.onclick = async function() {
if (SHAROKEY_TOKEN === 'sk_live_YOUR_API_TOKEN') {
alert('Please configure your Sharokey API token in the script');
return;
}
const originalText = this.innerHTML;
this.innerHTML = 'Creating...';
this.disabled = true;
try {
const secretData = await showSecretForm();
const result = await createSecret(getTicketInfo(), secretData);
showResult(result.share_url, getTicketInfo().key);
} catch (error) {
if (error.message !== 'Cancelled') {
alert('Error: ' + error.message);
}
} finally {
this.innerHTML = originalText;
this.disabled = false;
}
};
targetElement.appendChild(button);
}
function init() {
setTimeout(createSharokeyButton, 2000);
setInterval(createSharokeyButton, 5000);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
sk_live_YOUR_API_TOKEN
with your actual tokenIn the createSecret
function, modify the hours
parameter:
const secret = await Sharokey.create(content, 48, 1, { // Custom duration
Modify the URLs in the script header to match your environment:
// @match https://your-jira.company.com/*
const secret = await Sharokey.create(content, expiration, consultations, {
description: `Temporary access - ${ticketInfo.key}`,
captcha: true, // Add CAPTCHA
otpEmail: "[email protected]" // Two-factor authentication
});
The script uses multiple selectors to adapt to different Jira versions. If necessary, adjust the CSS selectors in the getTicketInfo()
function.
This Sharokey-Jira integration demonstrates how easily Sharokey can integrate into any existing web interface. The same principle can be applied to ServiceNow, Zendesk, Salesforce, or any other web platform your organization uses.
The UserScript approach presented here illustrates how to quickly transform any existing business workflow by adding secure sharing capabilities, without modifying the main application.
For more advanced needs, consult the Sharokey API documentation which offers more advanced integrations via Python, JavaScript and CLI SDKs.