This the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Architecture of the @platform

The components of the @platform architecture

The picture below provides a great way to visualize just how much thought has gone into making the life of a developer on the @platform that much easier! Functional Architecture

If you’re wondering what the difference between what the @platform consists of and what the @protocol consists of, look no further!

The @platform, which has been created on top of the @protocol consists of three major segments of developer tools. These segments consists of; Services, Libraries, and Widgets

1 - Services provided by the @platform

Important services provided by the @platform

Data Caching & Encryption

Data that others have shared with an @sign owner is cached on the @sign owner’s device’s local keystore if permitted.

Learn more

Notification

Notification is a mechanism which enables an @sign to share data with another @sign. The data shared is end to end encrypted. @sign owner can query the status of the notification.

Learn more

Onboarding

The onboarding process is responsible for creating the authenticating keys for a new @sign or retrieving the authenticating keys of an existing @sign from the keys file provided by the @sign owner. It also synchronizes the data between mobile apps and the cloud secondary server.

Learn more

Peer-to-Peer Streams

Streams enable transferring of files between the @sign’s through a secure and dedicated socket between sender and receiver. The files can be a text documents, images, audio-video files etc. The stream transfers are end to end encrypted.

Learn more

Persistence

The persistence defines the interfaces on how the data in @protocol is stored.

Learn more

Synchronization

Synchronization is a process to keep the data in mobile apps and @sign server identical.

Learn more

2 - Libraries

Find the list of libraries the @platform has to offer here!

at_persistence_spec

A Dart library containing abstract classes that defines what an implementation of the persistence layer is responsible for. This can be used to guide implementation of other persistence solutions for servers or SDKs as desired.

Learn more

at_commons

A library of Dart and Flutter utility classes that are used across other components of the @‎platform.

Learn more

at_common_flutter

A Flutter package to provide common widgets used by other @‎platform Flutter packages.

Learn more

at_client

The at_client library is the non-platform specific Client SDK which provides the essential methods for building an app using the @protocol.

Learn more

at_lookup

A Dart library that contains the core commands that can be used with a secondary server (scan, update, lookup, llookup, plookup, etc.)

Learn more

at_persistence_secondary_server

A Dart library with the implementation classes for the persistence layer of the secondary server.

Learn more

at_server_status

A Dart library that provides a means to check on the status of the @‎root server as well as the secondary server for any particular @‎sign.

Learn more

at_utils

A Dart library that contains various utility classes such as atSign, atmetadata, configuration, and logger.

Learn more

at_backupkey_flutter

A Flutter plugin project for saving the backup key of any @‎sign that is being onboarded with @‎platform apps. The backup key can be used to authenticate in other @‎platform apps.

Learn more

at_onboarding_flutter

A Flutter plugin project for onboarding any @‎sign in @‎platform apps with ease. Provides a QRscanner option and an upload key file option to authenticate.

Learn more

at_client_mobile

A Flutter extension to the at_client library which adds support for mobile, desktop and IoT devices.

Learn more

at_contacts_flutter

A Flutter plugin project to provide ease of managing contacts for an @‎sign using @p‎latform.

Learn more

at_chat_flutter

A Flutter plugin project to provide a chat feature between @‎signs built on the @‎platform to any Flutter application.

Learn more

at_demo_data

A Dart library that contains test data, testable @‎sign credentials and demo environment variables that can be used for writing demo apps and testing with the local test environment.

Learn more

at_contacts_group_flutter

A Flutter plugin project to provide group functionality with contacts using @‎platform.

Learn more

at_location_flutter

A Flutter plugin project to share locations between two @‎signs and track them on OSM (OpenStreetMap).

Learn more

at_utf7

Provides methods to encode/decode strings to/from the utf7 format as defined in rfc 2152

Learn more

at_contact

A Dart library for managing contact data that developers can use for their applications.

Learn more

at_events_flutter

A Flutter plugin project to manage events (time, place and attendees) using the @‎platform.

Learn more

at_base2e15

