STUDIO X
All articles
Security

How we build securely: BankID, GDPR and audit from the first sketch

Security is not added at the end of a project; it is built in from the first data model. We explain how we design our systems with encryption, traceability, and least-privilege as standard.

Jostein Flatin
STUDIO X

TL;DR

Security does not come from a penetration test at the end of the project. It comes from the data model being classified from day one, authentication being stronger than necessary, all changes being logged traceably, and least privilege being the default. This is what we do on every project, and what you should demand from any development partner.

The most common security anti-pattern

A project runs for several months. End-user testing is approaching. Someone in the project team says: "We must remember to do a security review before we go to production."

That is often too late.

When security is added at the end, it either becomes a checklist that satisfies the report but not reality, or a late discovery of structural problems that are expensive to fix. Both outcomes are bad.

Security is built in from the first sketch, or it never becomes genuine. Here is how we do it in practice.

The data model is classified on day one

Before we write a single line of code, we go through all entities in the system and classify them by what kind of data they contain:

  • Class 1 (public): Can be displayed without authentication. Company info, open product catalogues.
  • Class 2 (internal): Only for authenticated users. User profile, internal documentation.
  • Class 3 (sensitive): Only for authorised roles. Salary, health data, financial transactions.
  • Class 4 (critical): Special requirements for encryption and audit. Health data, BankID-signed documents, identifying personal data at particular risk.

The classification affects every technical decision going forward: which database encryption, how much audit logging, which authentication method, which backup policy, where data may reside geographically.

This takes two to four extra hours in the first project week, and saves weeks later when security questions arise.

Authentication: always stronger than necessary

Our default policy is that authentication should be one level stronger than "just sufficient" would suggest.

For internal professional tools: minimum SSO via the organisation's own identity provider, not username and password. If the system handles class 3 or above data: MFA required, no exceptions.

For patient or citizen-facing systems: BankID or ID-porten. Never "we will send you an SMS code", never "create an account with e-mail and password".

For B2B portals where external users log in: BankID if available, otherwise OIDC against their own identity provider. Never a local user database for class 2 or above data.

For machine calls between systems: Maskinporten in the public sector, OAuth2 client credentials in the private sector, mTLS for critical integrations. Never static API keys in clear text.

This is overkill for some projects. It is never a security disadvantage. And when requirements change, or the system needs to handle more sensitive data later, the foundation is already there.

Audit logging on everything that matters

Everything that changes data, and everything that reads sensitive data, is logged:

  • Who read which data, when
  • Who changed which data, from what to what, when
  • Who authenticated, which method, from which IP
  • Which systems fetched data via API, how much, when

Logs are stored separately from the application data, often in an append-only database or a log service with tamper protection. That means an attacker who compromises the application cannot delete traces of the attack.

For class 3 or above data, logs are retained for as long as regulations and need dictate. Logs are reviewed routinely, not only when something goes wrong.

This is not extra. It is the minimum standard for B2B systems going into production.

Least privilege is the default, not the exception

For each role in the system we ask: what does this role need to see and change to do the job? Everything else should be inaccessible.

In practice that means:

  • A case handler sees only their own cases, or cases belonging to colleagues in the same team
  • A manager sees team statistics, but not details of individual cases without clicking in
  • An admin has full control, but each admin action is additionally logged and often requires two-factor authentication
  • External integrations are given access to the narrowest possible part of the API

When a user requests more access, that is an explicit decision, not an automatic extension. That is inconvenient for users in the short term. It is insurance against a compromised account granting access to everything.

Encryption: at rest, in transit, always

All data is encrypted at rest (storage level), in transit (TLS 1.3 minimum), and for class 3 or above also at the application layer (column-level encryption for sensitive fields such as national identity numbers or bank account numbers).

Encryption keys are stored in dedicated key management services, not in application code or environment variables.

Key rotation happens automatically on a fixed schedule. Backups are encrypted with separate keys, not the production keys.

This is standard for all our systems that handle class 2 or above data, not something we do "if the client asks".

GDPR built into the foundations

For systems that process personal data we do the following routinely:

Data map at kickoff: which personal data is collected, where is it stored, how long is it retained, who has access, with whom is it shared. This is kept up to date throughout the project.

Data protection impact assessment where the processing warrants it, for example for class 3 or above data or broad processing of personal data. We are accustomed to carrying out such assessments in collaboration with the client.

Legal basis established for each type of processing. Not "we do it because we do it", but a clear basis where the processing is proportionate.

Privacy by design: the user can see which data about them exists, can export it, can correct errors, can request deletion. These functions are built in from the start, not as an afterthought.

Data processing agreements with all subprocessors. Norwegian or EU/EEA-based hosting for everything containing Norwegian personal data.

Penetration test, but not as the first security measure

We carry out a penetration test on all systems that handle class 3 or above data before going to production. We do this with external security specialists, not ourselves, because we are too close to the code to see it with fresh eyes.

But the penetration test is the final check, not the first. If the test finds critical vulnerabilities, that is not because the test was good. It is because we did poor work before it.

On a well-built system, a penetration test typically finds: small error messages that leak too much information, minor configuration errors, a couple of edge cases we had not thought of. Not structural problems.

Built to survive discoveries

Security is not a state, it is a continuous process. We set up:

  • Automatic monitoring of known vulnerabilities in dependencies (Snyk, Dependabot, GitHub Security)
  • Logging of unusual authentication patterns (many failed logins, login from unusual geography)
  • Periodic reviews of role and access structure
  • Clear runbooks for security incidents: what do we do if we discover a breach?

A good system survives the day something is discovered, not because nothing fails, but because we have structures to catch it and act.

What you should demand from any development partner

When you speak with potential partners, ask these questions:

  1. How do you classify data in a new project?
  2. What minimum authentication do you use on systems that handle personal data?
  3. How do you log changes to sensitive data, and where are the logs stored?
  4. How do you handle privacy and GDPR from project start?
  5. When do you carry out a penetration test, and by whom?
  6. What is your protocol if you discover a security vulnerability in production at a client's site?

A partner who answers in a structured and consistent way: a good candidate. A partner who answers vaguely or refers to a "policy" without explaining how it is practised in reality: be careful.

Security is not complicated words, it is concrete habits. Talk to us about what this looks like in a real project, or read more about systems development at STUDIO X.

Questions about this article?

Have a chat with us.

We reply personally, often the same day. Call or send an e-mail, and we will find out whether we are the right match for your project.

Daniel Heimstad

Daniel Heimstad

Inbound Lead Manager

Jostein Flatin

Jostein Flatin

CEO / Managing Director