Skip to main content
Back to Projects
FeaturedNode.jsReact.jsFlutterAWSDigital Authorization

Digital Power of Attorney Platform

Danish digital power-of-attorney service at e-fuldmagt.dk. Sameem worked on it as an engineer at Zencloud: MitID sign-in through Criipto, generated PDF documents and a Danish/English interface.

Digital Power of Attorney Platform
MitID via Criipto
Identity
Generated PDFs
Documents
Danish / English
Languages
Zencloud
Engineer at

Facts about the build and who it was for. Any figure here is shown on a public store listing or site linked on this page — how we present portfolio work.

Project Story

The Challenge

Individuals face challenges in securely managing digital authorizations across various platforms, often lacking a unified system to streamline this process.

What Was Built

As an engineer at Zencloud, Sameem worked on MitID sign-in through Criipto (OIDC), PDF generation with PDF-Lib, a Danish/English interface, and Node.js REST APIs built to GDPR requirements, with document storage on AWS S3.

The Result

Live at e-fuldmagt.dk.

Project Details

e-fuldmagt is a Danish service for creating and managing digital powers of attorney. Sameem worked on it as an engineer at Zencloud: MitID identity verification through Criipto (OIDC), PDF documents generated from user input with PDF-Lib, a Danish and English interface with i18next, and Node.js and TypeScript REST APIs built to GDPR requirements, with documents stored on AWS S3. DevoraX holds no security certifications and has run no audits.

Tech Stack

Node.js
Express

Category

Node.js Backend & AWS
Written by DevoraXReviewed by Sameem Amjad, Founder & Lead Architect EngineerLast updated Based on project records and public sources (case study)

e-fuldmagt is a Danish digital power-of-attorney service: people create a power of attorney online or in its app, send it to the person who will act for them, get it signed, and can revoke it later. Sameem worked on it as an engineer at Zencloud. He integrated MitID identity verification through Criipto using OpenID Connect, generated the power-of-attorney PDF documents from user input with PDF-Lib, built the Danish and English interface with i18next, and worked on REST APIs built to GDPR requirements. The service is live at e-fuldmagt.dk.

What you can check

  • Live site: e-fuldmagt.dk (Danish), with an English version at e-fuldmagt.dk/en
  • The site describes creating, sending, signing and revoking powers of attorney online or in the e-fuldmagt app

Each item points to something public: a store listing, a live site or a demo build. See our terms for how we present portfolio results.

What is e-fuldmagt, and what did Sameem work on?

e-fuldmagt is a Danish service for managing powers of attorney digitally. Its site, e-fuldmagt.dk, offers postal and enduring powers of attorney and describes the process as: choose the type and add your details, send it to the person who will act for you, and get it signed, with the option to revoke or invalidate it later from the app or online. The site is in Danish, with an English version at e-fuldmagt.dk/en, and it points to both a web app and a mobile app.

Sameem worked on e-fuldmagt as an engineer at Zencloud. He integrated Criipto, an identity broker, over OpenID Connect so that users verify their identity with MitID; used PDF-Lib to generate power-of-attorney documents from what users enter; and built a fully localised Danish and English frontend with i18next. He also worked on the REST APIs, built to GDPR requirements. The backend runs on Node.js, Express and TypeScript, with MongoDB and AWS S3 in the data layer. The sections below explain the engineering behind those parts.

Why does a power of attorney need strong identity verification?

A power of attorney is an instruction that one person may act for another, and its value depends entirely on whether a third party, such as a bank or a parcel service, will accept it. That acceptance rests on one question before any other: is the person granting authority really who the document says? A form that anyone can fill in with anyone's name answers nothing. In Denmark the established answer is MitID, the national digital identity that people already use for banking and public services, so a power-of-attorney service built on it inherits a check that relying parties already trust.

Integrating MitID through a broker such as Criipto keeps the service out of the identity business. The service redirects the user to the broker, the user approves the sign-in in MitID, and the broker returns an authorisation code that the backend exchanges for an ID token: a signed statement of who authenticated. Because this is standard OpenID Connect, the backend's job is well defined. It must verify the token's signature against the broker's published keys and check the issuer, the audience, the expiry and the nonce that ties the response to the request it started. The service never sees MitID credentials. Which identity attributes it asks for is itself a data-protection decision, since GDPR's data-minimisation principle says to request only what the service needs.