binary-to-text encoding schemes that represent binary data in an unicode string format, each unicode character represent 15 bits of binary data.

Learn more

at_follows_flutter

A Flutter plugin project that provides a basic social “follows” functionality for any @sign. Provides a list of @signs that follow you (followers) as well as the @signs that you follow (following) with the option to unfollow them.

Learn more

at_server_spec

A Dart library containing abstract classes that defines what implementations of the root and secondary servers are responsible for.

Learn more

at_map

A new Flutter plugin.

Learn more

3 - The @platform widgets

Build your app more quickly with these @platform widgets

The Onboarding Widget

Onboarding for the first time with the @platform isn’t as simple as choosing your @sign from a dropdown menu and clicking “Login” (after all, how would the application know where to retrieve your authentication keys from a given @sign?).

Implementing onboarding from scratch would be painstakingly difficult. Not only would you have to code the PKAM logic, but you would also have to build your own QR code scanner to extract the CRAM (Challenge-Response Authentication Mechanism) key from your @sign’s QR code generated on our website! The @ Company realized this very quickly, so we developed the at_onboarding_flutter widget to help developers who want to build production-level apps that onboard real @signs (AKA @signs that you get from our .com site).

Learn more about the onboarding widget here!

Use this package as a library

at_onboarding_flutter: ^1.0.0+4

The “Onboarding” widget is very handy in that you do not need to call the “onboard” or “authenticate” methods from the service file of the application to get it running. Instead, it will ask us to specify the following parameters (descriptions for each parameter are written in the comments):

class Onboarding {
 ///Required field as for navigation.
 final BuildContext context;

 ///Onboards the given [atsign] if not null.
 ///If [atsign] is null then it takes the atsign from keychain.
 ///If [atsign] is empty then it directly jumps into authenticate 
 ///without performing onboarding. (or)
 ///If [atsign] is empty then it just presents pairAtSign screen 
 ///without onboarding the atsign. (or)
 ///Just provide an empty string for ignoring existing atsign in 
 ///keychain or app's atsign.
 final String atsign;

 ///The atClientPreference [required] to continue with the onboarding.   
 ///atClientPreference is an instance of a class in the  
 ///at_client_mobile library that stores a number of important 
 ///attributes like the namespace of the application, the CRAM key of  
 ///an @sign, the root domain we want the project to communicate 
 ///with, and so on. 
 final AtClientPreference atClientPreference;

 ///The root domain for our project. By default, the plugin connects 
 ///to [root.atsign.org] to perform onboarding.
 final String domain;

 ///The color of the screen to match with the app's aesthetics. 
 ///default it is [black].
 final Color appColor;

 ///If logo is not null, then it displays the widget on the left side 
 ///of appbar. Else, it displays nothing.
 final Widget logo;

 ///Function returns atClientServiceMap on successful onboarding along 
 ///with onboarded @sign. Assign these returned values to the relevant 
 ///variables in your project’s service file.
 final Function(Map<String, AtClientService>, String) onboard;

 ///Function returns error if onboarding fails for an @sign.
 final Function(Object) onError;

 ///After successful onboarding, the app will be redirected to this 
 ///screen if it is not null.
 final Widget nextScreen;

 ///After the first successful onboarding, the app will get redirected 
 ///to this screen if not null.
 final Widget fistTimeAuthNextScreen;

 final AtSignLogger _logger = AtSignLogger('At Onboarding Flutter');

 Onboarding({Key key,
   @required this.context,
   this.atsign,
   @required this.onboard,
   @required this.onError,
   this.nextScreen,
   this.fistTimeAuthNextScreen,
   @required this.atClientPreference,
   this.appColor,
   this.logo,
   this.domain})
 ...
}

To see an actual implementation of the onboarding widget, let’s revisit the _login function in the at_hello_world app with some updated code:

