Skip to content

Commit

Permalink
Fix the token generation refreshment and internet connection issue.
Browse files Browse the repository at this point in the history
  • Loading branch information
mobizt committed Mar 23, 2021
1 parent 95ed4fc commit 11dfc01
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 118 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Google OAuth2.0 Access Token generation Arduino Library v1.0.0
# Google OAuth2.0 Access Token generation Arduino Library v1.0.1


This is the library will create the OAuth2.0 access token used in the Google API's http request (REST).

The Service Account credentials e.g. project host, project id, email and private key which are available in the service account key file will be used.
The Service Account credentials i.e. project_id, client_email and private_key which are available in the service account key file will be used.

This library supports ESP8266 and ESP32 MCU from Espressif.

Expand Down
54 changes: 32 additions & 22 deletions examples/Basic/Basic.ino
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,18 @@
#include <ESP8266WiFi.h>
#endif

#include "ESPSigner.h"
#include <ESPSigner.h>

#define WIFI_SSID "WiFi SSID"
#define WIFI_PASSWORD "WIFi PSK"


#define PROJECT_HOST "The project host without cheme (https://)"

/** These credentials are taken from Service Account key file (JSON)
* https://cloud.google.com/iam/docs/service-accounts
*/
#define PROJECT_ID "The project ID"
#define CLIENT_EMAIL "Client Email"
#define PRIVATE_KEY_ID "e172ba5eb712aea49938280fe3be3b9508dfbe0f"
const char PRIVATE_KEY[] PROGMEM = "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDQz8GHAQegHm9O\nz/mjEi5DsRW6o7ZtPqv8G2knDESxwesBvzbJxQI/WuVN1Lwn4cI84UFlbBS7p1eK\nE+GRJ8A+tPMa3K1ewCiDBZbiBRLullzhGfEvpPFadoqRWmWYeVrpUGsVp0ZkMWbM\nI6dIInXTT9CeX2CPlrUNzbENq10j+mkcAF7FX+UjoKmfBpTNdS44sxpFz6LbJMrX\nLqdOdGocNROZkYFrZ/UZKRqo1ZnUjpC8rW6kBTcyoonotioZxLU9VPYWEVEUGGcf\nP8ZT86+mVEldN98nUi05XpMhQbbzkVT9S+JYPJIurIx9O59sVukj1D3CBQ1txEIp\nxHFB0IXTAgMBAAECggEAT2NVhDLvh8BaeD/Y/Nc6MLFAfiOlBXbI44I2YcqnyV9d\nLl5ZAbA9sQGpYYRqfs010HihqOJFJa0zOoNhhJL048JfFQzmezoajOnQmiDsuDoB\nmPGIgaE3w7mC6E1Sh/xHhKH2/JYKzKf9mcpKXMIBQvQ68CN57k2Ri2xzDqvirvzi\nVPzD/gUWk9T8YY21N3kfkHFJa1vU6DNqQrRZC6PC1fwGyl1T8ggGNHn/BPas7mPP\nfDrznOiKUQOMTGN45ht+SKyoAwHZvRcnFQsi1tqng5XRkq3DUcTazLWEJkJML65G\nS9X53+Z9knNwuOWHRVi18JVawC0O7WzQBzyFcBMD0QKBgQD/KwIWWBqN8y4rMvo0\na2a6xGapCm4BSbr0HAyMYJXgM/MQW6PGv0qT0Qhm9inLFXtmUI+Me91B5TEOavej\nfDT/dTUaHV8wExc19Bwbon5yfziUeyWkEZ1WEd+Q25P8Gv01t7SIHpey53ucDL9t\nMgIRnZl2ReJE2DirR9Q3OOxkUQKBgQDRfg2zIglOh2CpGzbZBa6E8hVc9ZCXoJXV\ndKu8w+PyyPLDl/i1kUNd6roc6Zh6QT966TEXxlpxovfUznTcdjJJbqVjM0lZUrzq\n3p/Oscq86qP1MfibTv6EUSPLgdsYv5OSnYVqnS2H+QI1uIVb8rBU7KqpwX/vPyAi\nzDZ8Xq/y4wKBgBf35j5LEFN9ID0WkMITxJaOlEYUoLimQFVlvRgCipGAz7gdo4ir\nt0mjPPLO9KYK4oh90L4VdHcYHD+KdLB6nk/QpqhJUgOmB2wd/fXqkY4XvSzVVHfQ\n38KR8zocJg5sSpSdKOwQU5eOfuHtoJ2VMPSOpTei4NoupUQRfzGguzPBAoGBAL9B\njdBU6po/DghVSCWqAkJtoQNVTcSgXyqZcZDMZndo7fmT7QQWsqIzgeaTfRlgKExW\nSPOjqz7Dwe8O7bG4VwCje2qtj/F0j/T9eniB6M3Aih94l7dyzvqN+Vf6HcTiYiAg\nn4VOKhtRQqs44senMUTXLJf+iIYr43LhbXzuFURxAoGBAJruUO5E+HOpX4e4gRGT\nszy9v0zxS4m8Mro6Tdxylk8iondJHnJL515cuC2IwCj5JOj5tSzTFNYjy2+b7R9t\nNJs0uuRZuPxnog2OvsJpICI0PyU1Tq9lxflw46lPXmpNZkFtKmbelVpQlH3UvwuV\nUBegcEvgBSXRPrZUCgKgHVG+\n-----END PRIVATE KEY-----\n";

