Handle retrieving authorization codes
Added authTokens.dart to connect to Spicerack and Google OAuth2 servers
in order to get access tokens prior to launching Oregano.
Allow developers (developers developers) to add/override url parameters
with /tmp/client_params
Change-Id: I619f24d1fe5e167784e0cff39063709d46046448
diff --git a/package/google/google_oregano/authTokens.dart b/package/google/google_oregano/authTokens.dart
new file mode 100644
index 0000000..0a51ae1
--- /dev/null
+++ b/package/google/google_oregano/authTokens.dart
@@ -0,0 +1,111 @@
+/// Authorize client with Spicerack and OAuth2.0
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:convert';
+
+const String SPICERACK_AUTH =
+ "https://www-googleapis-staging.sandbox.google.com/rpc";
+
+const String separatorFlag = "--separator=";
+
+main(List<String> args) {
+ int now = new DateTime.now().millisecondsSinceEpoch;
+
+ String separator = "&";
+ // I don't want to import a 3rd party arguments parser for a simple script.
+ // Allow the caller to switch between '&flag=' and ' --flag='
+ if (args.length > 0 && args[0].startsWith(separatorFlag) ) {
+ separator = args[0].substring(separatorFlag.length);
+ }
+
+ String serialNumber;
+ ProcessResult rslt = Process.runSync("serial", []);
+ serialNumber = rslt.stdout.trim();
+
+ makeSignature(now).then((String signature) {
+ getAuthCode(serialNumber, signature). then((authResponse) {
+ Map json = JSON.decode(authResponse)['result'];
+ var oauthClientId = json['oauthClientId'];
+ var oauthAddress = json['oauthAddress'];
+ var oauthClientSecret = json['oauthClientSecret'];
+ getOAuth2Tokens(json['authorizationCode'], oauthAddress, oauthClientId,
+ oauthClientSecret).then((tokens) {
+ Map json = JSON.decode(tokens);
+ print(
+ "${separator}clientId=$oauthClientId"
+ "${separator}clientSecret=$oauthClientSecret"
+ "${separator}oauth2Url=$oauthAddress"
+ "${separator}refreshToken=${json['refresh_token']}");
+ });
+ });
+ });
+}
+
+
+/**
+ * Returns the [now], signed with the local device certificate, and base64
+ * encoded. See [getAuthCode]. This is equivalent to the following:
+ * $(date +%s | openssl rsautl -sign -inkey /etc/ssl/private/device.key | openssl base64 -A)
+ */
+Future<String> makeSignature(int now) {
+ return Process.start("openssl",
+ ["rsautl", "-sign", "-inkey", "/etc/ssl/private/device.key"])
+ .then((Process sign) {
+ sign.stdin.write("$now");
+ sign.stdin.close();
+ return Process.start("openssl", ["base64", "-A"])
+ .then((Process base64) {
+ sign.stdout.pipe(base64.stdin);
+ return base64.stdout.transform(new Utf8Decoder()).join()
+ .then((String encOut) => encOut);
+ });
+ });
+}
+
+
+/**
+ * Connect to Spicerack and request an authcode. Spicerack fetches the client
+ * certificate from CARS based on the [serial] number and then verifies the
+ * [signature] is valid.
+ */
+Future<String> getAuthCode(String serial, String signature) {
+ var map = {
+ "method": "spicerack.authcode.fetch",
+ "apiVersion": "v1",
+ "params": {
+ "serialNumber": serial,
+ "signature": signature,
+ }
+ };
+ String authRequest = JSON.encode(map);
+ return new HttpClient().postUrl(Uri.parse(SPICERACK_AUTH))
+ .then((HttpClientRequest request) {
+ request.headers.contentType = new ContentType("application", "json");
+ request.write(authRequest);
+ return request.close();
+ }).then((HttpClientResponse response) =>
+ response.transform(new Utf8Decoder()).join());
+}
+
+
+
+/**
+ * Connect to the Oath2 service to get access tokens.
+ */
+Future<String> getOAuth2Tokens(String authCode, String authAddress,
+ String authClientId, String authClientSecret) {
+ String tokenRequest = "code=$authCode"
+ "&client_id=$authClientId"
+ "&client_secret=$authClientSecret"
+ "&redirect_uri=oob"
+ "&grant_type=authorization_code";
+ return new HttpClient().postUrl(Uri.parse(authAddress))
+ .then((HttpClientRequest request) {
+ request.headers.contentType =
+ new ContentType("application", "x-www-form-urlencoded");
+ request.write(tokenRequest);
+ return request.close();
+ }).then((HttpClientResponse response) =>
+ response.transform(new Utf8Decoder()).join());
+}
diff --git a/package/google/google_oregano/google_oregano.mk b/package/google/google_oregano/google_oregano.mk
index aaf626e..813b2f8 100644
--- a/package/google/google_oregano/google_oregano.mk
+++ b/package/google/google_oregano/google_oregano.mk
@@ -7,7 +7,8 @@
define GOOGLE_OREGANO_INSTALL_TARGET_CMDS
mkdir -p $(TARGET_DIR)/app/oregano/
- $(INSTALL) -m 0755 -D package/google/google_oregano/S99oregano $(TARGET_DIR)/etc/init.d/S99oregano;
+ $(INSTALL) -m 0755 -D package/google/google_oregano/S99oregano $(TARGET_DIR)/etc/init.d/S99oregano
+ $(INSTALL) -m 0755 -D package/google/google_oregano/authTokens.dart $(TARGET_DIR)/app/oregano/authTokens.dart
$(INSTALL) -D -m 0755 package/google/google_oregano/runoregano $(TARGET_DIR)/app/oregano/runoregano
cp -af $(@D)/* $(TARGET_DIR)/app/oregano/
endef
diff --git a/package/google/google_oregano/runoregano b/package/google/google_oregano/runoregano
index 0a0c6aa..d859339 100755
--- a/package/google/google_oregano/runoregano
+++ b/package/google/google_oregano/runoregano
@@ -5,8 +5,7 @@
cd "$(dirname "$0")"
export LD_LIBRARY_PATH=/app/client:/usr/local/lib:$LD_LIBRARY_PATH
-export SERIALNUMBER=$(hnvram -qr 1ST_SERIAL_NUMBER)
-[ -z "$SERIALNUMBER" ] && SERIALNUMBER=$(hnvram -qr SERIAL_NO)
+export SERIALNUMBER=$(serial)
ulimit -c 49152
@@ -16,32 +15,37 @@
babysit 10 \
dart -p . isp/fiber/marjoram/src/basil.dart 2>&1 | logos basil 0 20000000 &
- #TODO(codefu): make this url less hard-coded.
cd /usr/local/bin/webkitGl2
- read epoch < /tmp/client_epoch && PARAMS="${PARAMS}&epoch=$epoch"
- read screenHost < /tmp/screeenHost && PARAMS="${PARAMS}&screenhost=$screenHost"
-
- #TODO(codefu): Handle authentication.
-
- #TODO(codefu): Ask spicerack for this either before, or have Oregano query.
+ #TODO(codefu): Have oregano query the storage box from Spicerack
storageHost="192.168.4.6"
read storageHost < /tmp/storageHost
- PARAMS="${PARAMS}&storageHost=$storageHost"
+ PARAMS="storageHost=$storageHost"
PARAMS="${PARAMS}&tvBoxSerial=$SERIALNUMBER"
- echo Oregano params = $PARAMS
+ #Authorize client with the backend.
+ PARAMS="$PARAMS"$(dart /app/oregano/authTokens.dart)
+
+ #Allow developer overriding default parameters, as they are tagged on last they
+ #will override all matching settings above.
+ read devParams < /tmp/client_params
+ PARAMS="$PARAMS&$devParams"
+
#TODO(codefu) use Spicerack redirector when its implemented.
- address="https://fiber.google.com/oregano/3/oregano.html"
+ address="https://fiber.google.com/oregano/4/oregano.html"
read address < /tmp/client_address
address="$address?$PARAMS"
- echo Oregano addres = $address
+
+ echo Oregano address = $address
babysit 10 \
./start --allow-unsecure-content --remote-debugging-port=9222 --disable-web-security "${address}" 2>&1 | logos oregano 0 20000000 &
else
start_sagesrv
+ #Authorize server with the backend.
+ PARAMS=$(dart /app/oregano/authTokens.dart --separator=" --")
+ echo marjoram PARAMS=$PARAMS
# Start up the scheduler / websocket server / spicerack proxy
babysit 10 \
- setuid video:video dart -p . isp/fiber/marjoram/src/marjoram.dart 2>&1 | logos marjoram 0 20000000 &
+ setuid video:video dart -p . isp/fiber/marjoram/src/marjoram.dart $PARAMS 2>&1 | logos marjoram 0 20000000 &
fi