/// Return an “Onboarding” widget that walks the individual through
/// the onboarding procedure for any real @sign.
_login() async {
 return Onboarding(
     context: context,
     /// Ensure that the “root” attribute is assigned to 
     /// “root.atsign.org” 
     domain: AtConfig.root
     atClientPreference: await 
        _serverDemoService.getAtClientPreference(),
     appColor: Color.fromARGB(255, 240, 94, 62),
     onboard: (atClientServiceMap, atsign) {
       _serverDemoService.atClientServiceMap = atClientServiceMap;
       _serverDemoService.atSign = atsign;
     },
     onError: (error) {
       print(error);
     },
     /// Remove the constructor in HomeScreen. You can call the @sign
     /// with the getAtSign() method in the service file. 
     nextScreen: HomeScreen(),
 );
}

All of the parameters in the “Onboarding” widget can be populated very easily with either methods from the project’s service file (e.g. getAtClientPreference()) or special variables from the app itself (e.g. context). “Onboarding” is capable of handling all instances of an @sign (e.g. a particular @sign does not exist, a particular @sign exists but needs to be paired with a QR code to the device, a particular @sign exists and its keys are already in the device’s keychain manager). By using this widget, what would have taken several screens and many lines of code can be completely bypassed with a single return statement!

That’s all for the “Onboarding” widget. Before moving on from this subsection, we highly recommend implementing the widget in your own application and onboarding a real @sign to understand its intended user journey. If you’re interested, these are the steps to implement the “Onboarding” widget in the at_hello_world project:

Update your Android Studio, Flutter SDK, and Dart SDK to their latest versions. Place the at_onboarding_flutter dependency in pubspec.yaml. Follow the setup procedure for the “Onboarding” widget in the “AndroidManifest” (android -> app -> src -> main -> AndroidManifest.xml) and “gradle” file (android -> app -> build.gradle) of the at_hello_world project. You may also need to update the “classpath” of the android gradle build tool to 3.5.4 (this can be done by going to android -> gradle -> build.gradle and editing the first classpath in the “dependencies” brackets). This must be completed in order to set up the permission for the QR code scanner to access your camera. Find those steps on the pub.dev site for at_onboarding_flutter here. Get a free @sign from atsign.com. Generate its QR code, and drag/drop the created file directly into the emulator. Confirm that the QR code image appears in the “Files” or “Drive” app of the emulator you’re using (assuming that it is an Android emulator). In “at_conf.dart”, update the “root” variable from ‘vip.ve.atsign.zone’ to ‘root.atsign.org’. This ensures that the project points to the domain that is used in production as opposed to the one for the virtual environment. Replace the existing code in the login() function with what we wrote above. Double-check that no errors arise (you’ll likely have to tweak the names of a couple of methods in the service file, because some of them begin with the “” private designation). Fire the app on your emulator. Although the dropdown menu will still appear (since we didn’t change any of that code), we will not be authenticating with any of the testable @signs. If you’d like, simply remove the “DropdownButton” widget so that we can eliminate the list of testable @signs. Click on the “Login” button. Assuming that you haven’t previously authenticated with a real @sign, the “Onboarding” widget should prompt you with a request to upload your QR code. Upload the QR code you saved onto the emulator earlier and wait for the authentication to complete. If no errors form, the “Onboarding” widget should take you seamlessly to the “Home” screen, where you can add & retrieve key/value pairs directly from your very own secondary server! The next time you authenticate (i.e. restart the application), the “Onboarding” widget should detect the authentication keys placed in your device’s keychain manager and guide you directly to the “Home” screen.

The Chatting Widget

One of the many things you can do after successfully authenticating an @sign is providing one-to-one text messaging! To do this, you’ll need the at_chat_flutter widget.

The at_chat_flutter widget offers a messaging experience that is unique to the @platform. In a traditional messaging application, your texts are stored in a remote database and the person you’re pinging pulls the texts from there (a bit unsettling if you think about it). Of course, there is no such thing as a remote database in the @platform, so we had to be a bit clever coming up with a messaging scheme. In a nutshell, your text messages are not “sent” but rather “shared” with another @sign. All your texts are stored securely in your secondary server and never leave; if you decide to send a message to someone, that person is given permission to view that text via the notify verb, which will be covered in the next section on advanced @platform verbs.

