1
0

Added UserCredential override with TokenUpdated event

Added Success code parser
Updated packages versions
This commit is contained in:
Michael Gordeev
2020-05-10 13:21:01 +03:00
parent 92781fe4f0
commit f968c95ab1
3 changed files with 147 additions and 82 deletions
@@ -5,6 +5,7 @@ using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace YouTube.Authorization namespace YouTube.Authorization
@@ -12,9 +13,9 @@ namespace YouTube.Authorization
public static class AuthorizationHelpers public static class AuthorizationHelpers
{ {
public static Uri Endpoint => "https://accounts.google.com/o/oauth2/approval".ToUri(); public static Uri Endpoint => "https://accounts.google.com/o/oauth2/approval".ToUri();
const string refreshEndpoint = "https://oauth2.googleapis.com/token"; private const string refreshEndpoint = "https://oauth2.googleapis.com/token";
const string tokenEndpoint = "https://www.googleapis.com/oauth2/v4/token"; private const string tokenEndpoint = "https://www.googleapis.com/oauth2/v4/token";
const string redirectUrl = "urn:ietf:wg:oauth:2.0:oob"; private const string redirectUrl = "urn:ietf:wg:oauth:2.0:oob";
public static Uri FormQueryString(ClientSecrets clientSecrets, params string[] scopes) public static Uri FormQueryString(ClientSecrets clientSecrets, params string[] scopes)
{ {
@@ -24,6 +25,9 @@ namespace YouTube.Authorization
return $"https://accounts.google.com/o/oauth2/auth?client_id={clientId}&redirect_uri={redirectUrl}&response_type=code&scope={scopeStr}".ToUri(); return $"https://accounts.google.com/o/oauth2/auth?client_id={clientId}&redirect_uri={redirectUrl}&response_type=code&scope={scopeStr}".ToUri();
} }
public static string ParseSuccessCode(string responseData) =>
new Regex(@"(?<=code=)(.*?)(?=&)").Match(responseData).Value;
public static async Task<UserCredential> ExchangeToken(ClientSecrets clientSecrets, string responseToken) public static async Task<UserCredential> ExchangeToken(ClientSecrets clientSecrets, string responseToken)
{ {
using HttpClient client = new HttpClient(); using HttpClient client = new HttpClient();
@@ -0,0 +1,61 @@
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Responses;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace YouTube.Authorization
{
public class UserCredential : Google.Apis.Auth.OAuth2.UserCredential
{
/// <summary>
/// Event is fired when new refresh token is recieved and the old one is no loger valid
/// </summary>
public event EventHandler RefreshTokenUpdated;
/// <summary>Constructs a new credential instance.</summary>
/// <param name="flow">Authorization code flow.</param>
/// <param name="userId">User identifier.</param>
/// <param name="token">An initial token for the user.</param>
public UserCredential(IAuthorizationCodeFlow flow, string userId, TokenResponse token) : base(flow, userId, token) { }
/// <summary>Constructs a new credential instance.</summary>
/// <param name="flow">Authorization code flow.</param>
/// <param name="userId">User identifier.</param>
/// <param name="token">An initial token for the user.</param>
/// <param name="quotaProjectId">The ID of the project associated
/// to this credential for the purposes of quota calculation and billing. Can be null.</param>
public UserCredential(IAuthorizationCodeFlow flow, string userId, TokenResponse token, string quotaProjectId) : base(flow, userId, token, quotaProjectId) { }
/// <summary>
/// Refreshes the token by calling to
/// <see cref="Google.Apis.Auth.OAuth2.Flows.IAuthorizationCodeFlow.RefreshTokenAsync"/>.
/// Then it updates the <see cref="TokenResponse"/> with the new token instance.
/// </summary>
/// <param name="taskCancellationToken">Cancellation token to cancel an operation.</param>
/// <returns><c>true</c> if the token was refreshed.</returns>
public new async Task<bool> RefreshTokenAsync(CancellationToken taskCancellationToken)
{
if (Token.RefreshToken == null)
{
Logger.Warning("Refresh token is null, can't refresh the token!");
return false;
}
// It's possible that two concurrent calls will be made to refresh the token, in that case the last one
// will win.
var newToken = await Flow.RefreshTokenAsync(UserId, Token.RefreshToken, taskCancellationToken)
.ConfigureAwait(false);
Logger.Info("Access token was refreshed successfully");
if (newToken.RefreshToken == null)
newToken.RefreshToken = Token.RefreshToken;
Token = newToken;
RefreshTokenUpdated?.Invoke(this, null);
return true;
}
}
}
+7 -7
View File
@@ -21,15 +21,15 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AngleSharp" Version="0.13.0" /> <PackageReference Include="AngleSharp" Version="0.14.0" />
<PackageReference Include="Google.Apis" Version="1.42.0" /> <PackageReference Include="Google.Apis" Version="1.45.0" />
<PackageReference Include="Google.Apis.Auth" Version="1.42.0" /> <PackageReference Include="Google.Apis.Auth" Version="1.45.0" />
<PackageReference Include="Google.Apis.Core" Version="1.42.0" /> <PackageReference Include="Google.Apis.Core" Version="1.45.0" />
<PackageReference Include="Google.Apis.Oauth2.v2" Version="1.42.0.1602" /> <PackageReference Include="Google.Apis.Oauth2.v2" Version="1.45.0.1869" />
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.42.0.1758" /> <PackageReference Include="Google.Apis.YouTube.v3" Version="1.45.0.1918" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" /> <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="all" /> <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="all" />
<PackageReference Include="YoutubeExplode" Version="4.7.10" /> <PackageReference Include="YoutubeExplode" Version="4.7.16" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>