authenticate method

  1. @override
Future<Principal> authenticate(
  1. Credential credential, {
  2. required Uint8List challenge,
})
override

Authenticates credential, returning the resolved Principal.

challenge is the per-connection nonce the Hub issued in its hello; public-key authenticators verify the signature against it for replay protection, while token authenticators ignore it.

Throws AuthException if the credential is unsupported, malformed, unknown or fails verification.

Implementation

@override
Future<Principal> authenticate(
  Credential credential, {
  required Uint8List challenge,
}) async {
  if (credential is! PublicKeyCredential) {
    throw const AuthException('Unsupported credential for public-key auth');
  }

  final Ed25519PublicKey publicKey;
  try {
    publicKey = Ed25519PublicKey.fromBase64(credential.publicKeyBase64);
  } on Object {
    throw const AuthException('Malformed public key');
  }

  final entry = store.find(credential.principal, publicKey);
  if (entry == null) {
    throw const AuthException('Public key not authorized for principal');
  }

  final List<int> signatureBytes;
  try {
    signatureBytes = base64.decode(
      base64.normalize(_toStandard(credential.signatureBase64)),
    );
  } on Object {
    throw const AuthException('Malformed signature');
  }

  final valid = await _algorithm.verify(
    challenge,
    signature: Signature(
      signatureBytes,
      publicKey: SimplePublicKey(publicKey.bytes, type: KeyPairType.ed25519),
    ),
  );
  if (!valid) {
    throw const AuthException('Signature verification failed');
  }

  return Principal(
    id: PrincipalId(credential.principal),
    displayName: entry.displayName.isEmpty
        ? credential.principal
        : entry.displayName,
    roles: entry.roles,
  );
}