Learn more about the chatting widget here!

Use this package as a library

at_chat_flutter: ^1.0.1

Although this messaging dynamic might sound a bit involved, set up is quite easy! To get a feel for using the “Chatting” widget, it’s best to follow along with the at_chats demo application.

The general flow of all @platform widgets is onboarding an @sign => initializing the service object => creating the actual widgets. Assuming we’ve already onboarded an @sign, let’s look at the steps to initialize our chat service:

(The following code snippets are taken directly from at_chats. While there will be explanations, don’t worry too much about all the variables!)

getAtSignAndInitializeChat() async {
 /// In the at_chats app, the onboarded @sign is displayed at the top 
 /// of the Second Screen. We set that @sign to [currentAtSign].
 String currentAtSign = await clientSdkService.getAtSign();
 /// Set [activeAtSign], which is the variable that gets displayed, to
 /// [currentAtSign] using setState(() {}).
 setState(() {
   activeAtSign = currentAtSign;
 });
 /// Initialize a List of Strings called [allAtSigns] that we will 
 /// eventually display in the dropdown on the Second Screen. Here, we 
 /// simply pull an existing List from the at_demo_data dependency.
 List<String> allAtSigns = at_demo_data.allAtsigns;
 /// We want to remove the [activeAtSign] from this List because we 
 /// can't chat with ourselves!
 allAtSigns.remove(activeAtSign);
 /// Again, call setState(() {}) to assign [allAtSigns] to the 
 /// variable [atSigns] that will be used in the dropdown widget.
 setState(() {
   atSigns = allAtSigns;
 });
 /// This is the only at_chat_flutter related function! 
 /// initializeChatService takes in an AtClientImpl instance, the 
 /// currently onboarded @sign, and the root domain for this project. 
 /// As its name suggest, this function will prepare the chat service 
 /// for us.
 initializeChatService(
     clientSdkService.atClientServiceInstance.atClient, activeAtSign,
     rootDomain: MixedConstants.ROOT_DOMAIN);
}


Because getAtSignandInitializeChat() is an initialization function, it is best to call it in the initState() function at the top of the _SecondScreenState class. The only other thing we need to do before calling the Chatting widget is deciding who wed like to chat with.

setAtsignToChatWith() {
 /// This function is as simple as calling the setChatWithAtSign() 
 /// function from the at_chat_flutter dependency with 
 /// [chatWithAtSign] passed in! [chatWithAtSign] is simply the @sign 
 /// that a user selects from the dropdown on the screen.
 setChatWithAtSign(chatWithAtSign);
}

We won’t want to call setAtsignToChatWith() in initState() because the function won’t know which @sign we’re communicating with until the individual selects it from the dropdown widget. Instead, it makes the most sense to place this function in the button (FlatButton for the at_chats app) that determines the navigation to the next screen. For at_chats, clicking the “Chat options” FlatButton will check to make sure that the “chatWithAtSign” variable is populated before it calls setAtsignToChatWith() and switches the “showOptions” variable to true, which allows the individual to see the two options for viewing the chatbox.

Now, for the moment of truth: once we’ve initialized the chat service, how do we create the actual chat screen? In most tutorials, you’ll probably be guided through a UI-heavy demo of different chatbox components and pairing a backend service. With the @platform, however, it’s really just one line of code:

(This snippet is directly from third_screen.dart in the at_chats project!)

class _ThirdScreenState extends State<ThirdScreen> {
 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(title: Text('Chat')),
     /// You can simply set the body parameter of Scaffold widget
     /// to the ChatScreen widget from the at_chat_flutter dependency!
     body: ChatScreen(
       /// Optional parameters to customize your ChatScreen widget.
       /// You can find the full list of parameters in our Github 
       /// under the at_widgets repository.
       height: MediaQuery.of(context).size.height,
       incomingMessageColor: Colors.blue[100],
       outgoingMessageColor: Colors.green[100],
       isScreen: true,
     ),
   );
 }
}

