Finished Authentication

main
Nichole Mattera 2 years ago
parent 36842df31d
commit ec3b63e691
  1. 2
      Makefile
  2. 79
      Source/Models/AuthResponse.cpp
  3. 37
      Source/Models/AuthResponse.hpp
  4. 82
      Source/Models/TokensResonse.cpp
  5. 38
      Source/Models/TokensResponse.hpp
  6. 33
      Source/Services/Tesla.cpp
  7. 6
      Source/Services/Tesla.hpp

@ -39,7 +39,7 @@ include $(DEVKITPRO)/libnx/switch_rules
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := Build
SOURCES := Source Source/Pages Source/Services
SOURCES := Source Source/Models Source/Pages Source/Services
ROMFS := Resources
APP_TITLE := TeslaNX

@ -0,0 +1,79 @@
// TeslaNX
// Copyright (C) 2021 Nichole Mattera
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <curl/curl.h>
#include "AuthResponse.hpp"
namespace TeslaNX::Models {
AuthResponse::AuthResponse() {
this->code = "";
this->state = "";
this->issuer = "";
}
void AuthResponse::parseResponse(std::string url) {
auto queryParamStart = url.find("?");
if (queryParamStart == std::string::npos)
return;
auto queryParams = url.substr(queryParamStart + 1);
if (queryParams.length() == 0)
return;
std::string::size_type startPos = 0;
while (startPos != queryParams.length()) {
auto foundPos = queryParams.find("&", startPos);
if (foundPos == std::string::npos) {
_parseParameter(queryParams);
startPos = queryParams.length();
} else {
_parseParameter(queryParams.substr(startPos, foundPos));
startPos = foundPos + 1;
}
}
}
void AuthResponse::_parseParameter(std::string parameter) {
auto pos = parameter.find("=");
if (pos == std::string::npos)
return;
auto key = parameter.substr(0, pos);
auto value = parameter.substr(pos + 1);
if (key == "code") {
this->code = _decodeValue(value);
} else if (key == "state") {
this->state = _decodeValue(value);
} else if (key == "issuer") {
this->issuer = _decodeValue(value);
}
}
std::string AuthResponse::_decodeValue(std::string value) {
auto curl = curl_easy_init();
auto decodedValue = curl_easy_unescape(curl, value.c_str(), value.length(), NULL);
auto result = std::string(decodedValue);
curl_free(decodedValue);
curl_easy_cleanup(curl);
return result;
}
}

@ -0,0 +1,37 @@
// TeslaNX
// Copyright (C) 2021 Nichole Mattera
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <string>
#pragma once
namespace TeslaNX::Models {
class AuthResponse {
public:
AuthResponse();
void parseResponse(std::string url);
std::string code;
std::string state;
std::string issuer;
private:
void _parseParameter(std::string parameter);
std::string _decodeValue(std::string value);
};
}

@ -0,0 +1,82 @@
// TeslaNX
// Copyright (C) 2021 Nichole Mattera
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <jansson.h>
#include "TokensResponse.hpp"
namespace TeslaNX::Models {
TokensResponse::TokensResponse() {
this->accessToken = "";
this->refreshToken = "";
this->idToken = "";
this->expiresIn = 0;
this->state = "";
this->tokenType = "";
}
void TokensResponse::parseResponse(std::vector<char> data) {
std::string jsonData = std::string(data.begin(), data.end());
json_t * root = json_loads(jsonData.c_str(), 0, NULL);
if (!root || !json_is_object(root))
return;
json_t * accessToken = json_object_get(root, "access_token");
if (!accessToken || !json_is_string(accessToken)) {
json_decref(root);
return;
}
json_t * refreshToken = json_object_get(root, "refresh_token");
if (!refreshToken || !json_is_string(refreshToken)) {
json_decref(root);
return;
}
json_t * idToken = json_object_get(root, "id_token");
if (!idToken || !json_is_string(idToken)) {
json_decref(root);
return;
}
json_t * expiresIn = json_object_get(root, "expires_in");
if (!expiresIn || !json_is_integer(expiresIn)) {
json_decref(root);
return;
}
json_t * state = json_object_get(root, "state");
if (!state || !json_is_string(state)) {
json_decref(root);
return;
}
json_t * tokenType = json_object_get(root, "token_type");
if (!tokenType || !json_is_string(tokenType)) {
json_decref(root);
return;
}
this->accessToken = std::string(json_string_value(accessToken));
this->refreshToken = std::string(json_string_value(refreshToken));
this->idToken = std::string(json_string_value(idToken));
this->expiresIn = json_integer_value(expiresIn);
this->state = std::string(json_string_value(state));
this->tokenType = std::string(json_string_value(tokenType));
}
}

@ -0,0 +1,38 @@
// TeslaNX
// Copyright (C) 2021 Nichole Mattera
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <string>
#include <vector>
#pragma once
namespace TeslaNX::Models {
class TokensResponse {
public:
TokensResponse();
void parseResponse(std::vector<char> data);
std::string accessToken;
std::string refreshToken;
std::string idToken;
long long expiresIn;
std::string state;
std::string tokenType;
};
}

@ -15,11 +15,13 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <jansson.h>
#include <mbedtls/base64.h>
#include <mbedtls/sha256.h>
#include <sstream>
#include "Tesla.hpp"
#include "Web.hpp"
namespace TeslaNX::Services {
std::string Tesla::generateCodeVerifier() {
@ -62,9 +64,34 @@ namespace TeslaNX::Services {
return url;
}
std::tuple<std::string, std::string, std::string> Tesla::parseCallbackUrl(std::string url) {
// TODO: Parse code, state, and issuer from callback URL.
return std::make_tuple("", "", "");
Models::AuthResponse * Tesla::parseCallbackUrl(std::string url) {
auto result = new Models::AuthResponse();
result->parseResponse(url);
return result;
}
Models::TokensResponse * Tesla::getTokens(std::string code, std::string codeVerifier, std::string redirectUri, std::function<void(double)> onLoading) {
auto result = new Models::TokensResponse();
auto jsonObject = json_pack("{s:s,s:s,s:s,s:s,s:s}",
"grant_type", "authorization_code",
"client_id", "ownerapi",
"code", code.c_str(),
"code_verifier", codeVerifier.c_str(),
"redirect_uri", redirectUri.c_str());
auto body = json_dumps(jsonObject, JSON_COMPACT);
auto bodyString = std::string(body);
free(body);
json_decref(jsonObject);
std::map<std::string, std::string> headers;
auto response = Web::post("https://auth.tesla.com/oauth2/v3/token", headers, body, onLoading);
if (std::get<0>(response) == 200) {
result->parseResponse(std::get<1>(response));
}
return result;
}
std::string Tesla::_toHexString(unsigned const char * data, size_t size) {

@ -21,6 +21,9 @@
#include <string>
#include <vector>
#include "../Models/AuthResponse.hpp"
#include "../Models/TokensResponse.hpp"
#pragma once
namespace TeslaNX::Services {
@ -30,7 +33,8 @@ namespace TeslaNX::Services {
static std::string generateCodeVerifier();
static std::string generateCodeChallenge(std::string codeVerifier);
static std::string getAuthenticationURL(std::string codeVerifier, std::string codeChallenge, std::string callback);
static std::tuple<std::string, std::string, std::string> parseCallbackUrl(std::string url);
static Models::AuthResponse * parseCallbackUrl(std::string url);
static Models::TokensResponse * getTokens(std::string code, std::string codeVerifier, std::string redirectUri, std::function<void(double)> onLoading);
private:
static std::string _toHexString(unsigned const char * data, size_t size);

Loading…
Cancel
Save