#define PROJECT_ID "The project ID" //Taken from "project_id" key in JSON file.
#define CLIENT_EMAIL "Client Email" //Taken from "client_email" key in JSON file.
#define PRIVATE_KEY_ID "Private key ID" //Taken from "private_key_id" in JSON file.
const char PRIVATE_KEY[] PROGMEM = "-----BEGIN PRIVATE KEY-----\\n-----END PRIVATE KEY-----\n"; //Taken from "private_key" key in JSON file.

SignerConfig config;

Expand All @@ -34,6 +30,8 @@ void setup()
Serial.println();
Serial.println();

WiFi.setAutoReconnect(true);

WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to Wi-Fi");
while (WiFi.status() != WL_CONNECTED)
Expand All @@ -46,31 +44,43 @@ void setup()
Serial.println(WiFi.localIP());
Serial.println();

/* Assign the project host (required) */
config.host = PROJECT_HOST;
/* Assign the sevice account credentials and private key (required) */
config.service_account.data.client_email = CLIENT_EMAIL;
config.service_account.data.project_id = PROJECT_ID;
config.service_account.data.private_key = PRIVATE_KEY;

/* Assign the sevice account credentials and private key (required) */
config.service_account.data.client_email = CLIENT_EMAIL;
config.service_account.data.project_id = PROJECT_ID;
config.service_account.data.private_key = PRIVATE_KEY;
/** Expired period in seconds (optional).
* Default is 3600 sec.
* This may not afftect the expiry time of generated access token.
*/
config.signer.expiredSeconds = 3600;

/** Assign the API scopes (required)
/* Seconds to refresh the token before expiry time (optional). Default is 60 sec.*/
config.signer.preRefreshSeconds = 60;

/** Assign the API scopes (required)
* Use space or comma to separate the scope.
*/
config.signer.tokens.scope = "https://www.googleapis.com/auth/cloud-platform, https://www.googleapis.com/auth/userinfo.email";
config.signer.tokens.scope = "https://www.googleapis.com/auth/cloud-platform, https://www.googleapis.com/auth/userinfo.email";

/** Assign the callback function for token ggeneration status (optional) */
config.token_status_callback = tokenStatusCallback;

/* Create token */
Signer.begin(&config);

//The WiFi connection can be processed before or after Signer.begin

/** Assign the callback function for token ggeneration status (optional) */
config.token_status_callback = tokenStatusCallback;
//Call Signer.getExpiredTimestamp() to get the token expired timestamp (seconds from midnight Jan 1, 1970)

/* Create token */
Signer.begin(&config);
//Call Signer.refreshToken() to force refresh the token.
}

void loop()
{
delay(1000);

/* Check to status and also refresh the access token */
/* Check for token generation ready state and also refresh the access token if it expired */
bool ready = Signer.tokenReady();
}

Expand Down
26 changes: 19 additions & 7 deletions examples/Service_Account_from_File/Service_Account_from_File.ino
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
#define WIFI_SSID "WiFi SSID"
#define WIFI_PASSWORD "WIFi PSK"

#define PROJECT_HOST "The project host without cheme (https://)"


SignerConfig config;

void tokenStatusCallback(TokenInfo info);
Expand All @@ -25,6 +22,8 @@ void setup()
Serial.println();
Serial.println();

WiFi.setAutoReconnect(true);

WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to Wi-Fi");
while (WiFi.status() != WL_CONNECTED)
Expand All @@ -37,9 +36,6 @@ void setup()
Serial.println(WiFi.localIP());
Serial.println();

/* Assign the project host (required) */
config.host = PROJECT_HOST;

/* The file systems for flash and SD/SDMMC can be changed in FS_Config.h. */

/** Assign the sevice account JSON file and the file storage type (required)
Expand All @@ -48,6 +44,16 @@ void setup()
config.service_account.json.path = "/service_account_file.json"; //change this for your json file
config.service_account.json.storage_type = esp_signer_mem_storage_type_flash; //or esp_signer_mem_storage_type_sd

/** Expired period in seconds (optional).
* Default is 3600 sec.
* This may not afftect the expiry time of generated access token.
*/
config.signer.expiredSeconds = 3600;

/* Seconds to refresh the token before expiry time (optional). Default is 60 sec.*/
config.signer.preRefreshSeconds = 60;


/** Assign the API scopes (required)
* Use space or comma to separate the scope.
*/
Expand All @@ -58,13 +64,19 @@ void setup()

/* Create token */
Signer.begin(&config);

//The WiFi connection can be processed before or after Signer.begin

//Call Signer.getExpiredTimestamp() to get the token expired timestamp (seconds from midnight Jan 1, 1970)

//Call Signer.refreshToken() to force refresh the token.
}

void loop()
{
delay(1000);

/* Check to status and also refresh the access token */
/* Check for token generation ready state and also refresh the access token if it expired */
bool ready = Signer.tokenReady();
}

Expand Down
2 changes: 2 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ getTokenType KEYWORD2
getTokenStatus KEYWORD2
getTokenError KEYWORD2
sdBegin KEYWORD2
getExpiredTimestamp KEYWORD2
refreshToken KEYWORD2