By initializing the chat service and calling the ChatScreen() widget, you can make a fully-functioning one-to-one messaging application! While the ChatScreen widget offers a number of ways to customize your chatbox, if you’d like to build your own widget from scratch, you can use the at_chat_flutter dependency as a basis for creating your personal chat library that works with the @platform.

The Contacts Widget

Too many @signs to keep track of? That’s no problem with the at_contacts_flutter widget! Simply add the at_contacts_flutter dependency to your project, and you’ll be capable of performing several actions with your @sign contacts.

Learn more about the contacts widget here!

Use this package as a library

at_contacts_flutter: ^1.0.0

In order to implement the at_contacts_flutter widget, you must first, of course, create an AtClientService instance and authenticate an @sign.

After you have successfully onboarded an @sign, you can add a page where you may choose to show your contacts or show your blocked contacts. On load of this page, you will want to initialize the contacts service, similar to initializing the at_chats service. The contacts service needs to be initialised with the atClient from the AtClientService, current @sign, and the root domain.

initializeContactsService(
clientSdkService.atClientServiceInstance.atClient,
activeAtSign,
rootDomain: MixedConstants.ROOT_DOMAIN);

After successfully initializing the contact service, you will now be capable of getting the list of contacts that exist for the authenticated @sign. This is as easy as simply passing the contacts into a variable.

var _result = await _contactService.fetchContacts();

This fetchContacts() function exists in the _contactService file, which can be found within the at_contact’s ‘services’ folder. If you want to do more than just get the list of contacts, you have the capability of adding more contacts to this list, in addition to removing or blocking any. In order to retrieve the list of blocked contacts, it is similar to retrieving the regular list of contacts. The code from the example app demonstrates this well.

Class BlockedScreen extends StatefulWidget{
  @override
  _BlockedScreenState createState() => _BlockedScreenState();
}

