onAuthenticate method

  1. @override
Future<AuthResult> onAuthenticate(
  1. AuthenticatorContext context,
  2. AuthenticateMessage message
)
override

Handles AUTHENTICATE response after a challenge.

Implementation

@override
Future<AuthResult> onAuthenticate(
  AuthenticatorContext context,
  AuthenticateMessage message,
) async {
  final pending = _pending;
  _pending = null;
  if (pending == null) {
    return AuthResult.failure(
      const AuthFailure(
        reason: wamp_core.Error.protocolViolation,
        message: 'AUTHENTICATE received without remote challenge',
      ),
    );
  }

  if (_config.challengeTimeoutMs > 0) {
    final expiresAt = pending.issuedAt.add(
      Duration(milliseconds: _config.challengeTimeoutMs),
    );
    if (DateTime.now().isAfter(expiresAt)) {
      await _notifyAbort(context, pending, reason: 'challenge_timeout');
      return AuthResult.failure(
        const AuthFailure(
          reason: wamp_core.Error.authenticationFailed,
          message: 'Remote authentication challenge expired',
        ),
      );
    }
  }

  if (pending.shouldFail) {
    return AuthResult.failure(
      pending.failure ??
          const AuthFailure(
            reason: wamp_core.Error.authenticationFailed,
            message: 'Remote authentication rejected',
          ),
    );
  }

  final rateLimitFailure = _guardRateLimit(pending.authId);
  if (rateLimitFailure != null) {
    return AuthResult.failure(rateLimitFailure);
  }

  final handle = _handleForId(pending.delegateId);
  if (handle == null) {
    return AuthResult.failure(
      const AuthFailure(
        reason: wamp_core.Error.notAuthorized,
        message: 'Remote authenticator delegate no longer available',
      ),
    );
  }
  if (!handle.isAvailable(DateTime.now())) {
    return AuthResult.failure(
      const AuthFailure(
        reason: wamp_core.Error.notAuthorized,
        message: 'Remote authenticator delegate temporarily unavailable',
      ),
    );
  }

  RemoteAuthenticateResponse response;
  try {
    response = await handle.delegate.onAuthenticate(
      RemoteAuthenticateRequest(
        realmSettings: _config.realm,
        context: context,
        authId: pending.authId,
        authenticate: message,
        options: _config.options,
        transactionId: pending.transactionId,
      ),
    );
    handle.markSuccess();
  } on RemoteDelegateUnavailableException catch (_) {
    handle.markFailure(DateTime.now(), _config.delegateRetryDelay);
    return AuthResult.failure(
      const AuthFailure(
        reason: wamp_core.Error.notAuthorized,
        message: 'Remote authenticator delegate unavailable',
      ),
    );
  } catch (_) {
    handle.markFailure(DateTime.now(), _config.delegateRetryDelay);
    return AuthResult.failure(
      const AuthFailure(
        reason: wamp_core.Error.notAuthorized,
        message: 'Remote authenticator invocation failed',
      ),
    );
  }

  try {
    switch (response.status) {
      case RemoteAuthenticateStatus.success:
        final success = _sanitizeSuccess(response.success!);
        final failure = _validateSuccess(success);
        if (failure != null) {
          _registerFailure(pending.authId);
          return AuthResult.failure(failure);
        }
        _registerSuccess(pending.authId);
        return AuthResult.success(success);
      case RemoteAuthenticateStatus.failure:
        _registerFailure(pending.authId);
        return AuthResult.failure(_sanitizeFailure(response.failure!));
    }
  } on _RemoteSchemaException catch (error) {
    _registerFailure(pending.authId);
    return AuthResult.failure(
      AuthFailure(
        reason: wamp_core.Error.notAuthorized,
        message: error.message,
      ),
    );
  }
}