Why does delegated authority need more than a stored document?

Delegated authority is a relationship rather than a file. Who granted it, who holds it and what it covers are the facts a relying party needs, and they are facts about current state. A document proves that something was agreed at a moment; a record of authority answers whether it still stands now. e-fuldmagt's own description makes the point: a power of attorney can be revoked or invalidated later, so the system has to answer "is this still valid?" and not only "was this signed?".

Scope matters as much as status. Authority is rarely all-or-nothing: a postal power of attorney covers collecting post and parcels, while an enduring power of attorney concerns future decisions, and a system that stores only a signed instrument has nowhere to express the difference. Systems in this category are generally built around a record of the grant, its type, its parties and its state, with the document generated from that record rather than the other way round.

How are power-of-attorney PDFs generated with PDF-Lib?

Sameem used PDF-Lib to generate documents dynamically from user input. PDF-Lib is a JavaScript library that creates and modifies PDF files directly, in Node.js or in the browser, without running a headless browser to print HTML. That suits documents with a fixed legal layout: a template can be designed once, and the generator fills its fields or draws the names, dates and scope onto known positions, so every document of a type looks the same and the layout does not shift with a browser's rendering. The alternative, rendering HTML to PDF in a headless browser, is more flexible for free-flowing pages but heavier to run and harder to keep pixel-stable.

Language is a practical detail with real consequences. PDF-Lib's built-in standard fonts cover Western European characters such as æ, ø and å, which handles Danish, but a name containing a character outside that set fails to encode unless a font that contains it is embedded. A generator that serves the public has to plan for that, because people's names are not limited to one alphabet. Once a document is produced and signed, it is best treated as write-once evidence: a signature is meaningful only if the bytes it covers are the bytes a relying party later retrieves. Object storage such as AWS S3 suits that model, because objects are addressed by key and can be versioned rather than edited in place.

What does a Danish and English interface involve?

Sameem built a fully localised Danish and English frontend with i18next. The mechanics are familiar: every visible string is a key, each language supplies its own text for that key, and the library handles interpolation, so a sentence with a person's name or a date in it is one translatable unit rather than fragments glued together in code. Pluralisation rules and formatting differ between languages too. Danish writes dates day first and uses a comma as the decimal separator, and those details belong to the locale rather than being hard-coded into screens.

In a legal product the harder part is terminology. The Danish terms fuldmagt, postfuldmagt and fremtidsfuldmagt map to power of attorney, postal power of attorney and enduring power of attorney, and the translation has to stay consistent across every screen, email and generated document, because a user deciding what authority to grant is reading those words closely. Keeping the terms in one translation catalogue, rather than scattered through components, is what makes that consistency enforceable.

How is the service put together across web, mobile and backend?

A Node.js, Express and TypeScript backend serves both a React.js web client and a Flutter mobile app. One backend behind two clients is the ordinary way to build this. Two front ends that each implemented the domain rules for themselves would eventually disagree, and in an authorisation system a disagreement about who may act is not a display difference. Concentrating the rules in one REST API means that the question of whether a power of attorney is valid, revoked or within scope has a single answer, whichever client asks.

Express fits that shape because cross-cutting checks, such as verifying the signed-in identity, validating the request and confirming that the caller may act on the record, can run as middleware in front of every route, which makes them a structural property rather than something each handler has to remember. TypeScript carries the other half of that discipline: the identity of the acting party, the scope of a grant and whether a value is present at all are exactly the things that cause authorisation bugs when they are passed around untyped.

Why would a document database like MongoDB suit a platform of this shape?

MongoDB is the database, and the case for a document store here is variety. e-fuldmagt describes itself as adapted to private individuals, businesses and public institutions, and offers more than one type of power of attorney. Different types and contexts tend to need different attributes, identifiers and evidence. Forcing every variation into one relational table usually produces either sparse columns or side tables that exist only to describe one case. A document model lets each record carry the attributes its type needs, while the fields common to all of them stay uniform, indexed and queryable.

