Sharokey
Free service in beta version - Enjoy all features at no cost

Secure Password Sharing in Jira: Alternative to Traditional Password Managers

24 September 2025

Sharokey Integration with Jira

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.

Key Features

  • Self-destructing links: One-time access then automatic destruction
  • AES-256 encryption: Zero-knowledge, maximum data protection
  • Controlled temporary access: Configurable automatic expiration
  • Seamless integration: Directly within Jira interface
  • Web interface: No installation required

Prerequisites

Installation

Step 1: Installing Tampermonkey

  1. Install the extension from your browser's store:
  2. Enable the extension in your browser

Step 2: UserScript Configuration

  1. Click on the Tampermonkey icon then "Create a new script"
  2. Replace the default content with the following script:
// ==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();
    }
})();

Step 3: API Token Configuration

  1. Get your API token from your Sharokey account
  2. Replace sk_live_YOUR_API_TOKEN with your actual token
  3. Save the script (Ctrl+S)

Usage

Standard workflow

  1. Open a ticket in Jira
  2. Click on the "🔐 Create secure access" button
  3. Enter the secret content directly (credentials, passwords, etc.)
  4. Add instructions if necessary
  5. Click "Create secret"
  6. Copy the generated link and share it with the requester

Features

Customization

Modify expiration duration

In the createSecret function, modify the hours parameter:

const secret = await Sharokey.create(content, 48, 1, { // Custom duration

Adapt to your Jira instance

Modify the URLs in the script header to match your environment:

// @match        https://your-jira.company.com/*

Add security restrictions

const secret = await Sharokey.create(content, expiration, consultations, {
    description: `Temporary access - ${ticketInfo.key}`,
    captcha: true,  // Add CAPTCHA
    otpEmail: "[email protected]"  // Two-factor authentication
});

Troubleshooting

Button doesn't appear

Error when creating secret

Compatibility with different Jira versions

The script uses multiple selectors to adapt to different Jira versions. If necessary, adjust the CSS selectors in the getTicketInfo() function.

Security and best practices

API token protection

Secret management

Conclusion

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.