🐈
【Flutter/Dart】SwitchBot API v1.1 httpsリクエスト時の認証に関するコード
はじめに
Flutter, Dart から SwitchBot API v1.1 を利用するにあたり、https リクエスト時の認証について具体的なコードを記載します。
注意点
コード
test/get_device_list_data_test.dart
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:logger/logger.dart';
void main() {
test('getDeviceListData', () async {
// logger
final logger = Logger();
// signature生成にあたり必要な情報
const token = "SwitchBotアプリ - プロフィール - 設定 - 開発者向けオプション - トークンの値を指定";
const secret = "SwitchBotアプリ - プロフィール - 設定 - 開発者向けオプション - クライアントシークレットの値を指定";
const nonce = ""; // 指定必須でない
final dateTimeNowEpoch = DateTime.now().millisecondsSinceEpoch;
logger.d(
"token: $token,\n secret: $secret,\n nonce: $nonce,\n dateTimeNowEpoch: $dateTimeNowEpoch");
String createSignature() {
// logger
final logger = Logger();
// epochからDateTimeへ変換し、日時を確認
final epochToDateTime =
DateTime.fromMillisecondsSinceEpoch(dateTimeNowEpoch);
String message = "epochからDateTimeへ変換した時刻: ";
message += "$epochToDateTime";
message += "\n ※時計がズレてると適切なsignatureが生成できず、結果、データ取得失敗する。";
logger.d(message);
// secretを文字列からバイト列に変換し、keyとする
final key = utf8.encode(secret);
// ハッシュ関数とkeyを引数に渡して、HMAC生成
// HMAC-SHA256
final hmacSha256 = Hmac(sha256, key);
logger.d("key: $key,\n secret: $hmacSha256");
// signatureの元データ作成
final signatureSourceData = "$token$dateTimeNowEpoch$nonce";
// signatureの元データを文字列からバイト列に変換
final signatureSourceDataByteArray = utf8.encode(signatureSourceData);
logger.d(
"signatureSourceData: $signatureSourceData,\n signatureSourceDataByteArray: $signatureSourceDataByteArray");
// signatureの元データのバイト列をHMACに渡してハッシュ値生成
final digest = hmacSha256.convert(signatureSourceDataByteArray);
// ハッシュ値のバイト列をbase64エンコードしてsignature生成
final digestBytes = digest.bytes;
final signature = base64.encode(digestBytes);
logger.d(
"digest: $digest,\n digestBytes: $digestBytes,\n signature: $signature");
return signature;
}
Future<Response> getDeviceListData() async {
// logger
final logger = Logger();
// request url
const url = 'https://api.switch-bot.com/v1.1/devices';
// request header
final Map<String, String> headers = {
'Authorization': token,
'sign': createSignature(),
'nonce': nonce,
't': dateTimeNowEpoch.toString(),
'Content-Type': 'application/json'
};
// dioインスタンス化
final dio = Dio();
// request, responseのheader情報をコンソール出力する設定
dio.interceptors.add(LogInterceptor());
try {
final response = await dio.get(
url,
options: Options(
headers: headers,
),
);
return response;
} catch (e) {
logger.d("response error: $e");
rethrow;
}
}
final response = await getDeviceListData();
logger.d("response: $response");
});
}
背景
最近、自宅に SiwtchBot を導入しました。
また、同じタイミングで、FlutterKaigi 2022
で、下記の発表を視聴しました。
FlutterKaigi 2022 Day 3
Flutter が拓くハードウェアの世界
SwitchBot API + Raspberry Pi,センサー を組み合わせて、SwitchBot のラインナップを独自に拡張できそうだなと想像しました。
そして、その実装を Flutter,Dart で行えそうな点が、Flutter,Dart 学習の題材としても面白そうに感じ、取っ掛かりとなる SwitchBot API の認証について、記事を書きました。
Discussion