authorize static method

Future<bool> authorize(
  1. String clientId,
  2. String clientSecret,
  3. List<String> scopes, {
  4. String redirectUri = 'http://localhost:65738/callback',
  5. PlanningCenterAuthRedirector? redirector,
})

Use OAuth2 to authorize Scopes should be one or more of the following: api, calendar, check_ins, giving, groups, people, services, webhooks ... for some reason, the webhooks scope gives an error

redirectUri must be registered on Planning Center's API dashboard for the client id and secret example: 'http://localhost:64738/pco_callback' example: 'myappcallback://pcocallback'

redirector must be a function that takes a String and returns an auth token as a Future

Future<String> oAuthCodeLocalhostRedirector(url) {
  // function to launch the url in a browser
  var completer = Completer<String>();
  print('Please open your browser to ${url} to authorize this app.');

  // start a server to listen to the response
  var server = await HttpServer.bind('0.0.0.0', 64738);
  server.listen((HttpRequest req) async {
    req.response.write('Code received!');
    req.response.close();
    server.close();
    print(req.requestedUri);
    print(req.requestedUri.queryParameters);
    print(req.requestedUri.queryParameters);
    completer.complete(req.requestedUri.queryParameters['code']);
  });
  return completer.future;
}
var authorized = await PlanningCenter.authorize(id, secret, ['giving'], oAuthCodeLocalhostRedirector);

Implementation

static Future<bool> authorize(
  String clientId,
  String clientSecret,
  List<String> scopes, {
  String redirectUri = 'http://localhost:65738/callback',
  PlanningCenterAuthRedirector? redirector,
}) async {
  var url =
      '$authEndpoint?client_id=$clientId&redirect_uri=$redirectUri&response_type=code&scope=${scopes.join('+')}';

  // call the redirector and wait for a code response
  redirector ??= localHttpRedirector(redirectUri);
  var code = await redirector(url);
  print('CODE IS: ' + code);

  // now that we have a code
  // call the oauth client
  // with data like this:
  // {
  //   "grant_type": "authorization_code",
  //   "code": "CODE_FROM_STEP_2",
  //   "client_id": "CLIENT_ID",
  //   "client_secret": "CLIENT_SECRET",
  //   "redirect_uri": "https://example.com/auth/complete"
  // }
  var res = await http.post(Uri.parse(tokenEndpoint),
      headers: {'Content-Type': 'application/json'},
      body: json.encode({
        'grant_type': 'authorization_code',
        'code': code,
        'client_id': clientId,
        'client_secret': clientSecret,
        'redirect_uri': redirectUri,
      }));

  /// the response will look like this:
  // {
  //   "access_token": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  //   "token_type": "bearer",
  //   "expires_in": 7200,
  //   "refresh_token": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  //   "scope": "people",
  //   "created_at": 1469553476
  // }
  // create a credentials object
  if (res.statusCode == 200) {
    var data = json.decode(res.body);
    var credentials = PlanningCenterCredentials.fromJson(data);
    instance =
        PlanningCenter._withCredentials(clientId, clientSecret, credentials);
    return true;
  }
  print(res.statusCode);
  print(res.body);
  return false;

  // use the access token like this:
  // 'Authorization: Bearer 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'

  // refresh tokens like this:
  // POST https://api.planningcenteronline.com/oauth/token
  // {
  //   "client_id": "<your application client id>",
  //   "client_secret": "<your application secret>",
  //   "refresh_token": "<your access token refresh token>",
  //   "grant_type": "refresh_token"
  // }
  // open simple web server
  // wait for the server to call back
}