authenticate method

  1. @override
Future<Principal?> authenticate(
  1. HandshakeConnection connection,
  2. HubRequest request
)

Runs the in-band handshake over connection for the upgrade request.

Implementation

@override
Future<omnyhub.Principal?> authenticate(
  omnyhub.HandshakeConnection connection,
  omnyhub.HubRequest request,
) async {
  final channel = HandshakeChannel(connection);

  final hello = await channel.expect<Hello>(timeout: timeout);
  if (!ProtocolVersion.current.isCompatibleWith(
    ProtocolVersion.parse(hello.protocolVersion),
  )) {
    // Report before rejecting: a peer that cannot parse our protocol still
    // needs to learn *why* it was turned away.
    channel.send(
      const ProtocolErrorMessage(
        code: ErrorCodes.versionMismatch,
        message: 'incompatible protocol version',
      ),
    );
    throw const omnyhub.UnauthorizedException(
      'incompatible protocol version',
    );
  }

  final challenge = challenges.next();
  channel.send(AuthChallenge(encodeChallenge(challenge)));

  final submit = await channel.expect<AuthSubmit>(timeout: timeout);
  try {
    final principal = await authenticator.authenticate(
      submit.credential,
      challenge: challenge,
    );
    channel.send(
      AuthOk(
        principalId: principal.id.value,
        roles: principal.roles.toList(),
      ),
    );
    // Carry the roles across the boundary so the gateway's registration
    // handler can authorize on them without re-reading the credential.
    return omnyhub.Principal(id: principal.id.value, roles: principal.roles);
  } on AuthException catch (e) {
    channel.send(AuthFail(e.message));
    await onRejected?.call(submit.credential.principal, e.message);
    throw omnyhub.UnauthorizedException(e.message);
  }
}