Notice: you're looking at a read-only mirror of our Dokuwiki.
This document formally defines a QR Code format that encodes the minimum identifiable user information for use by other services.
The QR Code encodes a string encoded in Alphanumeric mode. The string must implement this syntax:
QR_STRING := 'HTTPS://DMA.SPACE/QR/' CLAIMS_PART '.' SIGNATURE_PART
Note: All characters MUST be upper-cased for Alphanumeric mode.
The QR string makes extensive use of standard Base32 encoding with NO padding, as defined in RFC 4648.
CLAIMS_PART := USER_ID ':' USERNAME_BASE32 ':' USER_ROLE ':' ISSUED_DATE
USER_ID := /[0-9]+/
USER_ROLE := 'ADMIN' | 'MEMBER' | '_'
ISSUED_DATE := YEAR '-' MONTH '-' DATE
The claims part is described in the syntax above, with the following notes:
UNAME_BASE32 means the username is encoded using the predefined Base32 encoding._ must be used to denote either normal user or unknown role.As an example, this claims string:
10:MRUWC3LPNZSA:ADMIN:2026-01-01
Means the following:
10diamond (decoded from the Base32 string MRUWC3LPNZSA)admin, meaning they belong in the dma-admins IdP groupSIGNATURE_PART := SIGNATURE_ED25519 | ...
SIGNATURE_ED25519 := 'ED25519:' BASE32_DATA
The signature type denotes the type of the signature string that follows after it and the colon (:) character.
The signature part is the signature of the entire Claims Part string, signed using whatever the signature type denotes, and encoded using the predefined Base32 encoding.
The supported signature types are:
ED25519An example signature part of the above claims part string example could be:
ED25519:7CSS7U7C2BJM3Z3MXYENYNSBUWZRS3BGT4YWX4DXTMDBOWUABFBT4REZSKJ4FCVTFXCFY6A2WNOUIMIR3HHGLQT5CNA5ZABNOBPBMBY
The following function implements the algorithm in Go using a fake random source to generate the Ed25519 key (INSECURE) [aasadasds][asdasdasd]:
func encodeEd25519(priv ed25519.PrivateKey, uid int, uname string, urole string, issuedAt time.Time) []byte {
enc := base32.StdEncoding.WithPadding(base32.NoPadding)
plx := fmt.Sprintf(
"%d:%s:%s:%s",
uid,
enc.EncodeToString([]byte(uname)),
urole,
issuedAt.Format("2006-01-02"),
)
sig := ed25519.Sign(priv, []byte(plx))
return fmt.Appendf(nil, "HTTPS://DMA.SPACE/QR/%s.ED25519:%s", plx, enc.EncodeToString(sig))
}
The example outputs above was generated with:
issuedAt := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
constRand := rand.NewChaCha8([32]byte{})
_, priv, _ := ed25519.GenerateKey(constRand)
encodeEd25519(priv, 10, "diamond", roleAdmin, issuedAt)
This returns the following string:
HTTPS://DMA.SPACE/QR/10:MRUWC3LPNZSA:ADMIN:2026-01-01.ED25519:7CSS7U7C2BJM3Z3MXYENYNSBUWZRS3BGT4YWX4DXTMDBOWUABFBT4REZSKJ4FCVTFXCFY6A2WNOUIMIR3HHGLQT5CNA5ZABNOBPBMBY
The frontend server must be able to handle /QR paths and perform a redirection to the Monolith API server's GET /api/qr endpoint. The query string must be kept as-is.
This section is not finalized.
Proposed endpoints:
/qr/*: same as /QR/*/QR/keys.json: returns the public keys that are used to sign/QR/<CODE>: redirect to user-specific page or custom URL if we don't have this feature yet. This allows any user to scan this code as normal and be redirected to a nice webpage./QR/<CODE>/verify: verify the signature ONLY (any client can verify themselves using the public key)./QR/<CODE>/claims: verify the signature and return the additional user claims.$ curl -X GET "HTTPS://DMA.SPACE/QR/10:MRUWC3LPNZSA:ADMIN:2026-01-01.ED25519:7CSS7U7C2BJM3Z3MXYENYNSBUWZRS3BGT4YWX4DXTMDBOWUABFBT4REZSKJ4FCVTFXCFY6A2WNOUIMIR3HHGLQT5CNA5ZABNOBPBMBY/verify"
{
"valid": true
}
$ curl -X GET "HTTPS://DMA.SPACE/QR/10:MRUWC3LPNZSA:ADMIN:2026-01-01.ED25519:7CSS7U7C2BJM3Z3MXYENYNSBUWZRS3BGT4YWX4DXTMDBOWUABFBT4REZSKJ4FCVTFXCFY6A2WNOUIMIR3HHGLQT5CNA5ZABNOBPBMBY/claims"
{
"valid": true,
"claims": {
"sub": 10,
"username": "diamond",
"preferred_name": "diamond",
"email": "diamond@dma.space",
"groups": ["dma-users", "dma-members", "dma-admins"]
}
}
The Monolith should implement a GET /api/qr.
This design does prevent fake QR codes from being created, so imitating another person is not trivial.
However, the QR code can still be copied or stolen from others, so the whole system is not perfect and should not be used to gate access to critical things.