create account

Work in Progress: A Simple Flask App for Hive Keychain Login by thecrazygm

View this thread on: hive.blogpeakd.comecency.com
· @thecrazygm · (edited)
$10.58
Work in Progress: A Simple Flask App for Hive Keychain Login
Hey everyone,

Today I wanted to share something I've been tinkering with – a very early, crude, and simple Flask application designed to handle a Hive Keychain login using a posting key signature. This is definitely a work in progress, but I thought I'd put it out there for anyone interested.

The project is called **`flask_keychain`** and the idea is to provide a basic backend that can:

1.  Receive a login request from a frontend that uses Hive Keychain to sign a message.
2.  Verify the signature against the user's posting key.
3.  If valid, issue a simple session token.

### How It Works (The Gist)

The system involves a simple HTML frontend that uses JavaScript to interact with the Hive Keychain browser extension, and a Python Flask backend to verify the signed message.

1.  **Frontend (JavaScript & Keychain):**

    - When you enter your username and click "Login," the JavaScript captures the username.
    - It then calls `window.hive_keychain.requestSignBuffer()`. This prompts Hive Keychain to ask you to sign a message (in this basic example, it's the current UTC date/time string) using the posting key of the entered username.
    - If you approve in Keychain, the extension returns the signature (`response.result`) and the public posting key (`response.publicKey`) that was used.
    - The JavaScript then sends your `username`, the `signature` (as "challenge"), the `publicKey`, and the original `message` (as "proof") to the Flask backend's `/login` endpoint.

    Here's the core JavaScript that handles the Keychain interaction and the call to the backend:

    ```javascript
    function getCurrentUTCDateTime() {
      const now = new Date();
      return now.toISOString();
    }
    document
      .getElementById("loginForm")
      .addEventListener("submit", function (e) {
        e.preventDefault();
        const username = document.getElementById("username").value.trim();
        const status = document.getElementById("status");
        status.textContent = "";
        if (!username) {
          status.textContent = "Please enter your Hive username.";
          return;
        }
        if (typeof window.hive_keychain === "undefined") {
          status.textContent = "Hive Keychain extension not detected!";
          return;
        }
        const datetimeToSign = getCurrentUTCDateTime(); // This will be our message
        window.hive_keychain.requestSignBuffer(
          username,
          datetimeToSign, // Message to sign
          "Posting", // Key type
          function (response) {
            if (response.success) {
              status.textContent = "Posting signed! Sending to API...";
              const signature = response.result;
              const pubkey =
                response.publicKey ||
                (response.data && response.data.publicKey) ||
                null;
              if (!pubkey) {
                status.textContent =
                  "Could not retrieve public key from Keychain response.";
                return;
              }
              const payload = {
                challenge: signature, // The signature from Keychain
                username: username,
                pubkey: pubkey, // The public key Keychain used
                proof: datetimeToSign, // The original message that was signed
              };
              fetch("/login", {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify(payload),
              })
                .then((r) => r.json())
                .then((data) => {
                  if (data.success) {
                    let msg = "Login successful! <br>";
                    if (data.token) {
                      localStorage.setItem("token", data.token);
                      msg += ` Token: <code>${data.token}</code> <br>`;
                    }
                    status.innerHTML = msg;
                  } else {
                    status.textContent = data.error || "Login failed.";
                  }
                })
                .catch((err) => {
                  status.textContent = "API error: " + err;
                });
            } else {
              status.textContent = "Keychain signature failed.";
            }
          },
        );
      });
    ```

2.  **Backend (Python Flask & `hive-nectar`):**

    - The `/login` route in Flask receives the `username`, `signature` (referred to as "challenge" from the frontend), `publicKey`, and original `message` (referred to as "proof" from the frontend).
    - It fetches the actual posting keys for the provided `username` from the Hive blockchain using `hive-nectar`.
    - It verifies that the `publicKey` sent by the client is indeed one of the account's valid posting keys.
    - It then uses `nectar-graphenebase`'s (a component of `hive-nectar`) `verify_message` function to check if the `signature` is valid for the given `message` and `publicKey`.
    - If everything checks out, it generates a secure random session token (using `secrets.token_urlsafe`) and sends it back to the client.

    Here’s the key Python snippet from `app.py` for the verification:

    ```python
    # (Previous steps: get data from request, fetch account's posting keys)
    # 'message' is what Keychain signed (datetimeToSign from JS, sent as 'proof')
    # 'signature' is the hex string from Keychain (sent as 'challenge' from JS)
    # 'pubkey' is the public key Keychain reported using for signing

    # Check that provided pubkey is one of the account's actual posting keys
    if pubkey not in posting_keys:
        return jsonify({
            "success": False,
            "error": "Provided public key is not a valid posting key for this account.",
        }), 400

    # Verify signature
    try:
        recovered_pubkey_bytes = verify_message(message, bytes.fromhex(signature))
        recovered_pubkey_str = str(PublicKey(recovered_pubkey_bytes.hex(), prefix="STM"))
        valid = recovered_pubkey_str == pubkey
    except Exception as e:
        return jsonify({"success": False, "error": f"Signature verification error: {str(e)}"}), 400

    if not valid:
        return jsonify({"success": False, "error": "Signature is invalid."}), 401

    # Success: generate and return a session token
    token = secrets.token_urlsafe(32)
    sessions[token] = username # Simple in-memory store for this example
    return jsonify({"success": True, "username": username, "token": token})
    ```

This frontend/backend interaction provides a basic but functional way to authenticate a Hive user via their posting key.

### The Basic Frontend

I've included a super simple HTML template (`login.html`) that just provides a basic login button which uses the JavaScript above to trigger the Keychain signature request and send it to the Flask backend. If successful, it just displays the token.


![The very basic login page showing a successful token response.](https://files.peakd.com/file/peakd-hive/thecrazygm/23tcNzkBHWoSx2bMstmRU7wz4j6b9qFkjFAqwvzM9zTXaE88bPt36DEcMNP4nQhTAp4Eq.png)


### Where to Find It

This is very much a proof-of-concept and a starting point. If you're interested in playing around with it or seeing the basic structure, you can find the code on GitHub:
[https://github.com/TheCrazyGM/flask_keychain](https://github.com/TheCrazyGM/flask_keychain)

It's not meant to be a production-ready solution as-is, but more of a demonstration of how one might start building a Flask backend for Hive Keychain posting key logins. Maybe it'll be useful to someone looking to integrate Hive login into their Python web projects!

**EDIT**: I would like to give a shoutout to @sagarkothari88 who made the distriator api login, which inspired this idea.

As always,
Michael Garcia a.k.a. TheCrazyGM
πŸ‘  , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , and 129 others
properties (23)
authorthecrazygm
permlinkwork-in-progress-a-simple-flask-app-for-hive-keychain-login
categoryhive-186392
json_metadata{"app":"peakd/2025.5.7","format":"markdown","image":["https://files.peakd.com/file/peakd-hive/thecrazygm/23tcNzkBHWoSx2bMstmRU7wz4j6b9qFkjFAqwvzM9zTXaE88bPt36DEcMNP4nQhTAp4Eq.png"],"tags":["dev","tribes","archon","proofofbrain","pimp"],"users":["sagarkothari88"]}
created2025-05-24 14:30:15
last_update2025-05-24 14:38:15
depth0
children9
last_payout2025-05-31 14:30:15
cashout_time1969-12-31 23:59:59
total_payout_value4.871 HBD
curator_payout_value5.708 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length7,825
author_reputation76,652,371,980,122
root_title"Work in Progress: A Simple Flask App for Hive Keychain Login"
beneficiaries
0.
accountthecrazygm.bank
weight1,500
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id142,939,094
net_rshares32,409,733,149,847
author_curate_reward""
vote details (193)
@borniet ·
$0.18
Doing the same thing for https://hiveearnings.botlord.eu/ using flask, signin via Hive Keychain. It’s not really needed yet (no info there yet that requires login), but wanted to give it a try as well, and will need it in the future. 

!HOPE
!PIZZA
!INDEED
!ALIVE
!BBH
!STRIDE
!WEIRD
!DUO
!PIMP
πŸ‘  , , , , , ,
properties (23)
authorborniet
permlinkre-thecrazygm-2025524t165451837z
categoryhive-186392
json_metadata{"type":"comment","tags":["hive-186392","dev","tribes","archon","proofofbrain","pimp"],"app":"ecency/3.3.2-mobile","format":"markdown+html"}
created2025-05-24 14:54:51
last_update2025-05-24 14:54:51
depth1
children6
last_payout2025-05-31 14:54:51
cashout_time1969-12-31 23:59:59
total_payout_value0.088 HBD
curator_payout_value0.088 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length294
author_reputation208,628,005,227,457
root_title"Work in Progress: A Simple Flask App for Hive Keychain Login"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id142,939,413
net_rshares508,028,286,935
author_curate_reward""
vote details (7)
@duo-tip ·
<center>
<sup>You just got DUO from @borniet.</sup>
<sup>They have <b>1/1</b> <b>DUO</b> calls left.</sup>
<hr>
<img src="https://files.peakd.com/file/peakd-hive/theguruasia/AK7w4BMNZVvSFUnu5EpdemZruiGCM55HjfyKSjZHwYZUDrTBPBRKJXjbn5yEGHs.png" alt="duo_logo">
<hr>
<sup>Learn all about <a href="https://peakd.com/pimp/@hive-193566/duo-white-paper">DUO here.</a></sup>
</center>
properties (22)
authorduo-tip
permlink20250524t145502446z
categoryhive-186392
json_metadata{"tags":["dook","tokendook","dookbot"],"app":"dook-bot/4.0","format":"markdown"}
created2025-05-24 14:55:03
last_update2025-05-24 14:55:03
depth2
children0
last_payout2025-05-31 14:55:03
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length385
author_reputation69,070,314,803
root_title"Work in Progress: A Simple Flask App for Hive Keychain Login"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id142,939,416
net_rshares0
@thecrazygm · (edited)
$0.27
I have future use, which is why I looked into it, and while I was working on some tools making use of Distriator the other day, the api login / return token just kinda meshed with what I had in mind. And of course python is more my thing for the backend, so wanted to give it a shot using hive-nectar (which also added to my knowledge how the cryptography works in it, as it still needs some work there too.)
πŸ‘  , , , , , , , ,
properties (23)
authorthecrazygm
permlinkre-borniet-swrtpo
categoryhive-186392
json_metadata{"app":"peakd/2025.5.7","tags":["hive-186392"]}
created2025-05-24 15:01:03
last_update2025-05-25 12:26:27
depth2
children4
last_payout2025-05-31 15:01:03
cashout_time1969-12-31 23:59:59
total_payout_value0.138 HBD
curator_payout_value0.136 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length408
author_reputation76,652,371,980,122
root_title"Work in Progress: A Simple Flask App for Hive Keychain Login"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id142,939,505
net_rshares787,575,469,800
author_curate_reward""
vote details (9)
@borniet ·
$0.19
Tell me more about Distriator!!! ;-) Sounds interesting! 
BTW: I’ve recently switched the HiveEarnings tool too the Hive-Nectar lib as well! Still want to do a post about it too ;-)

!HOPE
!PIZZA
!INDEED
!ALIVE
!BBH
!STRIDE
!WEIRD
πŸ‘  , , , , , , , , , ,
properties (23)
authorborniet
permlinkre-thecrazygm-2025527t7159894z
categoryhive-186392
json_metadata{"type":"comment","tags":["hive-186392"],"app":"ecency/3.3.2-mobile","format":"markdown+html"}
created2025-05-27 05:02:00
last_update2025-05-27 05:02:00
depth3
children2
last_payout2025-06-03 05:02:00
cashout_time1969-12-31 23:59:59
total_payout_value0.094 HBD
curator_payout_value0.092 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length230
author_reputation208,628,005,227,457
root_title"Work in Progress: A Simple Flask App for Hive Keychain Login"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id142,987,645
net_rshares602,335,754,793
author_curate_reward""
vote details (11)
@ecoinstant ·
$0.02
Tap into Distriator!

!PIMP
!PIZZA
πŸ‘  ,
properties (23)
authorecoinstant
permlinkre-thecrazygm-swsr2o
categoryhive-186392
json_metadata{"tags":["hive-186392"],"app":"peakd/2025.5.7"}
created2025-05-25 03:01:39
last_update2025-05-25 03:01:39
depth3
children0
last_payout2025-06-01 03:01:39
cashout_time1969-12-31 23:59:59
total_payout_value0.012 HBD
curator_payout_value0.012 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length34
author_reputation824,628,195,171,790
root_title"Work in Progress: A Simple Flask App for Hive Keychain Login"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id142,949,065
net_rshares74,555,003,382
author_curate_reward""
vote details (2)
@pizzabot · (edited)
RE: Work in Progress: A Simple Flask App for Hive Keychain Login
<center>PIZZA!


$PIZZA slices delivered:
@borniet<sub>(4/15)</sub> tipped @thecrazygm (x2)
ecoinstant tipped thecrazygm 


<sub>Come get [MOON](https://moon.hive.pizza)ed!</sub></center>
properties (22)
authorpizzabot
permlinkre-work-in-progress-a-simple-flask-app-for-hive-keychain-login-20250524t145515z
categoryhive-186392
json_metadata"{"app": "pizzabot"}"
created2025-05-24 14:55:15
last_update2025-05-27 05:02:21
depth1
children0
last_payout2025-05-31 14:55:15
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length187
author_reputation7,429,613,346,379
root_title"Work in Progress: A Simple Flask App for Hive Keychain Login"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id142,939,421
net_rshares0
@tydynrain ·
$0.17
Given that I don't (*yet*) know what a flask app is, I don't have much to say on this tool yet, other than it sounds like it would be very useful. 😁 πŸ™ πŸ’š ✨ πŸ€™ 
πŸ‘  , , , , ,
properties (23)
authortydynrain
permlinkre-thecrazygm-2025524t21912177z
categoryhive-186392
json_metadata{"links":[],"type":"comment","tags":["hive-186392","dev","tribes","archon","proofofbrain","pimp"],"app":"ecency/3.3.3-mobile","format":"markdown+html"}
created2025-05-25 07:09:15
last_update2025-05-25 07:09:15
depth1
children0
last_payout2025-06-01 07:09:15
cashout_time1969-12-31 23:59:59
total_payout_value0.084 HBD
curator_payout_value0.083 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length157
author_reputation198,516,680,396,764
root_title"Work in Progress: A Simple Flask App for Hive Keychain Login"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id142,951,479
net_rshares509,338,737,764
author_curate_reward""
vote details (6)