class _BlockedScreenState extends State<BlockedScreen> {
  // Here, we are initializing a ContactService object in order
  // to call our list of blocked contacts later within our widget.
  // Refer to how the list is populated within the example app
  ContactService _contactService;
  @override 
  void initState() {
    _contactService = ContactService();
    _contactService.fetchBlockContactList();
    super.initState();
}

To block a contact, it is as easy as calling the blockUnblock method. If a contact is blocked, it will unblock the contact. If the contact is not blocked, it will block it for you.

await _contactService.blockUnblockContact(contact: _atSign_you_wish_toBlockUnblock);

After you block a contact, you may wish to have that contact removed from the list. All you have to do is simply implement the code below:

await _contactService.deleteAtSign(atSign: _atSign_you_wish_toRemove);

Along with the previously stated functionalities, the at_contacts_flutter package also provides the UI so there’s no need to set up a separate page to house these functions!

The Location Widget

One of the more common mobile application features is geolocation. Even if your app doesn’t explicitly use a map, with an individual’s permission, you can use their location for a variety of relevant recommendations like shops, restaurants, and nearby events. The at_location_flutter dependency is a powerful abstraction for geolocation with the @platform, and we’ll see some use cases of its most common functions.

Learn more about the contacts widget here!

Use this package as a library

at_location_flutter: ^1.0.3

Once we’ve successfully onboarded an @sign, let’s initialize our location service. For this subsection, we’ll base our code off of the example app in the Github directory for at_location_flutter.

initService() {
 /// A different way to call the currently onboarded @sign. In 
 /// practice, it is better to write a getAtSign() method in your 
 /// project's service file. This variable is used to display the 
 /// onboarded @sign at the top of the screen.
 activeAtSign =
     clientSdkService.atClientServiceInstance.atClient.currentAtSign;
 /// initializeLocationService() is a function from 
 /// at_location_flutter that's located in init_location_service.dart. 
 /// This function takes  in an AtClientImpl instance, the currently
 /// onboarded @sign, a GlobalKey to access the NavigatorState (for 
 /// navigating between routes), and the domain we want to point our 
 /// project to.
 initializeLocationService(
     clientSdkService.atClientServiceInstance.atClient,
     activeAtSign,
     NavService.navKey,
     rootDomain: MixedConstants.ROOT_DOMAIN
 );
}

As is the case with most @platform widgets, you can call this initialization function in the initState() function of your class.

Once our location service is ready to go, you can let the authenticated individual freely send and request locations to/from other @sign customers. These capabilities are made possible with the “sendShareLocationNotification” and “send RequestLocationNotification” functions (which exist in the init_location_service.dart file).

ElevatedButton(
 onPressed: () async {
   /// checkAtsign() is a helper functions that ensures the entered 
   /// @sign (for sending/requesting a location) is valid. It is
   /// unique to the example app in the at_location_flutter Github
   /// directory.
   bool result = await checkAtsign();
   if (!result) {
     CustomToast().show('@sign not valid', context);
     return;
   }
   /// This function takes in the @sign receiving the location
   /// notification as well as the duration (in minutes) of
   /// how long this shared location persists on the receiving
   /// @sign's secondary server.
   await sendShareLocationNotification(receiver, 30);
 },
 child: Text('Send Location'),
),
ElevatedButton(
 onPressed: () async {
   bool result = await checkAtsign();
   if (!result) {
     CustomToast().show('@sign not valid', context);
     return;
   }
   /// Similar to the previous function,
   /// "sendRequestLocationNotification" needs the @sign to
   /// request a location from.
   await sendRequestLocationNotification(receiver);
 },
 child: Text('Request Location'),
),

While the above two functions are certainly useful, there is another widget in the at_location_flutter dependency that offers a more elegant UI for sending your location, requesting locations, and even visualizing your current position. That widget is called “HomeScreen”.

/// When an individual clicks on the ElevatedButton that says “Show 
/// map”, the Navigator will lead them to the HomeScreen().
ElevatedButton(
 onPressed: () {
   Navigator.of(context).push(MaterialPageRoute(
     builder: (BuildContext context) => HomeScreen(),
   ));
 },
 child: Text('Show map'),
),

The HomeScreen displays a map with your location and offers two options (contained in “Task” widgets) that provide more user-friendly versions of the “sendShareLocationNotification” and “send RequestLocationNotification” functions (if you’re curious, these more elegant widgets are called ShareLocationSheet() and RequestLocationSheet() respectively). When you click on one of these tasks, a popup will appear to enter a receiving @sign (and duration for sharing a location), and any task you complete will appear in the bottom white region of the screen with its current status.

That’s all for the “Location” widget! If you want to test the at_location_flutter dependency for yourself, feel free to start by cloning the example app from the at_location_flutter Github repository. For more intricate functions like the location notification stream, our Github would be an excellent place to learn more.

The Events Widget

Like how we regularly share calendar items between our friends, family, and colleagues, it would be very convenient to have a data structure for events that works with the @platform. This is where the at_events_flutter dependency comes into play.

Learn more about the events widget here!

Use this package as a library

at_events_flutter: ^1.0.0

The first step, as you very well may have guessed, is the initialization of the event service. Like the previous few widgets discussed above, we’ll be examining snippets from the example app in the at_event_flutter Github directory throughout this subsection.

initService() {
 activeAtSign =
     clientSdkService.atClientServiceInstance.atClient.currentAtSign;
 /// Unlike most of the initialization functions, our event 
 /// initializer only needs an AtClientImpl instance and an optional 
 /// argument for the root domain.
initialiseEventService(clientSdkService.atClientServiceInstance.atClient,
     rootDomain: MixedConstants.ROOT_DOMAIN);
}

The most important function in the at_event_flutter library is CreateEvent(), which builds an instance of a CreateEvent that can be customized and shared across different @signs:

TextButton(
 onPressed: () {
   /// bottomSheet will return a pop up screen that takes up 90%
   /// of the screen height. 
   bottomSheet(
       CreateEvent(), MediaQuery.of(context).size.height * 0.9);
 },
 child: Container(
   height: 40,
   child:
       Text('Create event', style: TextStyle(color: Colors.black)),
 ),

CreateEvent() is a separate screen in the application that guides an individual through a list of fields they can populate to provide information about their event. If you look into the CreateEvent class, you’ll see that these fields are stored in an object called “eventData”, which is an instance of an EventNotificationModel. It’s full list of attributes is below (the ones with comments are used in the CreateEvent class):

class EventNotificationModel {
 EventNotificationModel();
 String atsignCreator;
 bool isCancelled;
 /// The title of the event.
 String title;
 /// A location serving as the event's venue.
 Venue venue;
 /// An object that stores info like event date, start time, and repeat duration.
 Event event;
 String key;
 AtGroup group;
 bool isSharing;
 bool isUpdate; //when an event data is being updated , this should be true.
 ...
}

“eventData” is a crucial data structure that’s used not just in creating an event but updating and deleting events as well. The init_events_service.dart file illustrates a variety of functions that can be used to perform useful actions on these objects.

One important feature of the example app is its EventList class, which doesn’t come directly with the at_events_flutter dependency:

TextButton(
 onPressed: () {
   Navigator.push(
     context,
     MaterialPageRoute(
       builder: (context) => EventList(),
     ),
   );
 },

This seemingly harmless class is actually doing quite a bit of work behind the scenes! EventList listens to an event stream that comes from an EventService object (a class within the at_event_flutter dependency) and displays them in a ListView format. Clicking on one of these events, you’ll be navigated to a popup of a CreateEvent instance with its “isUpdate” parameter set to true. This allows you to edit and save any event of your choice!

The Backup Keys Widget

When someone uses their @sign for the first time with an @platform app, it is important to have them authenticate with their generated QR code and create a set of backup keys just in case the ones in the keychain manager are lost or if you want to use the same @sign on a different device. The backup keys widget occurs during the “Onboarding” widget.

Learn more about the events widget here!

Use this package as a library

at_onboarding_flutter: ^1.0.0+4

You may notice that in order to get the at_backupKeys_flutter package, you can simply pull from the at_onboarding_flutter widget which houses the at_backupkeys_flutter widget! See below the process of at_onboarding_flutter to see where at_backupkeys_flutter comes into play!

at_cookbook
at_cookbook
at_cookbook

After inputting what @sign you wish to pair, you will need to upload the QR code retrieved from atsign.com. The emulator in the picture is not hooked up to a camera, so a small GIF of a house is there to fill where the camera would be. After successfully uploading and authenticating with the QR code, the backup key widget will be introduced to you! From the save option, you will be prompted to either save your keys to the files folder of the device or upload the keys to an associated Google Drive.

Fortunately, implementing the backup key widget is painless as it is a part of the onboarding widget! If you have already implemented the onboarding widget, there’s no code you need to write!

at_onboarding_flutter

A flutter plugin project for onboarding any @sign in @protocol apps with ease. Provides QRscanner and upload key file option to authenticate.

Learn more

at_chat_flutter

A flutter plugin project to provide chat feature using atsigns and atprotocol.

Learn more

at_common_flutter

A flutter package to provide common widgets used by other atsign flutter packages.

Learn more

at_backupkey_flutter

A flutter plugin project for saving backup key of any @sign that is being onboarded with @protocol apps. Backup key can used to authenticate in any @protocol apps.

Learn more

at_contacts_flutter

A flutter plugin project to provide ease of managing contacts for an atsign using atprotocol.

Learn more

at_contacts_group_flutter

A flutter plugin project to provide the group functionality with contacts using atprotocol.

Learn more

at_location_flutter

A flutter plugin project to share location between two atsigns and track them on OSM (open street maps).

Learn more

at_events_flutter

A flutter plugin project to manage events using the atprotocol.

Learn more

4 - The @protocol verbs

Understand the @platform verbs and their functions

from

The “from” verb is used to tell the secondary server what @sign you claim to be, and the secondary server will respond with a challenge. The challenge will be in the form of a full @ address and a cookie to place at that address. Before giving the challenge it will verify the client SSL certificate. The client SSL certificate has to match the FQDN list in the root server for that @sign in either the CN or SAN fields in the certificate. Learn More

cram

The cram verb is used to authenticate the @sign to the secondary server. On successful request, binds the @sign to the secondary server. The secret is appended to the challenge (response of from verb) and gives a SHA512 digest which serves as an input to the CRAM verb. On successful cram verb request, the @sign is successfully authenticated to the secondary server and allows user to Add/Update, Delete and lookup the keys in their respective secondary servers. We use “cram” authentication for the first time and will create a public/private key pair for pkam authentication for subsequent logins. Learn more

pkam

The pkam( Public Key Authentication Mechanism) verb is used to authenticate the @sign to the secondary server. This is similar to how ssh authentication works. On successful request, binds the @sign to the secondary server.On successful pkam verb request, the @sign is successfully authenticated to the secondary server and allows user to Add/Update, Delete and lookup the keys in their respective secondary servers. Learn more

scan

The “scan” verb scans the available keys. The scan verb when used by unauthenticated @sign user, scans for keys that are publicly available to you.The scan when used by an authenticated user via the cram verb, scans all the available keys on the secondary server. You can use scan verb with regex if you want to get keys matches with the regex. Learn more

lookup

The “lookup” verb allows the lookup of a particular address in the @ handles namespace. The “lookup” verb provides public lookups and specific key look ups when authenticated as a particular @ handle using the “from” and “pol” verbs. If a lookup is valid the resulting information is returned with the data: header and a carriage return and a further @ prompt ready for further commands. If the lookup is not valid then a null is returned again with the data: header. The @sign should be authenticated using the cram verb prior to use the lookup verb. Learn more

plookup

The “plookup” verb, provides a proxied public lookups for a resolver that perhaps is behind a firewall. This will allow a resolver to contact a @ server and have the @ server lookup both public @ handles information. This will be useful in large enterprise environments where they would want all lookups going through a single secondary server for the entity or where a single port needs to be opened through a firewall to lookup @ handles. The @sign should be authenticated using cram verb prior to use the plookup verb. Learn more

llookup

The “llookup” verb can be used to locally lookup keys stored on our secondary server. To perform local look up, the user should be successfully authenticated via the “cram” verb. Learn more

update

The “update” verb is used to create/update the keys in the secondary server. We can create/update both public and private keys. kThe update verb is used to set public responses and specific responses for a particular authenticated users after using the pol verb. The @sign should be authenticated using cram verb prior to use the update verb. Learn more

delete

The “update” verb is used to delete the keys in the secondary server. A delete request must contain the distinguished name of the key to be deleted. The @sign should be authenticated using the cram/pkam verb prior to use the delete verb. Learn more

notify

The “notify” verb used to notify a key to another atsign. The @sign should be authenticated using the cram/pkam verb prior to use the notify verb. You can send a notification to multiple users using “notify:all” command. Also you can list out all the notifications using “notify:list”. Learn more

monitor

The “monitor:” verb is used to monitor either all or specific notification events that are sent using the “notify:” verb. Notifications are both queued and managed by the secondary server, and the status of an individual notification can also be seen. Learn more

stats

The “stats” verb used to get all the available metrics. We can get specific metrics by providing ‘,’ separated list like stats:1,2. If we didn’t provide anything it will return all the metrics information. Learn more

sync

The “sync” verb is used to fetch all the changes after a given commit sequence number from the commit log on the server. This verb is helpful when local and remote secondary servers are not in sync. We can sync only specific keys by providing regex pattern Learn more

config

The “config” verb is used for configuring or viewing an @sign’s block/allow list. ‘from’ verb functionality is dertermined by using the configurations of ‘config’ verb. If an atsign is in block list, secondary server won’t allow it for authentication. Learn more

pol

The “pol” verb allows to switch as another @sign user. To switch as another user, use from:<@sign>(The another @sign user) verb which gives a response as proof:; then use pol verb. On successful authentication, the prompt changes to the another @sign user. If we authenticate to other atsign using pol, we can only access public information available. Learn more