supertokens/supertokens-flutter

Updating sdk with new Supertokens APIs

Closed this issue · 0 comments

Findings

During our testing with the default http client (dart: http package) we figured out internally the http package calls the http.send(Request) function, where in the get, put, post, etc methods create the appropriate Request object and pass it down to the send which finally makes the network request.

We tested this by extending the base client and overriding the send function to print a string and call the send function from the super class, then we called the get, post, put, methods from the new class. This resulted in still printing the string.

import 'package:http/http.dart' as http;

class CustomClient extends http.BaseClient {
  late final http.Client _inner;

  Future<http.StreamedResponse> send(http.BaseRequest request) {
    print('send method called');
    return _inner.send(request);
  }
}
var client = CustomClient();
Uri uri = Uri.parse("localhost:5000/");
client.get(uri);

Proposed Solution

In the above test we simply created an object of the custom client, but we want to write our SDK in complete parity with the official http client. Hence we will architect the sdk in a way that we also export the functions required to send requests. Along with get, post, put,etc. Function we'll also export the custom client which will give the user access to the following functions to better interact with the API.

Along with a few functions specific to supertokens API, these functions being

  • signOut()
  • getUserId()
  • doesSessionExists()
  • getTokenPayloadSecurely()
  • attemptRefreshingSession()

Here's what using the http package to make a get request looks like.

import 'package:http/http.dart' as http;

void main() async {
  Uri url = Uri.parse('https://try.supertokens.com');
  var resp = await http.get(url);
}

The following is what you need to do to make replicate similar behaviour

import 'package:supertokens/supertokens-http-client.dart' as http;

void main() async {
  Uri url = Uri.parse('https://try.supertokens.com');
  var resp = await http.get(url);
}

As you can see the only change is the import statement, you don't need to change anything else, we follow similar rules with the client as well.

Flow of the new SDK

Proposed SDK follows this flow:

Initial step requires initiate the Supertoken class

Suupertokens.init({
    required String apiDomain,  // Domain where the supertokens backend resides
    String? apiBasePath,  // path for the authentication endpoints
    int sessionExpiredStatusCode = 401,  // http Status code for session expire response
    String? cookieDomain,  
    Function(Eventype)? eventHandler,   // voidCallback ran for various events (events listed below)
    Function(APIAction, http.Request)? preAPIHook,  // callback ran before sending the request to supertokens
    Function(APIAction, http.Request, http.Response)? postAPIHook,  // callback ran after response received from supertokens
})

** Event types for eventHandler

enum Eventype {
  SIGN_OUT,
  REFRESH_SESSION,
  SESSION_CREATED,
  ACCESS_TOKEN_PAYLOAD_UPDATED,
  UNAUTHORISED
}

This can be followed by checking if a session exists or not

Supertokens.doesSessionExist();

Following this we can import the supertokens http client and use the http functions as is

import 'package:supertokens/supertokens-http-client.dart' as http;

void main() async {
  Uri url = Uri.parse('https://try.supertokens.com');
  var resp = await http.get(url);
}