Skip to content

Create custom SASL (authentication) mechanism

Michael Spiss edited this page Mar 7, 2019 · 1 revision

To create a custom authentication mechanism you have to create a class that extends ImapSaslMechanism. The following example walks you through the cration of the ImapLoginAuth class:

// normally you would need an import 'package:imap_client/imap_client.dart';

class ImapLoginAuth extends ImapSaslMechanism {
  /*
  Constructor, which sets the mechanism's id (name) to "login".
  This will be used to check if the server supports it.
  Not case-sensitive.
   */
  ImapLoginAuth() : super("login");

  /*
  This method will be called every time the server responds
  with another command continue request. [response] is the
  data sent with the request.
  The returned String will be sent to the server. Do not
  append a CRLF (\r\n) linebreak, this will be done
  automatically.
   */
  @override
  String challenge(String response) {
    // TODO
  }
}

Our authentication mechanism needs a password and username which must be entered on instantiation.

class ImapLoginAuth extends ImapSaslMechanism {
  final String _username;
  final String _password;

  ImapLoginAuth(this._username, this._password) : super("login");

  @override
  String challenge(String response) {
    // TODO
  }
}

The last step is implementing the behaviour. The login mechanism consists of two steps:

  1. Username in base64
  2. Password in base64

base64 has already been imported on package-level, so we don't have to explicitly have to import it here.

class ImapLoginAuth extends ImapSaslMechanism {
  final String _username;
  final String _password;
  int _step = 1; // step counter

  ImapLoginAuth(this._username, this._password) : super("login");

  @override
  String challenge(String response) {
    if (_step == 1) { 
      _step++; // increase counter to next step
      return base64.encode(_username.codeUnits); // sends base64 encoded username
    } else {
      _isAuthenticated = true; // marks this login as completed
      return base64.encode(_password.codeUnits); // sends base64 encoded password
    }
  }
}

Please note the _isAuthenticated = true;. This must be set during the last step to prevent errors due to incorrect server requests. If the server is still not satisfied and confirms the authentication as complete, an exception will be thrown.

Clone this wiki locally