Advertisement
Guest User

Untitled

a guest
Dec 1st, 2024
25
0
18 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.88 KB | None | 0 0
  1. public partial class EmailService : IEmailService
  2. {
  3. private const string ApplicationName = "Hidden-On-Purpose";
  4. public const string TokenUrl = "https://oauth2.googleapis.com/token";
  5. public const string FileNameCredentials = "Your_File_With_Credentials.json";
  6. public const string RefreshToken = "HiddenOnPurpose";
  7.  
  8. // Update Scope to hit Google Calendar
  9. private readonly string[] _scopes = [GmailService.Scope.GmailReadonly];
  10. private readonly string _redirectUri;
  11.  
  12. private static GoogleCredential Credential { get; set; } = default!;
  13.  
  14. public static GoogleClientSecrets ClientSecrets { get; set; } = default!;
  15.  
  16. private readonly IDataStore _dataStore;
  17.  
  18. public EmailService(
  19. IHttpClientFactory httpClientFactory,
  20. IHttpContextAccessor httpContextAccessor,
  21. IDataStore dataStore)
  22. {
  23. if (httpContextAccessor?.HttpContext is null)
  24. {
  25. throw new ArgumentNullException(nameof(httpClientFactory));
  26. }
  27.  
  28. // Must be the same as the one you set in the Google Console in the Oauth2 section ( https://console.cloud.google.com/apis/credentials/oauthclient/)
  29. _redirectUri = $"https://{httpContextAccessor.HttpContext!.Request.Host}/Home/AuthorizeGoogle";
  30.  
  31. // I have my own custom DataStore, but you can use the default one it should not affect your code
  32. // I am storing my Token in Azure Storage, you can ask chatgpt for this it will help you
  33. _dataStore = dataStore ?? throw new ArgumentNullException(nameof(dataStore));
  34. }
  35.  
  36. #region Google Authentication Process
  37.  
  38. /// <summary>
  39. /// Starting point for the Gmail Authentication
  40. /// Very Important! Must be called in Incognito Mode to be able to get Refresh Token, otherwise you might not get.
  41. /// </summary>
  42. /// <returns></returns>
  43. public async Task<string> StartGmailChallengeAuthenticationAsync(CancellationToken cancellationToken)
  44. {
  45. if (ClientSecrets is null)
  46. {
  47. await InitializeClientSecretsAsync(cancellationToken);
  48. }
  49.  
  50. using var flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
  51. {
  52. ClientSecrets = ClientSecrets!.Secrets,
  53. Scopes = _scopes,
  54. DataStore = _dataStore
  55. });
  56.  
  57. var absoluteUri = flow.CreateAuthorizationCodeRequest(_redirectUri).Build().AbsoluteUri;
  58.  
  59. return absoluteUri;
  60. }
  61.  
  62. public static async Task<TokenResponse> RefreshAccessTokenAsync([NotNull] HttpClient httpClient, string clientId, string clientSecret, string refreshToken)
  63. {
  64. using var requestBody = new FormUrlEncodedContent(new[]
  65. {
  66. new KeyValuePair<string, string>("client_id", clientId),
  67. new KeyValuePair<string, string>("client_secret", clientSecret),
  68. new KeyValuePair<string, string>("refresh_token", refreshToken),
  69. new KeyValuePair<string, string>("grant_type", "refresh_token")
  70. });
  71.  
  72. var response = await httpClient.PostAsync(TokenUrl, requestBody);
  73. response.EnsureSuccessStatusCode();
  74.  
  75. var responseContent = await response.Content.ReadFromJsonAsync<TokenResponse>() ?? throw new ApplicationException("Response content is null in the background job");
  76.  
  77. return responseContent;
  78. }
  79.  
  80. public async Task ExchangeCodeForTokenResponseGmailAsync(string code, CancellationToken cancellationToken)
  81. {
  82. if (string.IsNullOrEmpty(code))
  83. {
  84. throw new ApplicationException("No code found");
  85. }
  86.  
  87. if (ClientSecrets is null)
  88. {
  89. await InitializeClientSecretsAsync(cancellationToken);
  90. throw new ApplicationException("Client Secrets is null");
  91. }
  92.  
  93. // Exchange the authorization code for user credentials (tokens)
  94. using var flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
  95. {
  96. ClientSecrets = ClientSecrets.Secrets,
  97. Scopes = _scopes,
  98. DataStore = _dataStore
  99. });
  100.  
  101. var token = await flow.ExchangeCodeForTokenAsync(
  102. userId: "user",
  103. code: code,
  104. redirectUri: _redirectUri,
  105. cancellationToken);
  106.  
  107. await _dataStore.StoreAsync("user", token);
  108. }
  109.  
  110. public static async Task InitializeClientSecretsAsync(CancellationToken cancellationToken)
  111. {
  112. using var stream = new FileStream(FileNameCredentials, FileMode.Open, FileAccess.Read);
  113.  
  114. ClientSecrets = await GoogleClientSecrets.FromStreamAsync(stream, cancellationToken: cancellationToken);
  115. }
  116.  
  117. private async Task InitializeGoogleCredentialsAsync()
  118. {
  119. var tokenResponse = await _dataStore.GetAsync<TokenResponse>("user");
  120. Credential = GoogleCredential.FromAccessToken(tokenResponse.AccessToken);
  121. }
  122.  
  123. #endregion
  124.  
  125. }
  126.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement