Python

This example provides a very simple partner application template based on Python (3 or higher). It helps you to understand the basic steps regarding application integration and how our authentication process works. It uses the pyjwt library for verifying/signing JWTs.

Setup

Beside python you might need pip to install additional dependencies. The following dependencies are required to run the code:

  • pyjwt
  • requests

JWT signature verification

In order to verify our JWT's signature based on our stages you will need to download these public key files and put them next to your code:

365FarmNet_Connect-API_public_key_development.pem

365FarmNet_Connect-API_public_key_production.pem

Code

Create a file index.py and put this code into it:

#!/usr/bin/python
from time import asctime
from http.server import BaseHTTPRequestHandler, HTTPServer

from urllib.parse import urlparse
import jwt
import requests
import json

PORT = 3000

PARTNER_ID = "5726c2cf-143b-4834-aa54-24a1c1516a48"
PARTNER_SECRET = "trsL26xTtFXgPHBJE8n4ZrN6R7fWfLrK"

PARTNER_HEADER = {
    "alg": "HS256",
    "ver": "0.1",
    "type": "partner"
}

PROD_STAGES = ["https://connect.365farmnet.com", "https://pp-connect.365farmnet.com"]


def read_jwt_from_path(path):
    query = urlparse(path).query
    query_params = dict(qc.split("=") for qc in query.split("&"))
    return query_params["jwt"]


def read_public_key(api_base):
    stage = "production" if api_base in PROD_STAGES else "development"
    with open("365FarmNet_Connect-API_public_key_%s.pem" % stage, "rb") as pem_file:
        return pem_file.read()


def create_partner_token(connect_token_jwt, connect_token):
    payload = {
        "con": connect_token_jwt,
        "exp": connect_token["exp"],
        "iss": PARTNER_ID,
        "iat": connect_token["iat"]
    }
    return jwt.encode(payload, PARTNER_SECRET, algorithm="HS256", headers=PARTNER_HEADER).decode()


def fetch_company_from_connect(partner_token_jwt, api_base):
    url = "%s/connect/v1/company" % api_base
    headers = {"Authorization": "Bearer %s" % partner_token_jwt}
    return requests.get(url, headers=headers)


class ExampleHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):

        connect_token_jwt = read_jwt_from_path(self.path)
        connect_token = jwt.decode(connect_token_jwt, verify=False)

        api_base = connect_token["fn-ext"]["apiBase"]

        jwt.decode(connect_token_jwt, read_public_key(api_base), options={"verify_aud": False})

        partner_token_jwt = create_partner_token(connect_token_jwt, connect_token)
        company = fetch_company_from_connect(partner_token_jwt, api_base).json()

        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        self.wfile.write(bytes(json.dumps(company), "UTF-8"))


if __name__ == "__main__":
    server = HTTPServer(("", PORT), ExampleHTTPRequestHandler)
    print(asctime(), "Server started - http://localhost:%s/" % (PORT))
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        print("^C received, shutting down the web server")
        server.socket.close()

Run

Open your terminal, install the dependencies and start the application by running python index.py. This will spawn a server listening for calls on port 3000. You can open your browser, navigate to localhost:3000 and should see an error in your console logs since your application did not receive a JWT. In this case the application stops running since it does not provide an advanced error handling yet.

Run the application again and navigate to our developer environment, register and set the URL to http://localhost:3000/ in our developer area. Since the example uses our developer credentials it should work out of the box and show your account information.