authenticate method
Authenticates against the server.
This is designed with package:angel_auth in mind.
The type is appended to the authEndpoint, ex. local becomes /auth/local.
The given credentials are sent to server as-is; the request body is sent as JSON.
Implementation
@override
Future<AngelAuthResult> authenticate(
    {String? type, credentials, String authEndpoint = '/auth'}) async {
  type ??= 'token';
  var segments = baseUrl.pathSegments
      .followedBy(_p.split(authEndpoint))
      .followedBy([type]);
  //var p1 = p.joinAll(segments).replaceAll('\\', '/');
  var url = baseUrl.replace(path: _p.joinAll(segments));
  http.Response response;
  if (credentials != null) {
    response = await post(url,
        body: json.encode(credentials), headers: _writeHeaders);
  } else {
    response = await post(url, headers: _writeHeaders);
  }
  if (_invalid(response)) {
    throw failure(response);
  }
  try {
    //var v = json.decode(response.body);
    _log.info(response.headers);
    var v = jsonDecode(response.body);
    if (v is! Map || !v.containsKey('data') || !v.containsKey('token')) {
      throw AngelHttpException.notAuthenticated(
          message: "Auth endpoint '$url' did not return a proper response.");
    }
    var r = AngelAuthResult.fromMap(v);
    _onAuthenticated.add(r);
    return r;
  } on AngelHttpException {
    rethrow;
  } catch (e, st) {
    _log.severe('Authentication failed');
    throw failure(response, error: e, stack: st);
  }
}