---
title: "Vitrolife Group Case Study"
description: "How Vitrolife combines Microsoft Entra ID app roles with OpenFGA fine-grained ReBAC for a .NET 10 metadata platform serving IVF clinics worldwide."
canonical: "https://openfga.dev/docs/adopters/vitrolife"
content_type: "documentation"
last_updated: "2026-09-04T10:33:45.000Z"
---

# Vitrolife Group: Hybrid Entra + OpenFGA authorization for a .NET healthcare platform

The [Vitrolife Group](https://www.vitrolife.com) is a Swedish medical-device and software company serving IVF clinics worldwide. Its internal metadata platform — built on .NET 10 to organize landing zones, domains, platforms, and teams — uses a hybrid authorization design: Microsoft Entra ID app roles for coarse-grained access and OpenFGA for fine-grained, per-resource decisions.

## At a glance

|                       |                                                                                          |
| --------------------- | ---------------------------------------------------------------------------------------- |
| **Industry**          | Healthcare / medical devices (IVF)                                                       |
| **Stack**             | .NET 10, ASP.NET Core, Microsoft Entra ID, [Wolverine](https://wolverinefx.net/), Aspire |
| **Use case**          | Internal metadata platform: landing zones, domains, platforms, teams                     |
| **Deployment**        | Self-hosted alongside the .NET API                                                       |
| **Key features used** | Contextual tuples, intersections, conditions, full + differential sync from OpenFGA      |

## Why OpenFGA

Entra ID gave Vitrolife a managed identity layer for both human users and service principals, but app roles alone could not express _per-resource_ permissions ("can edit _this_ landing zone, not all of them"). The platform team layered OpenFGA underneath to model ownership and group membership without inventing a parallel directory.

Crucially, the team wanted OpenFGA — not Entra — to be the **source of truth** for access groups, so that the application's own model of "who has access to what" did not depend on a directory operation in a separate system.

## Architecture

- **App-role grammar.** Every Entra app role follows `<api>.<resource>.<capability>.<qualifier>`. Capabilities are `viewer` / `editor` / `admin`. The qualifier is either `all` (the principal may act on every record of that resource) or `self` (the principal may act only on records they have an OpenFGA relationship with). `all` injects a contextual tuple at request time; `self` falls through to a normal [Check](https://openfga.dev/docs/interacting/relationship-queries.md) against the relationship graph.
- **Users and service principals are uniform.** Because both human users and service principals carry app roles, the application code never branches on principal type — the OpenFGA tuple set treats them identically.
- **Type-safe C# wrappers.** `FGAObjectId` enforces `<type>:<id>` shape at compile time. An `FGATuple` builder makes tuple construction explicit, and relations are modeled as `snake_case` enums to match the OpenFGA wire format without stringly-typed bugs.
- **Group memberships as contextual tuples.** Entra group memberships are surfaced into OpenFGA via contextual tuples on each request, intersected with FGA group definitions so a principal must satisfy _both_ the Entra group and the FGA relationship to gain access.
- **Atomic writes via transactional outbox.** SQL writes and OpenFGA tuple writes are coordinated through a [Wolverine](https://wolverinefx.net/) outbox: the database row and the queued FGA mutation commit together; consumers process the outbox to make the tuple change visible. This is eventually consistent within a small, bounded window.
- **OpenFGA → Entra sync.** A scheduled job reads OpenFGA as the source of truth and reconciles Entra access groups: an hourly **full sync** plus a **differential sync** triggered by outbox events. If a tuple is removed in OpenFGA, the corresponding Entra membership is removed on the next pass.
- **Vertical slices and Aspire local dev.** Features are organized as vertical slices; .NET Aspire orchestrates a local environment with a mocked Microsoft Graph and a local OpenFGA, so the team can run the full authorization path end-to-end on a developer laptop.

## Outcomes

- **One mental model for authorization** that spans humans, service principals, and resources, with Entra handling identity and OpenFGA handling relationships.
- **Per-resource permissions** without a custom directory — the existing Entra investment stays in place.
- **OpenFGA as the durable source of truth** for access groups, with Entra reconciled on a schedule rather than the other way around.
- **Atomic SQL + tuple writes** through the Wolverine outbox, removing the class of bugs where the application data and the access graph drift apart.

## Source

This case study is based on a [presentation in the OpenFGA community meeting by Simon Gottschlag, CTO at Co-native, working with the Vitrolife Group on its platform](https://www.youtube.com/watch?v=nwu5SiiMpM8).
