Skip to content
This repository was archived by the owner on Jul 10, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions examples/python-flask/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,68 @@ $ poetry install
```bash
$ poetry run main
```

## Step-By-Step

First, open your browser on the selected host (default is http://localhost:5001)

<b>Note: This flask exemple creates a DID by default in key.jwk</b>

From there, you should see 4 options available:

1. Issue Verifiable Credential
2. Verify Verifiable Credential
3. Issue Verifiable Presentation
4. Verify Verifiable Presentation

### Issue a Verifiable Credential (VC)
The first step should be to generate a Verifiable Credential. To understand better
what a VC is, please refer to SpruceID Glossary [here](https://www.spruceid.dev/references/glossary#verifiable-credentials-vcs)

In order to simplify this example, there are only 2 ways to issue a VC:

1. Read a QRcode via Credible
2. Get server issued credential

On a real case scenario, a unsigned credential would be required so DIDKit can sign it.
One can refer to this in the quickstart example [here](https://www.spruceid.dev/quickstart)

The issued VC will be presented in JSON format. Store this value for later use.

### Verify a Verifiable Credential (VC)
After successfully issuing a VC, the next step should be to verify it.

Copy and paste the issued VC from the first step and click on the button to verify it.
The default response should be:
```json
{
"checks":["proof"],
"errors":[],
"warnings":[]
}
```
This means the given VC is valid.

### Issue a Verifiable Presentation (VP)
Now, one can use the valid VC to generate a Verifiable Presentation. To understand better
what a VP is, please refer to W3C exemple [here](https://www.w3.org/TR/vc-data-model-2.0/#dfn-verifiable-presentation)

<b>Note: in very brief terms, a VP can contain cherry-picked information from the original VC
in order to preserve sensitive/unwanted verifiable information </b>

To generate a VP using DIDKit, 3 variables are needed:
1. The unsigned VP
2. A valid VC
3. The VC holder identifier (in this example, a DID:key)

One can refer to this in the CLI example [here](https://www.spruceid.dev/didkit/didkit-examples/core-functions-cli#create-a-verifiable-presentation-that-embeds-the-verifiable-credential)

The default response should be:
```json
{
"checks":["proof"],
"errors":[],
"warnings":[]
}
```
This means the given VP is valid.
9 changes: 9 additions & 0 deletions examples/python-flask/didkit_flask/issue_credential.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@


async def req_issue_vc(request):
"""Issues a Verifiable VC using SpruceID DIDKit
Args:
request (flask.Request): Flask API request containing
None (Issue via server) or
QRcode url

Returns:
Dict: Generated VC from DIDKit issue_credential
"""
with open("key.jwk", "r") as f:
key = f.readline()
f.close()
Expand Down
35 changes: 35 additions & 0 deletions examples/python-flask/didkit_flask/issue_presentation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

from didkit import issue_presentation, key_to_verification_method
import json


async def issue_vp_credential(request):
"""Issue a VP credential using SpruceID DIDKit

Args:
request (flask.Request): Flask API request containing:
Unsigned VP,
Signed VC,
Holder info

Returns:
Dict: Python dict containing a valid DIDKit VP
"""
with open("key.jwk", "r") as f:
key = f.readline()
f.close()
verification_method = await key_to_verification_method("key", key)
didkit_options = {
"proofPurpose": "assertionMethod",
"verificationMethod": verification_method,
}
vp = json.loads(request.form.get("input_vp"))
vc = json.loads(request.form.get("input_vc"))
holder = request.form.get("holder")

vp["verifiableCredential"] = vc
vp["holder"] = holder

presentation = await issue_presentation(json.dumps(vp),
json.dumps(didkit_options), key)
return json.loads(presentation)
42 changes: 40 additions & 2 deletions examples/python-flask/didkit_flask/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
from flask_qrcode import QRcode

from didkit_flask.issue_credential import req_issue_vc
from didkit_flask.verify_credential import verify_vc_credential
from didkit_flask.issue_presentation import issue_vp_credential
from didkit_flask.verify_presentation import verify_vp_credential

app = Flask(__name__)
qrcode = QRcode(app)
Expand Down Expand Up @@ -37,7 +40,9 @@ def index():

@app.route("/credential", methods=["GET", "POST"])
async def credential():
credential = json.dumps(await req_issue_vc(request), indent=2, sort_keys=True)
credential = json.dumps(await req_issue_vc(request),
indent=2,
sort_keys=True)

return render_template("credential.html", credential=credential)

Expand All @@ -46,11 +51,44 @@ async def credential():
async def wallet():
credential = await req_issue_vc(request)
if request.method == "GET":
return jsonify({"type": "CredentialOffer", "credentialPreview": credential})
return jsonify({"type": "CredentialOffer",
"credentialPreview": credential})
elif request.method == "POST":
return jsonify(credential)


@app.route("/issue_vc", methods=["GET"])
async def issue_vc():
return render_template("issue_vc.html")


@app.route("/verify_vc", methods=["GET", "POST"])
async def verify_vc():
if request.method == "GET":
return render_template("verify_vc.html")
elif request.method == "POST":
validation = await verify_vc_credential(request)
return jsonify(validation)


@app.route("/issue_vp", methods=["GET", "POST"])
async def issue_vp():
if request.method == "GET":
return render_template("issue_vp.html")
elif request.method == "POST":
presentation = await issue_vp_credential(request)
return jsonify(presentation)


@app.route("/verify_vp", methods=["GET", "POST"])
async def verify_vp():
if request.method == "GET":
return render_template("verify_vp.html")
elif request.method == "POST":
presentation = await verify_vp_credential(request)
return jsonify(presentation)


def main():
flags = os.O_CREAT | os.O_EXCL | os.O_WRONLY
try:
Expand Down
54 changes: 33 additions & 21 deletions examples/python-flask/didkit_flask/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,40 @@
<head>
<meta charset="utf-8">
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<title>DIDKit Django</title>
<title>DIDKit Flask</title>
</head>
<body class="flex flex-col items-center justify-center h-screen w-screen">
<form class="flex items-center justify-center mb-4" method="post" action="/credential">
<input type="text" placeholder="Enter your DID:" class="h-12 p-4 border border-blue-900 rounded mr-4" name="subject_id" />
<button
class="h-12 p-2 border border-blue-900 rounded"
type="submit"
>
Get credential
</button>
</form>
<p>or scan the QRCode bellow with your wallet. i.e: Credible</p>
<div class="my-8"><img src={{ qrcode(url) }} class="w-32 h-32"></div>
<p>or</p>
<a href="/credential">
<button
class="h-12 p-2 border mt-6 border-blue-900 rounded"
type="submit"
>
Get server issued credential
</button>
</a>
<form class="flex items-center justify-center mb-4" method="get" action="/issue_vc">
<button
class="h-12 p-2 border border-blue-900 rounded"
type="submit"
>
Issue Verifiable Credential
</button>
</form>
<form class="flex items-center justify-center mb-4" method="get" action="/verify_vc">
<button
class="h-12 p-2 border border-blue-900 rounded"
type="submit"
>
Verify Verifiable Credential
</button>
</form>
<form class="flex items-center justify-center mb-4" method="get" action="/issue_vp">
<button
class="h-12 p-2 border border-blue-900 rounded"
type="submit"
>
Issue Verifiable Presentation
</button>
</form>
<form class="flex items-center justify-center mb-4" method="get" action="/verify_vp">
<button
class="h-12 p-2 border border-blue-900 rounded"
type="submit"
>
Verify Verifiable Presentation
</button>
</form>
</body>
</html>
21 changes: 21 additions & 0 deletions examples/python-flask/didkit_flask/templates/issue_vc.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<title>DIDKit Flask</title>
</head>
<body class="flex flex-col items-center justify-center h-screen w-screen">
<p>Scan the QRCode bellow with your wallet. i.e: Credible</p>
<div class="my-8"><img src={{ qrcode(url) }} class="w-32 h-32"></div>
<p>or</p>
<a href="/credential">
<button
class="h-12 p-2 border mt-6 border-blue-900 rounded"
type="submit"
>
Get server issued credential
</button>
</a>
</body>
</html>
23 changes: 23 additions & 0 deletions examples/python-flask/didkit_flask/templates/issue_vp.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<title>DIDKit Flask</title>
</head>
<body class="flex flex-col items-center justify-center h-screen w-screen">
<p>Now that we have a verified VC, let`s issue a verifiable VP!</p>
<p>Tip: refer to the oficial SpruceID docs <a href=https://www.spruceid.dev/didkit/didkit-examples/core-functions-cli#create-a-verifiable-presentation-that-embeds-the-verifiable-credential style="color:blue;">here</a> for detailed info</p>
<form class="flex items-center justify-center mb-4" method="post" action="/issue_vp">
<input type="text" placeholder="Enter your Verifiable Presentation:" class="h-24 p-16 border border-blue-900 rounded mr-4" name="input_vp" />
<input type="text" placeholder="Enter your Verifiable Credential:" class="h-24 p-16 border border-blue-900 rounded mr-4" name="input_vc" />
<input type="text" placeholder="Enter your Holder value:" class="h-24 p-16 border border-blue-900 rounded mr-4" name="holder" />
<button
class="h-12 p-2 border border-blue-900 rounded"
type="submit"
>
Verify Presentation
</button>
</form>
</body>
</html>
21 changes: 21 additions & 0 deletions examples/python-flask/didkit_flask/templates/verify_vc.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<title>DIDKit Flask</title>
</head>
<body class="flex flex-col items-center justify-center h-screen w-screen">
<p>Paste your issued VC here to validate it!</p>
<p>Tip: Try modifing some lines of your VC to see how DIDKit reacts!</p>
<form class="flex items-center justify-center mb-4" method="post" action="/verify_vc">
<input type="text" placeholder="Enter your credential:" class="h-24 p-8 border border-blue-900 rounded mr-4" name="input_credential" />
<button
class="h-12 p-2 border border-blue-900 rounded"
type="submit"
>
Verify Credential
</button>
</form>
</body>
</html>
21 changes: 21 additions & 0 deletions examples/python-flask/didkit_flask/templates/verify_vp.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<title>DIDKit Flask</title>
</head>
<body class="flex flex-col items-center justify-center h-screen w-screen">
<p>Paste your issued VP here to validate it!</p>
<p>Tip: Try modifing some lines of your VP to see how DIDKit reacts!</p>
<form class="flex items-center justify-center mb-4" method="post" action="/verify_vp">
<input type="text" placeholder="Enter your credential:" class="h-24 p-8 border border-blue-900 rounded mr-4" name="input_vp" />
<button
class="h-12 p-2 border border-blue-900 rounded"
type="submit"
>
Verify Presentation
</button>
</form>
</body>
</html>
30 changes: 30 additions & 0 deletions examples/python-flask/didkit_flask/verify_credential.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import json
from didkit import verify_credential, key_to_verification_method


async def verify_vc_credential(request):
"""Verifies a generated VC using
SpruceID DIDKit

Args:
request (flask.Request): flask API request containing
the issued VC to be Verifiable

Returns:
Dict: DIDKit verification response in Python dict format
"""
# Access the server-generated jwk key
with open("key.jwk", "r") as f:
key = f.readline()
f.close()
# Generate a verification method using the jwk key
verification_method = await key_to_verification_method("key", key)
# Generate the proof options so we can verify the VC
didkit_options = {
"proofPurpose": "assertionMethod",
"verificationMethod": verification_method,
}
# Verify the credential using SpruceID DIDKit library
credential = await verify_credential(request.form.get('input_credential'),
json.dumps(didkit_options))
return json.loads(credential)
Loading