← All articles

Decentralized Web/6 min read

Storing wallet credentials in Solid Pods

What I learned integrating Solid Pods into DITLab's React Native e-wallet: WebID-OIDC login, gzip compression that saved 40%, backup and restore, and sharing credentials with ACLs.

Mohamad.B Alhakim

In 2025 I did my internship at DITLab, an innovation lab where higher education and the Dutch government work together on trustworthy, privacy-friendly digital services. They build the DitlabWallet: a mobile e-wallet, written in React Native, where you keep verifiable credentials like diplomas and ID proofs.

My question for the internship was: how can Solid Pods make storing, syncing and sharing those credentials safer and more efficient, for users and for organisations like DUO?

Why not EBSI

I originally wanted to work on the European Blockchain Services Infrastructure (EBSI), the EU's framework for this kind of credential. After talking it through with my supervisors, we agreed it was still too much in development, with too few resources, to deliver something useful in one internship. So we picked a different angle: adding a decentralised feature to the wallet based on Solid.

The pieces: SSI, VCs and Solid

  • Verifiable Credentials (VCs) are the W3C standard for digital proofs. They're signed by an issuer, so anyone can check them without calling that issuer.
  • Self-sovereign identity (SSI) means you hold those credentials, in a wallet, instead of a company holding them for you.
  • Solid gives every person a Pod: a personal data store on the web, plus a WebID that identifies them. Apps ask your Pod for data, and you decide who gets access.

A wallet normally keeps credentials only on the phone. Lose the phone and they're gone. A Pod turns the wallet into a client for data you control somewhere else.

Starting with a gap analysis

Before building anything, I did a gap analysis of the existing wallet: for each area, what does it do now, and what should it do according to the Solid and W3C guidelines? That surfaced five themes:

  1. Authentication with a Solid WebID,
  2. Storage of credentials in the Pod,
  3. Backup, restore and sync between phone and Pod,
  4. Sharing credentials with others through access control lists (ACLs),
  5. Interoperability with different Pod providers.

I worked through them in three-week sprints, each ending with a review with the DITLab team and code reviews on pull requests.

Learning Solid with a small app first

To learn the platform I first built a small Solid todo app: log in with Solid OIDC, find the user's storage, write a resource, read it back, and handle missing permissions. A todo list is trivial, but it covers the whole loop, and it made the wallet work much less daunting.

1. Logging in with your WebID

The wallet now logs in through WebID-OIDC using Inrupt's Solid client libraries, with SolidCommunity.net as the identity provider. A few details mattered on mobile:

  • Sessions and tokens are stored with EncryptedStorage, not plain app storage.
  • Expired access tokens (DPoP-bound) are refreshed automatically.
  • The user's WebID can be derived from their email, so login feels familiar.

Every part of the flow had unit tests: getting an access token, building an authenticated fetch with the right headers, token refresh, and the failure cases.

2. Storing credentials, and how slow a Pod really is

Credentials are stored as JSON-LD in a structured folder in the user's Pod. Then I measured what that costs compared with local storage, for a set of three credentials:

Average time
Save locally30 ms
Load locally0.1 ms
Upload to Solid Pod2585 ms
Load from Solid Pod285 ms

So uploads to the Pod were about 85× slower and loads about 2850× slower than local storage. That's network round trips plus OAuth authentication on every request. The good news: every operation succeeded, as long as the session was valid. Slow but reliable is something you can design around.

3. Compression: 40% smaller, a second faster

Verifiable credentials are verbose JSON-LD with long, repeated URIs, so they compress well. My proof of concept compresses each credential before upload and decompresses it on load. I compared several settings:

MethodUpload (ms)Load (ms)
No compression2585285
gzip level 11654234
gzip level 61591213
gzip level 92165355
deflate level 62768339

Compression cut the stored size by about 40% on average, and gzip level 6 gave the best balance: uploads went from 2585 ms to 1591 ms. Level 9 squeezes a bit more but costs more time than it saves, which is a nice reminder that "maximum" is rarely the right setting. Gzip 6 became the recommendation for the wallet.

4. Backup and restore

Every credential the wallet creates or receives is saved to the user's Pod automatically. If you lose your phone, reinstall the app or switch devices, one button restores everything from the Pod: credentials and DID keys.

I deliberately didn't build a full offline queue that tracks changes made while offline and replays them later. For DITLab the goal was recovery, not two-way sync, and a queue would have added a lot of complexity for little benefit. Instead, the backup and restore service fails cleanly without a connection and tells the user why. All backup, restore and status flows, including the offline cases, are covered by Jest tests.

5. Sharing with ACLs

Holding credentials is only half of SSI; the point is to show them to someone. Solid uses Web Access Control: each resource can have an ACL that grants other WebIDs rights.

The proof of concept is a screen where Alice picks a permission (none, read or write) for Bob's WebID and taps Grant access. Under the hood that's:

  1. load the credential's dataset and its ACL,
  2. setAgentResourceAccess for Bob's WebID,
  3. saveAclFor to write the new ACL.

A Verify as Bob button then logs in as Bob and fetches the file: 200 with the JSON if he has access, 403 if not. It works for a single credential and for the whole credentials folder.

Technically it works. The real limitation is on the other side: Bob gets no notification that something was shared with him, and there's no easy way for him to find the shared file in his own Pod. Fixing that needs support from Solid servers (inbox notifications, a view of shared items), not just from the wallet.

What I took away

  • Measure before you optimise. The baseline numbers showed exactly where the time went, and made the gain from compression easy to prove.
  • Decentralised moves complexity to the client. Sessions, latency, sync and permissions all become the app's problem.
  • "Works technically" isn't "works for people". ACL sharing passed every test, but without notifications it isn't usable yet.
  • Scope honestly. Dropping EBSI and the offline queue let me finish the parts that mattered.

The result: Solid Pods in a wallet are technically feasible and give users secure, decentralised backup and controlled sharing of their credentials. The next steps are a friendlier sharing UI and support for revoking credentials.

Blog / Keep reading

Related articles.

Storing wallet credentials in Solid Pods - Mohamad Bashar Alhakim