//
// MainPage.xaml.cpp
// Implementation of the MainPage class.
//
#include "pch.h"
#include "MainPage.xaml.h"
using namespace OAuth2Live;
using namespace Concurrency;
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Media;
using namespace Windows::UI::Xaml::Navigation;
using namespace Windows::Security::Authentication::Web;
using namespace web::http;
using namespace web::http::client;
using namespace web::http::oauth2::experimental;
//
// NOTE: You must set this Live key and secret for app to work.
//
static const utility::string_t s_live_key(U(""));
static const utility::string_t s_live_secret(U(""));
MainPage::MainPage()
: m_live_oauth2_config(
s_live_key,
s_live_secret,
L"https://login.live.com/oauth20_authorize.srf",
L"https://login.live.com/oauth20_token.srf",
L"https://login.live.com/oauth20_desktop.srf")
{
InitializeComponent();
}
///
/// Invoked when this page is about to be displayed in a Frame.
///
/// Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.
void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
{
(void) e; // Unused parameter
}
void OAuth2Live::MainPage::_UpdateButtonState()
{
const bool has_access_token = !m_live_oauth2_config.token().access_token().empty();
GetInfoButton->IsEnabled = has_access_token;
GetContactsButton->IsEnabled = has_access_token;
GetEventsButton->IsEnabled = has_access_token;
const bool has_refresh_token = !m_live_oauth2_config.token().refresh_token().empty();
RefreshTokenButton->IsEnabled = has_refresh_token;
}
void OAuth2Live::MainPage::_GetToken()
{
m_live_oauth2_config.set_scope(L"wl.basic wl.calendars");
// Start over, clear tokens and button state.
m_live_oauth2_config.set_token(oauth2_token());
AccessToken->Text = "";
_UpdateButtonState();
String^ authURI = ref new String(m_live_oauth2_config.build_authorization_uri(true).c_str());
auto startURI = ref new Uri(authURI);
String^ redirectURI = ref new String(m_live_oauth2_config.redirect_uri().c_str());
auto endURI = ref new Uri(redirectURI);
try
{
DebugArea->Text += "> Navigating WebAuthenticationBroker to " + authURI + "\n";
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
WebAuthenticationBroker::AuthenticateAndContinue(startURI, endURI, nullptr, WebAuthenticationOptions::None);
#else
concurrency::create_task(WebAuthenticationBroker::AuthenticateAsync(WebAuthenticationOptions::None, startURI, endURI))
.then([this](WebAuthenticationResult^ result)
{
String^ statusString;
DebugArea->Text += "< WebAuthenticationBroker returned: ";
switch (result->ResponseStatus)
{
case WebAuthenticationStatus::ErrorHttp:
{
DebugArea->Text += "ErrorHttp: " + result->ResponseErrorDetail + "\n";
break;
}
case WebAuthenticationStatus::Success:
{
DebugArea->Text += "Success\n";
utility::string_t data = result->ResponseData->Data();
DebugArea->Text += "Redirected URI:\n" + result->ResponseData + "\n";
DebugArea->Text += "> Obtaining token using the redirected URI\n";
m_live_oauth2_config.token_from_redirected_uri(data).then([this](pplx::task token_task)
{
try
{
token_task.wait();
DebugArea->Text += "< Got token\n";
AccessToken->Text = ref new String(m_live_oauth2_config.token().access_token().c_str());
}
catch (const oauth2_exception& e)
{
DebugArea->Text += "< Failed to get token\n";
String^ error = ref new String(utility::conversions::to_string_t(e.what()).c_str());
DebugArea->Text += "Error: " + error + "\n";
}
}, pplx::task_continuation_context::use_current());
break;
}
default:
case WebAuthenticationStatus::UserCancel:
{
DebugArea->Text += "UserCancel\n";
break;
}
}
});
#endif
}
catch (Exception^ ex)
{
DebugArea->Text += "< Error launching WebAuthenticationBroker: " + ex->Message + "\n";
}
}
void OAuth2Live::MainPage::GetTokenButtonClick(Platform::Object^ sender, Windows::UI::Xaml::Navigation::NavigationEventArgs^ e)
{
if (m_live_oauth2_config.client_key().empty() || m_live_oauth2_config.client_secret().empty())
{
DebugArea->Text += "Error: Cannot get token because Live app key or secret is empty. Please see instructions.\n";
}
else
{
_GetToken();
}
}
void OAuth2Live::MainPage::GetInfoButtonClick(Platform::Object^ sender, Windows::UI::Xaml::Navigation::NavigationEventArgs^ e)
{
DebugArea->Text += "> Get user info\n";
m_live_client->request(methods::GET, U("me"))
.then([](http_response resp)
{
return resp.extract_json();
})
.then([this](web::json::value j) -> void
{
String^ json_code = ref new String(j.serialize().c_str());
DebugArea->Text += "< User info (JSON): " + json_code + "\n";
}, pplx::task_continuation_context::use_current());
}
void OAuth2Live::MainPage::GetContactsButtonClick(Platform::Object^ sender, Windows::UI::Xaml::Navigation::NavigationEventArgs^ e)
{
DebugArea->Text += "> Get user contacts\n";
m_live_client->request(methods::GET, U("me/contacts"))
.then([](http_response resp)
{
return resp.extract_json();
})
.then([this](web::json::value j) -> void
{
String^ json_code = ref new String(j.serialize().c_str());
DebugArea->Text += "< User contacts (JSON): " + json_code + "\n";
}, pplx::task_continuation_context::use_current());
}
void OAuth2Live::MainPage::GetEventsButtonClick(Platform::Object^ sender, Windows::UI::Xaml::Navigation::NavigationEventArgs^ e)
{
DebugArea->Text += "> Get user events\n";
m_live_client->request(methods::GET, U("me/events"))
.then([](http_response resp)
{
return resp.extract_json();
})
.then([this](web::json::value j) -> void
{
String^ json_code = ref new String(j.serialize().c_str());
DebugArea->Text += "< User calendar events (JSON): " + json_code + "\n";
}, pplx::task_continuation_context::use_current());
}
void OAuth2Live::MainPage::AccessTokenTextChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::TextChangedEventArgs^ e)
{
http_client_config http_config;
http_config.set_oauth2(m_live_oauth2_config);
m_live_client.reset(new http_client(U("https://apis.live.net/v5.0/"), http_config));
_UpdateButtonState();
}
void OAuth2Live::MainPage::ImplicitGrantUnchecked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
m_live_oauth2_config.set_implicit_grant(false);
}
void OAuth2Live::MainPage::ImplicitGrantChecked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
m_live_oauth2_config.set_implicit_grant(true);
}
void OAuth2Live::MainPage::RefreshTokenButtonClick(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
DebugArea->Text += "> Refreshing token\n";
m_live_oauth2_config.token_from_refresh().then([this](pplx::task refresh_task)
{
try
{
refresh_task.wait();
DebugArea->Text += "< Got token\n";
AccessToken->Text = ref new String(m_live_oauth2_config.token().access_token().c_str());
}
catch (const oauth2_exception& e)
{
DebugArea->Text += "< Failed to get token\n";
String^ error = ref new String(utility::conversions::to_string_t(e.what()).c_str());
DebugArea->Text += "Error: " + error + "\n";
}
}, pplx::task_continuation_context::use_current());
}