fix: fix expiry for `to_json()` (#589)

* This patch for </issues/501> includes the following fixes:

- The access token is always set to `None`, so the fix involves using (the access) `token` from the saved JSON credentials file.
- For refresh needs, `expiry` also needs to be saved via `to_json()`.
    - DUMP: As `expiry` is a `datetime.datetime` object, serialize to `datetime.isoformat()` in the same [`oauth2client` format](https://github.com/googleapis/oauth2client/blob/master/oauth2client/client.py#L55) for consistency.
    - LOAD: Add code to restore `expiry` back to `datetime.datetime` object when imported.
    - LOAD: If `expiry` was unsaved, automatically set it as expired so refresh takes place.
- Minor `scopes` updates
    - DUMP: Add property for `scopes` so `to_json()` can grab it
    - LOAD: `scopes` may be saved as a string instead of a JSON array (Python list), so ensure it is Sequence[str] when imported.
diff --git a/tests/oauth2/test_credentials.py b/tests/oauth2/test_credentials.py
index ceb8cdf..ee8b8a2 100644
--- a/tests/oauth2/test_credentials.py
+++ b/tests/oauth2/test_credentials.py
@@ -359,6 +359,20 @@
         assert creds.token_uri == credentials._GOOGLE_OAUTH2_TOKEN_ENDPOINT
         assert creds.scopes == scopes
 
+        info["scopes"] = "email"  # single non-array scope from file
+        creds = credentials.Credentials.from_authorized_user_info(info)
+        assert creds.scopes == [info["scopes"]]
+
+        info["scopes"] = ["email", "profile"]  # array scope from file
+        creds = credentials.Credentials.from_authorized_user_info(info)
+        assert creds.scopes == info["scopes"]
+
+        expiry = datetime.datetime(2020, 8, 14, 15, 54, 1)
+        info["expiry"] = expiry.isoformat() + "Z"
+        creds = credentials.Credentials.from_authorized_user_info(info)
+        assert creds.expiry == expiry
+        assert creds.expired
+
     def test_from_authorized_user_file(self):
         info = AUTH_USER_INFO.copy()
 
@@ -381,7 +395,10 @@
 
     def test_to_json(self):
         info = AUTH_USER_INFO.copy()
+        expiry = datetime.datetime(2020, 8, 14, 15, 54, 1)
+        info["expiry"] = expiry.isoformat() + "Z"
         creds = credentials.Credentials.from_authorized_user_info(info)
+        assert creds.expiry == expiry
 
         # Test with no `strip` arg
         json_output = creds.to_json()
@@ -392,6 +409,7 @@
         assert json_asdict.get("client_id") == creds.client_id
         assert json_asdict.get("scopes") == creds.scopes
         assert json_asdict.get("client_secret") == creds.client_secret
+        assert json_asdict.get("expiry") == info["expiry"]
 
         # Test with a `strip` arg
         json_output = creds.to_json(strip=["client_secret"])
@@ -403,6 +421,12 @@
         assert json_asdict.get("scopes") == creds.scopes
         assert json_asdict.get("client_secret") is None
 
+        # Test with no expiry
+        creds.expiry = None
+        json_output = creds.to_json()
+        json_asdict = json.loads(json_output)
+        assert json_asdict.get("expiry") is None
+
     def test_pickle_and_unpickle(self):
         creds = self.make_credentials()
         unpickled = pickle.loads(pickle.dumps(creds))