at_auth 4.0.0
at_auth: ^4.0.0 copied to clipboard
Package that implements common logic for onboarding/authenticating an atsign to a secondary server
4.0.0 #
- docs: Upgrading to at_client 4.0 takes an app from at_client 3 to 4.
- feat: an atKeys file that is not a JSON object is read as
AtKeysFormatException, aFormatExceptionwhosereasonandpositionsay why and at which character, and which holds none of the file's text. A JSON value that is not an object no longer fails as aTypeError. - fix: after
CramAuthenticator.authenticatethe lookup's own authenticator is back in place, and a second CRAM authentication on a lookup already running one throwsStateError. - breaking:
AtAuth.createtakes noatChops, and itsatLookUpis a requiredAtLookupMuxable. - breaking:
PkamAuthenticator.authenticatetakes noenrollmentId; the lookup's authenticator decides which enrollment logs in. - breaking:
ServerEnrollmentRequestandEnrollmentServerResponseare removed; at_client'sclient.enrollments.list()returns eachEnrollment. - breaking:
KeyAlgorithmType,CryptographicKeyType,KeyPartStatusandAtKeysMaterialare removed;CryptographicMaterialAlgorithm,CryptographicMaterialRoleandKeyEntryStatusreplace them. - breaking:
RegistrarApiEndpointlosesgetFreeAtsign,getFreeAtsignByCategory,registerPersonandvalidatePerson, andHttpMethodlosesget, with theRegistrarServicemethods that used them. - breaking:
authenticatorForChopsis removed, andauthenticatorForno longer takeschopsorsigningAlgo: it signs with the keypair the keys hold, under the algorithm they name. - breaking:
AtKeys.authenticationForis removed; useauthenticationKeyPairFor. - feat:
waitForApprovaltakescancelled: once it completes, with a value or an error, no further poll starts and the wait throwsStoppedException. A stopped connection ends the wait at once, rather than spending the retry budget. - build: requires
at_utils^4.0.0 andat_lookup^4.0.0. - feat:
AtKeys.unfileLegacyEnrollmentdrops whatfileLegacyMaterialfiled for an enrollment that is gone, and nothing another enrollment filed. - breaking:
AtEnrollmentRequestandAtEnrollmentRequest.pqrequire asession. Their deprecatedatSign,rootDomain,apkamPublicKeyandencryptedAPKAMSymmetricKeyparameters are removed, as is theencryptedAPKAMSymmetricKeyfield, which nothing read. - breaking:
AtEnrollmentRequest.pqrefusesrsa2048with anArgumentError, before anything is sent: an enrollment that takes its keys post-quantum authenticates withmldsa65. Anrsa2048request uses the legacy key exchange. - fix: on Linux and macOS, a keyfile, and the
.bakand.pre-v1copies written beside it, are readable and writable by their owner alone (mode 0600), whatever mode the keyfile had before. - fix: on Linux and macOS, when root rewrites a keyfile, the keyfile and the
.bakand.pre-v1copies written beside it take the owner and group of the keyfile as it was read, and root does not rewrite a keyfile that is a symbolic link or anything other than a regular file. - fix: a keyfile write that removes a pending enrollment, as a cancelled or
denied request's does, keeps no copy of it in
.bak. - fix: a keyfile at_auth 3.3.0 wrote, which carries
version, its atSign and an emptykeysarray, can be updated or flushed without adding typed key material; it is rewritten in the flat shape. - fix:
FileAtKeysIorefuses to write keys for one atSign over a keyfile that holds no credential and names another atSign. - fix: a self-enrollment whose keyfile cannot be written fails before it sends anything. When the keyfile refuses the save after the request is approved, the enrollment it created is revoked, and the error names that enrollment and says whether the revoke succeeded.
- build: requires
ffi^2.1.0. - chore: constructing
InMemoryAtKeysIooutside a test draws an analyzer warning: nothing it holds survives the process, and the store a client runs on must be durable.
4.0.0-rc7 #
- fix: a refused CRAM authentication reports "Cram authentication failed for
- fix: a keyfile field that does not hold valid base64 is reported by its name and the offset of the first bad character.
- fix: a keyfile, or a passphrase-protected keyfile's decrypted content, that is not valid JSON is reported with the parser's reason and the character where it stopped.
- fix: a passphrase-protected keyfile whose envelope
saltis not valid base64 is refused withAtDecryptionException, as itsivandcontentare. - build: requires
at_lookup^3.7.0-rc4.
4.0.0-rc6 #
- fix: an atSign whose RSA PKAM key is 1024 bits authenticates again, rather than failing with "Cannot sign with a 1024-bit key". RSA PKAM keys of other sizes than 1024 or 2048 bits are still refused.
- build: requires
at_chops^3.7.0.
4.0.0-rc5 #
- feat:
RegistrarService.registerAtSign(v4/register-atsign/). - feat:
RegistrarAdminServicefor the v4/manage-atsigns/delete flow (Super API key). - refactor:
registrarApiRequest'sdatais nowMap<String, dynamic>. - BREAKING: removed
getFreeAtSign,getFreeAtSignByCategory,registerPersonandvalidatePerson; useregisterAtSign.
4.0.0-rc4 #
- fix: waiting for an enrollment's approval ends at once, with the atServer's
reason, when the enrollment has expired or the atServer has no record of it
(
AT0028), instead of after the whole retry budget. - chore(deps): at_utils ^4.0.0-rc1
4.0.0-rc3 #
- fix: a keyfile lock left behind by a process that stopped mid-write is released within 5 seconds, instead of blocking every other writer for 30.
4.0.0-rc2 #
Logging in and managing enrollments moved to at_client (Atsign.open,
Atsign.enroll and client.enrollments); this release removes what they
replace.
- BREAKING:
AtAuthand its request and response objects (AtAuthRequest,AtAuthResponse,AuthRequest,AuthResponse,AtOnboardingRequestandAtOnboardingResponse) are removed. Activate withactivateAtSign(...); log in with at_client'sAtsign.open, or check credentials withAtsign.authenticatesAs.RetryOptionsis still exported. - BREAKING:
AtEnrollmentkeepssubmit,approveandwaitForApproval.deny,revoke,list,generateOtpandsetSpp, withOtpanddefaultOtpExpiry, are at_client'sclient.enrollments;updateandEnrollmentUpdateRequestare at_client'sEnrollmentUpdater. - BREAKING:
activateAtSignrequiresatLookUpandAtEnrollment.waitForApprovalrequiresatLookup, each anAtLookupMuxableit neither builds nor closes. - BREAKING:
AtEnrollment.approverequiresapproverKeys, anApproverKeyMaterial;approverChopsis removed, andapproveno longer writes the APKAM symmetric key into the caller'sAtChops. - BREAKING: no caller names the enrollment to authenticate as: the keys decide,
through
AtKeys.enrollmentToAuthenticateAs(), and a retrofitted keyfile authenticates as its successor. A keyfile holding several live enrollments throws, naming them. - BREAKING:
apkamSymmetricKeyResolveronAtEnrollmentRequest.pqandAtEnrollmentResponsereturns aStream<String>rather than one key. - BREAKING: a self-enrollment no longer approves its own request; a
pendinganswer is denied and thrown. - BREAKING:
AtAuthSessionno longer carriesatLookUp. - BREAKING:
httpsProbe,defaultProbeandsecureSocketProbeare removed; the check before an activation uses at_lookup'scheckAtSignServer. at_auth no longer depends on at_server_status. - BREAKING:
AtKeys.toAtChopsandtoAtChopsForEnrollmentare private; useAtKeys.authenticationFor, orauthenticationKeyPairFor,encryptionKeyPairandselfEncryptionKeyfor the material itself. - BREAKING:
AtKeys.copyWithis removed; useaddKey. - BREAKING:
KeyIOMixinis removed; read and write a.atKeysfile withFileAtKeysIo.readandwrite, or useAtKeysIo.passphraseCodecfor the passphrase envelope alone. - BREAKING: the registrar's
ActivateApiEndpointandRegistrarApiEndpoint.login/validateare removed; useRegistrarApiEndpoint.requestOtp/validateOtp. - feat:
activateAtSign(...)activates an atSign with its CRAM secret and answers the new enrollment's id. - feat:
CryptographicMaterialStatus.pendingmarks an enrollment's keys between submission and approval, managed withAtKeys.activatePending,discardEnrollmentandpendingEnrollmentIds. - feat:
AtKeys.holdsAuthenticationMaterial,authenticationKeyPairFor,encryptionKeyPairandselfEncryptionKey. - feat:
AtKeys.fileLegacyMaterial,AtKeys.legacy,enrollmentSymmetricKeyandstoredEnrollmentIdreach a keyfile's flat legacy fields without the deprecated members. - feat:
InMemoryAtKeysIo.holding(atSign, keys), an in-memory store already holding a key set. - feat: the first time
FileAtKeysIowrites typed keys into a flat keyfile, it keeps a<keyfile>.pre-v1copy. - fix: a typed keyfile is written with
"keys": []again, so an application on at_auth 3.3.0 can still read it. - fix: an approval can fill legacy fields its submission left empty, and a keyfile emptied by a denial can take the next request.
- fix: a keyfile whose atSign keys are typed produces working encryption keys.
- fix: activation works with at_lookup's
close(), which now ends a lookup. - fix:
waitForApprovalwithlogProgressset no longer waits 500 ms before each attempt. - fix:
AtKeys.metadatais no longer deprecated. - build: requires
at_lookup^3.7.0-rc2 andat_commons^5.18.0.
4.0.0-rc1 #
A release candidate: adopt it deliberately. The headline is post-quantum credentials, with an enrollment able to authenticate with ML-DSA-65 while deployed peers still read what it advertises.
- BREAKING:
package:at_auth/at_auth.dartno longer reachesdart:io.FileAtKeysIo, and anything else needing a filesystem, a socket or HTTP, is inpackage:at_auth/at_auth_io.dart. - BREAKING:
AtEnrollmentRequestrequiressigningAlgo. - BREAKING:
AtOnboardingRequest.atKeysIono longer defaults toFileAtKeysIo(). - BREAKING:
authenticatorForChopsrequiressigningAlgoandhashingAlgo. - BREAKING: the
.atKeystyped document groups keys by enrollment, role and algorithm. Legacy keyfiles, and those written by 3.3.0, still read. - BREAKING: a keyfile's role, algorithm and status values are types, and
CryptographicMaterialStatusandKeyEntryStatusread values a newer client writes rather than refusing them. - BREAKING:
_apskadvertises a list. One activersa2048key is still the bare public key every deployed peer reads; anything else is a JSON array, which deployed peers cannot read. - BREAKING:
AtKeys.authenticationAlgorithmForthrows for an algorithm this build cannot sign with, rather than returning null. - BREAKING:
AtOnboardingRequest.atKeys,AtAuthRequest.encryptedKeysMapandAtKeysIo.generateKeyPairs'satSignare removed; the other members marked for removal in v4 now say v5. - feat: post-quantum self-retrofit:
AtSelfEnrollmentRequestmoves an enrollment to an ML-DSA-65 APKAM key, andAtEnrollment.updatesends theenroll:updatewith the possession proof the atServer checks. - feat: a CRAM activation can mint an ML-DSA-65 APKAM key from the start, and
mintLegacyMaterialopts out of classical keys beside it. - feat: an enrollment holds one signing key per algorithm and advertises them
all at
_apsk; a retired key stays advertised, so what it signed still verifies. - feat:
AtAuthenticator: at_lookup is handed an authenticator for a PKAM key, anAtChops, a CRAM secret or an enrollment, rather than credential fields. - feat:
AtEnrollmentRequest.pq(...)has the approver seal the symmetric key to the request's key package, so nothing RSA-wrapped rides the enrollment. - feat: a keyfile holding several live enrollments is read, and
resolveAuthenticatingEnrollment()lists them rather than choosing one. - feat: a self-enrollment from an atSign that holds no enrollment approves itself over the connection that requested it.
- fix: two processes sharing a keyfile no longer lose each other's writes:
FileAtKeysIolocks across processes, andWrittenAtKeysIo.updateis one operation. - fix: the
.atKeyspassphrase envelope uses a random salt and carries a version; files without one still open. - fix:
FileAtKeysIo.updateno longer recreates a keyfile deleted while it ran, and throwsAtKeysSourceAbsentException. - fix: an OTP enrollment that advertises a signing key keeps its private half, so the next start no longer mints and advertises a second one.
- fix:
waitForApprovalstops on a refusal it cannot resolve, counts its retries as consecutive failures, and opens key records written without aniv. - fix: an aborted self-retrofit denies the pending enrollment it created.
- build: requires
at_commons^5.16.0,at_chops^3.6.0 andat_lookup^3.7.0-rc1.
3.3.0 #
- feat: add
AtAuthSession(exported) — the explicit auth→client hand-off artifact: the confirmed subset of an auth request that client creation actually needs (atSign,rootDomain,namespace,atKeysIo,enrollmentId), promoted to its own type so "request" no longer doubles as "session". Keys cross the boundary as anAtKeysIosource, not as live crypto state: the client derives its ownAtKeysviaatKeysIo.read(atSign)rather than adopting auth'sAtChops/AtLookUp. The session also carries auth's already-authenticatedatLookUpso a caller can opt in to reusing that connection (AtClientManager.fromAuthSession(session, reuse: true)) and skip a second PKAM handshake; the default hand-off rebuilds a fresh connection. - feat:
AtAuthImpl.authenticate(...)and.onboard(...)populate the newAuthResponse.sessionon success whenever the request supplied anatKeysIo— pass it straight toAtClientManager.fromAuthSession(...). The legacyatAuthKeys-only path has no key source to hand across, so it gets no session and keeps behaving exactly as before. - feat:
AtEnrollmentRequestnow takes asession(the requesting app's atSign, rootDomain and theatKeysIoits new keys will be persisted into) in place of the individualatSign/rootDomain/apkamPublicKey/encryptedAPKAMSymmetricKeyparams. On approval,waitForApproval(...)flushes the completed keyset intosession.atKeysIo(when it is aWrittenAtKeysIo) and hands back a ready-to-useAtEnrollmentResponse.session. Supplying neithersessionnor the deprecatedatSignthrowsArgumentError. The legacy path (no session, or a read-onlyAtKeysIo) leavesatAuthKeyspopulated for the caller to persist and setssessionto null. - deprecation: everything the
AtAuthSessionhand-off replaces is marked@Deprecated(... 'remove in v4')and still fully functional in 3.3.0 —AuthResponseand itsAtAuthResponse/AtOnboardingResponsesubclasses, theatAuthKeys/atLookUp/atChopsresponse fields,AtEnrollmentResponse.atSign/.rootDomain/.atAuthKeys, and theAtEnrollmentRequestparams listed above. No runtime behaviour changed; this release is additive so consumers can migrate tosessionbefore at_auth 4. - feat: add
AtKeysMaterial— the only key typeAtKeys's API deals in (addKey,getKey,keysForKeyId,keysForEnrollment,retireKey, thekeysListconstructor param, ...). It's fully self-describing:keyId/enrollmentIdpluskeyPartType(an openString— the mechanical crypto role; known tokens inCryptographicKeyType: symmetric encryption/authentication and the public/private halves of encryption, verification/signing, encapsulation/decapsulation and key agreement),keyAlgorithmType(an openString— the algorithm family; known tokens inKeyAlgorithmType:aes256/rsa2048/ecc_secp256r1/ed25519/x25519/mlkem768/mldsa65/xwing, matching the pkam/enrollmentsigningAlgoliterals),bytes,operations,createdAt, andstatus(active/retired/dead;withStatus(...)copies a material at a new status). Both token fields are deliberately Strings, not enums: unknown tokens are preserved and round-tripped, so a keyfile written by a newer client stays readable — and losslessly flushable — by an older one; whether an algorithm is classical, post-quantum or hybrid is carried by the algorithm token (e.g.xwing), not a separate role axis. The wire's nestedkeys[].keyParts[]document shape — grouping the materials sharing akeyId(e.g. the public+private halves of a keypair) — is produced/consumed byencodeAtKeysDocument/parseAtKeysDocument(also exported), not a separate model type. Keys produced by one enrollment are grouped by an optionalenrollmentIdand queried viaAtKeys.keysForEnrollment(...); at most one material of a givenCryptographicKeyTypemay share anenrollmentId. - feat:
AtKeys.toJson()/.fromJson(...)now produce/consume the versioned typed-keys document shape (version,atsign,keys, with legacy fields flat at the top level — upgrading a legacy file to the typed-keys document is additive, not a format swap), replacing the former codec/resolver/document layer. Backward compatible:fromJsonaccepts json without aversionfield as the legacy flat shape, and throwsAtKeysUnsupportedVersionExceptionon an unknown version. Typed materials are looked up viaAtKeys.getKey(keyId, type)and.keysForKeyId(keyId). - feat: add
WrittenAtKeysIo.flush(Atsign, AtKeys)— the runtime persist operation: mutate the in-memoryAtKeys(addKey,retireKey, ...), then flush the complete state. On an existing file, flush safety-checks the rewrite (AtKeysAssurance.validateMapUpdate— nothing may be lost: every existing(keyId, keyPartType)must survive with identical fields, thoughstatusmay move forwardactive→retired→deadand new materials may be added), then rewrites; flushing a legacy.atKeysfile upgrades it in place to the typed-keys document format (legacy fields preserved byte-for-byte). On a missing file, flush creates it.write(...)stays the create-only initial persist. (Theappend/savemethods that existed briefly during this release's development are gone — never published.)FileAtKeysIowrites are atomic (write-to-temp + rename, so a crash can never truncate the keyfile) and a flush over an existing file first preserves it as<file>.bak. - feat:
AtKeysAssuranceis now the single home for all atKeys validation — both the low-levelexpect*/optional*value/type checks used byAtKeysMaterial.fromJson/AtKeys.fromJson, and the structural invariants (validateKeyMaterials: duplicatekeyId, one material of eachCryptographicKeyTypeper enrollment, the flush-safety checkvalidateMapUpdate). - feat: add passphrase envelope support via
AtKeysPassphraseEnvelopeCodec(encode/decode/isEnvelope, argon2id key derivation), and addInMemoryAtKeysIofor in-memory/test flows (both exported). - fix:
AtKeys.==/hashCodenow also coveratsign,metadata(compared structurally — nested maps/lists by value, not identity) and the typed key materials (order-insensitive). - chore(deps): require
at_chops^3.4.1 for hashing algorithm barrel exports used by AtKeys passphrase handling. - fix:
RegistrarServicenow fails loudly on a bad API key instead of reporting an ordinary negative result. The constructor throwsAtExceptionwhenapiKeyis empty or whitespace-only, and every registrar call that requires authentication throwsAtExceptionnaming the endpoint and status code when the registrar answers 401/403. Previously a rejected key surfaced assendActivationOtp()returningfalse(or an empty atsign list), which is indistinguishable from a legitimate "no" — callers that treated a falsy result as an expected outcome will now see an exception (#1909).
3.2.0 #
- feat: bound
AtAuthImpl.validateAtServerwith a single overall deadline so a dead network can no longer hang authentication/onboarding.RetryOptionsgains an optionaloverallTimeout; when null the default depends on the request: authentication usesAtNetworkTimeouts.effectiveDefault(30s) so a dead network fails fast, while ONBOARDING usesAtNetworkTimeouts.defaultOnboardingTimeout(5 min) because a newly-registered atSign can take minutes to be provisioned. The loop is deadline-driven — it retries everyretryDelayuntil the budget is spent, then throwsAtTimeoutException; each inner network call (the atDirectory lookup and the connectivity probe) is bounded by the remaining budget and capped at 60s.RetryOptions.maxRetriesno longer bounds this loop (the deadline does) (#1923). Requiresat_commons ^5.13.0. - chore(deps):
at_lookup: ^3.6.0—validateAtServerpasses thetimeoutparameter thatSecondaryAddressFinder.findSecondarygained in at_lookup 3.6.0, so this version does not compile against at_lookup ≤3.5.x.
3.1.1 #
- refactor: route enrollment RSA (encrypt/decrypt
apkamSymmetricKeyunder the default encryption keypair) through at_chops (RsaEncryptionAlgo) —cryptonno longer imported inliband moved todev_dependencies(only the enrollment test still uses it for RSA keypair fixtures). Same framing, byte-identical by construction. - fix:
decodeAtKeys()now reliably throwsAtDecryptionExceptionon an incorrect passphrase. ThejsonDecodeof the decrypted bytes now runs inside the decrypt try/catch, so wrong-passphrase garbage no longer escapes as an uncaughtFormatException(an intermittent failure inat_keys_io_test).
3.1.0 #
- feat:
validateAtServer()now emits progress events and probes atSign connectivity before returning - fix:
decodeAtKeys()now throws when an invalid passphrase is provided - fix:
FileAtKeysIOnow encrypts the key file with a passphrase when one is available - fix: throws
AtAuthenticationExceptionwhen the atSign is already onboarded - feat: use AtBytes.equals in
AtKeys(requires at_commons: ^5.9.0)
3.0.1 #
- feat: improve
AtEnrollmentImpl - feat: introduce
NamespacePermission - fix: ensure directory when writing keys in FileAtKeysIo
3.0.0 #
- chore(deps): at_chops ^3.0.0
- refactor: remove all singletons, injecting dependecies via
AuthRequest - feat:
AtKeysIointerface which defines interaction between stored/generated keys and at_auth - feat:
FileAtKeysIoclass which defines implementation - feat: authentication returns
AtLookupandAtChopsviaAuthResponse - feat:
AtAuthexposes aProgressStreamto consume status of at_auth
2.4.0 #
- chore(deps): at_commons ^5.5.0
2.3.0 #
- feat: add
AtLookUp? atLookUpto theAtAuthinterface so that it can be reused (e.g. by AtClient) once auth is complete
2.2.0 #
- feat: enable callers of
AtAuth.onboardto control post-auth activation completion (set the encryption public key on the server, delete the "cram" secret)
2.1.0 #
- fix: potential bug handling atSigns which end in
datae.g.@foo_data
2.0.10 #
- fix: Replace legacy IVs with random IVs for encrypting "defaultEncryptionPrivateKey" and "selfEncryptionKey" in APKAM flow
2.0.9 #
- fix:Enable caching of encryption public key
2.0.8 #
- feat: Add "passPhrase" in "AtAuthRequest" to support password protected atKeys file
- build[deps]: Upgraded the following packages:
- at_commons to v5.0.2
- at_auth to v2.2.0
- lints to v5.0.0
- test to v1.25.8
- mocktail to v1.0.4
2.0.7 #
- build[deps]: Upgraded the following packages:
- at_commons to v5.0.0
- at_lookup to v3.0.49
- at_utils to v3.0.19
- at_chops to v2.0.1
2.0.6 #
- fix: Add "apkamKeysExpiryDuration" to "EnrollmentRequest" to support auto expiry of APKAM keys
2.0.5 #
- fix: set atChops in atLookup before pkam auth in AtAuthImpl
- build[deps]: Upgraded the following packages:
- at_commons to 4.0.11
- at_lookup to 3.0.47
- feat: Add signing SigningAlgoType and HashingAlgoType in AtAuthRequest, AtOnboardingRequest
2.0.4 #
- fix: Add "revoke" to the "AtEnrollmentBase" to support enroll:revoke operation
2.0.3 #
- fix: Add optional parameters to the "atAuth" method in "AtAuthInterface"
2.0.2 #
- fix: set default value for app name and device name if they are not passed in the onboarding request.
2.0.1 #
- fix: deprecate enableEnrollment flag in OnboardingRequest and removed the check in AtAuthImpl
2.0.0 #
- build[deps]: Upgraded the following packages:
- at_commons to 4.0.5
- at_lookup to 3.0.46
- Implement new methods for enrollment operations within AtEnrollmentImpl and remove older methods.
- Enhance readability by renaming the current classes associated with EnrollmentRequest.
1.0.5 #
- build[deps]: Upgraded the following packages:
- at_chops to v2.0.0
- at_lookup to v3.0.45
1.0.4 #
- build[deps]: Upgraded the following packages:
- at_commons to v4.0.0
- at_utils to v3.0.16
- at_chops to v1.0.7
- at_lookup to v3.0.44
1.0.3 #
- fix: upgrade at_lookup to 3.0.43 since 3.0.42 has breaking change for private key reference
1.0.2 #
- feat: enrollment common code from at_client_mobile and at_onboarding_cli
- chore: upgrade at_lookup to 3.0.42 and at_demo_data to 1.0.3
1.0.1 #
- feat: Introduce "submitEnrollment" and "manageEnrollment" methods for APKAM
1.0.0 #
- Implemented onboard and authenticate methods.