The trade-off is real. Schema discipline moves out of the database and into application code. With the backend written in TypeScript, that typing carries structural weight rather than editor-level convenience, because it is the main thing standing between a changed record shape and a request that is quietly mishandled.

What does building to GDPR requirements mean for the engineering?

The REST APIs Sameem worked on were built to GDPR requirements. That is a design constraint, and it is best read as one. GDPR turns several ordinary choices into requirements: personal data needs a stated purpose and a retention position, data subjects have rights of access and erasure, collection should be limited to what the purpose needs, and processing has to be recorded. That pulls against the other requirement in this domain, because an authorisation system needs a durable trail of who granted what and when, and an immutable trail is hard to reconcile with a right to erasure.

The usual resolution is separation and explicit retention. Evidence a relying party may need is held apart from personal data that may have to be removed, retention is decided per category rather than as one all-or-nothing policy, and erasure is handled with the understanding that it is not absolute where the law requires a record to be kept. DevoraX holds no certifications and has run no compliance audits.

Where can you see e-fuldmagt?

The service is live at e-fuldmagt.dk, in Danish, with an English version at e-fuldmagt.dk/en. The public pages describe the types of power of attorney on offer, the create, send and sign process, revocation, and the e-fuldmagt app. Most of Sameem's work sits behind the sign-in: MitID verification, the generated documents, the localised interface where powers of attorney are created, and the APIs underneath. A visitor can confirm that the service exists and what it does.

Why this stack

  • Node.js: the workload is almost entirely input and output rather than computation: reading and writing records, calling an identity broker, generating and fetching documents, and serving two clients. A non-blocking event loop holds many concurrent requests without a thread per connection, which suits a service whose latency is dominated by waiting on a database, object storage and outside services. It also runs PDF-Lib natively, so document generation lives in the same runtime as the API.
  • Express: a thin routing and middleware layer over Node.js, which is what a service built around access decisions generally wants. Authentication, request validation and permission checks have to apply to every endpoint identically, and middleware makes that a structural property rather than something each route handler has to remember. Its minimalism helps too, because there is less framework behaviour to reason about when correctness depends on the order in which checks run.
  • TypeScript: permission-shaped systems are where static types earn the most. The identity of the acting party, the scope of a grant and whether a value is present at all are the things that cause authorisation bugs when passed around as untyped objects. Typing them turns a missing field or a changed record shape into a compile error rather than a request that is quietly allowed. With a document database underneath, the types also carry schema the database is not enforcing.
  • Criipto with OpenID Connect (MitID): MitID is the identity Danish users and relying parties already trust, and a broker exposes it through standard OpenID Connect, so the service never handles MitID credentials. The backend's obligations are well defined: exchange the authorisation code, then verify the ID token's signature, issuer, audience, expiry and nonce. Requesting only the identity attributes the service needs is part of building to GDPR requirements.
  • PDF-Lib: a JavaScript library that creates and fills PDF files directly, without a headless browser. That suits documents with a fixed legal layout, generated from a template and the user's input, so every document of a type looks the same. Its standard fonts cover Danish characters, while names outside that character set need an embedded font, which a public-facing generator has to plan for.
  • i18next: every visible string is a key with Danish and English text behind it, with interpolation for names and dates and locale-aware plural and number handling. In a legal product the value is consistency: terms such as fuldmagt and fremtidsfuldmagt map to the same English wording on every screen because they come from one catalogue.
  • MongoDB: the database. A document store suits a service that handles several types of power of attorney for individuals, businesses and public institutions, where each type needs different attributes. Each record can carry what its type needs while common fields stay indexed and queryable. The cost is that schema discipline moves into application code, which is part of why a typed backend matters.
  • AWS S3: generated documents are immutable once signed and read more often than they are written, so they belong in object storage rather than in a database or on application disks. Keeping them out of the API tier leaves it lighter and replaceable, and addressing objects by key and version suits material that has to be retrievable as the exact bytes a signature covered.