Assume we have an application that wants access popular Russian social network VK and written on C# with WinForms GUI. VK uses OAuth2-similiar approach, so we need to open web browser with vk oauth authorization url. Then we subscribe to webBrowser's OnNavigated event and waiting until url will not be equal some pre-defined url with access token in query string.
From now on we can call vk methods using received access token, but some strange things take place here: when i try to invoke some vk methods with HttpClient.GetAsync(methodUri), everything goes according to plan, except to opening the link from the authorization web browser in the system web browser.
vk's client authorization Url looks like https://oauth.vk.com/authorize?client_id={clientId}&scope={scope}&redirect_uri=https://oauth.vk.com/blank.html&display={displayType}&response_type=token
, Url with received accessToken looks like https://oauth.vk.com/blank.html#access_token={accessToken}&expires_in={expiresIn}&user_id={userId}
, note the number sign instead on question mark.
code in main form:
var authenticationForm = new AuthenticationForm();
authenticationForm.Show();
_authenticatedUser = await application.ClientAuthenticator.Authenticate(authenticationForm.GetToken);
authenticationForm.Close();
var httpClient = new HttpClient();
var request = "https://api.vk.com/method/users.get.xml?user_ids=1&fields=online";
var response = await httpClient.GetAsync(request);
authenticationForm class code:
public partial class AuthenticationForm : Form
{
private readonly TaskCompletionSource<VkAccessToken> _tokenCompletitionSource = new TaskCompletionSource<VkAccessToken>();
private Uri _redirectUri;
public AuthenticationForm()
{
InitializeComponent();
}
public async Task<IVkAccessToken> GetToken(Uri authUri, Uri redirectUri)
{
authenticationBrowser.Navigate(authUri);
_redirectUri = redirectUri;
var token = await _tokenCompletitionSource.Task;
return token;
}
private async void authenticationBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
if (!(_redirectUri.IsBaseOf(e.Url) && _redirectUri.AbsolutePath.Equals(e.Url.AbsolutePath))) return;
//working with e.Url to achieve token, userId and expiresIn, creating token variable based on them
_tokenCompletitionSource.SetResult(token);
}
}
ClientAuthenticator.Authenticate code:
public async Task<IVkAuthenticatedUser> Authenticate(Func<Uri, Uri, Task<IVkAuthenticatedUser>> aunthenticationResultGetter)
{
var authorizationUri =
new Uri("https://oauth.vk.com/authorize?client_id={clientId}&scope={scope}&redirect_uri=https://oauth.vk.com/blank.html&display=page&response_type=token");
var token = await aunthenticationResultGetter(authorizationUri, _application.Settings.RedirectUri);
//...
return newUserBasedOnToken;
}
after stepping out(using debugger) var response = await httpClient.GetAsync(request);
line from main form, my system browser opens link like https://oauth.vk.com/blank.html#access_token={accessToken}&expires_in={expiresIn}&user_id={userId} - #access_token={accessToken}&expires_in={expiresIn}&user_id={userId}
with recent accessToken, expiresIn and userId values. Yes, with ... - #access_token=....
in url.
I have no idea why this might happen, but I am concerned that the number sign.
important addition: it only happens if the Web browser does not have information about a session or it is expired, that is, I have to enter username and password to vk's login form. if cookies contain the necessary information and it automatically redirect to the page containing token in it's url (with #
sign again), everything works as expected