######################################
Expand Down
4 changes: 2 additions & 2 deletions library.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"name": "ESP Signer",
"version": "1.0.0",
"version": "1.0.1",
"keywords": "communication, REST, esp32, esp8266, arduino",
"description": "The Google OAuth2.0 access token generation for Google REST API's http request.",
"repository": {
"type": "git",
"url": "https://github.com/mobizt/ESp-Signer.git"
"url": "https://github.com/mobizt/ESP-Signer.git"
},
"authors": [{
"name": "Mobizt",
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name=ESP Signer

version=1.0.0
version=1.0.1

author=Mobizt

Expand Down
105 changes: 32 additions & 73 deletions src/ESPSigner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,6 @@ void ESP_Signer::begin(SignerConfig *cfg)
if (tokenSigninDataReady())
config->signer.tokens.token_type = esp_signer_token_type_oauth2_access_token;

struct esp_signer_url_info_t uinfo;

if (config->host.length() > 0)
{
ut->getUrlInfo(config->host.c_str(), uinfo);
config->host = uinfo.host;
}

if (strlen_P(config->cert.data))
config->_int.esp_signer_caCert = config->cert.data;

Expand Down Expand Up @@ -215,7 +207,7 @@ bool ESP_Signer::handleToken()
if (!config)
return false;

if (config->signer.tokens.token_type == esp_signer_token_type_oauth2_access_token && (millis() > config->signer.tokens.expires - config->signer.preRefreshMillis || config->signer.tokens.expires == 0))
if (config->signer.tokens.token_type == esp_signer_token_type_oauth2_access_token && (time(nullptr) > config->signer.tokens.expires - config->signer.preRefreshSeconds || config->signer.tokens.expires == 0))
{

if (config->signer.step == esp_signer_jwt_generation_step_begin)
Expand Down Expand Up @@ -308,11 +300,9 @@ void ESP_Signer::tokenProcessingTask()

yield();
}

vTaskDelete(NULL);

_this->config->_int.token_processing_task_handle = NULL;
_this->config->signer.tokenTaskRunning = false;
vTaskDelete(NULL);
};

char *taskname = ut->strP(esp_signer_pgm_str_20);
Expand Down Expand Up @@ -535,6 +525,9 @@ void ESP_Signer::sendTokenStatusCB()

bool ESP_Signer::handleTokenResponse()
{
if (config->_int.esp_signer_reconnect_wifi)
ut->reconnect(0);

if (WiFi.status() != WL_CONNECTED)
return false;

Expand Down Expand Up @@ -566,7 +559,7 @@ bool ESP_Signer::handleTokenResponse()
#endif
while (stream->connected() && stream->available() == 0)
{
if (!reconnect(dataTime))
if (!ut->reconnect(dataTime))
{
if (stream)
if (stream->connected())
Expand All @@ -589,7 +582,11 @@ bool ESP_Signer::handleTokenResponse()
{
while (!complete)
{
if (config->_int.esp_signer_reconnect_wifi)
ut->reconnect(0);

delay(0);

if (WiFi.status() != WL_CONNECTED)
{
if (stream)
Expand Down Expand Up @@ -785,7 +782,12 @@ bool ESP_Signer::createJWT()
ut->delS(tmp);

tmp = ut->strP(esp_signer_pgm_str_47);
config->signer.json->add(tmp, (int)(now + 60 * 60));

if (config->signer.expiredSeconds > 3600)
config->signer.json->add(tmp, (int)(now + 3600));
else
config->signer.json->add(tmp, (int)(now + config->signer.expiredSeconds));

ut->delS(tmp);

if (config->signer.tokens.token_type == esp_signer_token_type_oauth2_access_token)
Expand Down Expand Up @@ -991,37 +993,12 @@ bool ESP_Signer::createJWT()
return true;
}

bool ESP_Signer::reconnect(unsigned long dataTime)
bool ESP_Signer::requestTokens()
{

bool status = WiFi.status() == WL_CONNECTED;

if (dataTime > 0)
{
if (millis() - dataTime > 30000)
return false;
}

if (!status)
{

if (config->_int.esp_signer_reconnect_wifi)
{
if (millis() - config->_int.esp_signer_last_reconnect_millis > config->_int.esp_signer_reconnect_tmo)
{
WiFi.reconnect();
config->_int.esp_signer_last_reconnect_millis = millis();
}
}

status = WiFi.status() == WL_CONNECTED;
}

return status;
}
if (config->_int.esp_signer_reconnect_wifi)
ut->reconnect(0);

bool ESP_Signer::requestTokens()
{
if (WiFi.status() != WL_CONNECTED)
return false;

Expand Down Expand Up @@ -1155,7 +1132,7 @@ bool ESP_Signer::requestTokens()
config->signer.json->get(*config->signer.data, tmp);
ut->delS(tmp);
if (config->signer.data->success)
config->signer.tokens.expires = millis() + (1000 * atoi(config->signer.data->stringValue.c_str()));
config->signer.tokens.expires = time(nullptr) + atoi(config->signer.data->stringValue.c_str());
}
return handleSignerError(0);
}
Expand All @@ -1170,7 +1147,7 @@ void ESP_Signer::checkToken()
if (!config)
return;

if (config->signer.tokens.token_type == esp_signer_token_type_oauth2_access_token && (millis() > config->signer.tokens.expires - config->signer.preRefreshMillis || config->signer.tokens.expires == 0))
if (config->signer.tokens.token_type == esp_signer_token_type_oauth2_access_token && (time(nullptr) > config->signer.tokens.expires - config->signer.preRefreshSeconds || config->signer.tokens.expires == 0))
handleToken();
}

Expand Down Expand Up @@ -1276,6 +1253,17 @@ String ESP_Signer::getTokenError()
return getTokenError(tokenInfo);
}

unsigned long ESP_Signer::getExpiredTimestamp()
{
return config->signer.tokens.expires;
}

void ESP_Signer::refreshToken()
{
config->signer.tokens.expires = 0;
checkToken();
}

void ESP_Signer::errorToString(int httpCode, std::string &buff)
{
buff.clear();
Expand Down Expand Up @@ -1410,35 +1398,6 @@ void ESP_Signer::errorToString(int httpCode, std::string &buff)
}
}

std::string ESP_Signer::getToken(esp_signer_auth_token_type type)
{
if (!config)
return "";

if (type == esp_signer_token_type_oauth2_access_token)
return config->signer.tokens.access_token;
else
return "";
}

SignerConfig *ESP_Signer::getCfg()
{
return config;
}

std::string ESP_Signer::getCAFile()
{
if (!config)
return "";
return config->cert.file;
}
int ESP_Signer::getCAFileStorage()
{
if (!config)
return 0;
return config->cert.file_storage;
}

ESP_Signer Signer = ESP_Signer();

#endif
Loading

0 comments on commit 11dfc01

Please sign in to comment.