GoogleOAuth2Service.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. using System.Text;
  2. using Logging.Net;
  3. using Moonlight.App.Database.Entities;
  4. using Moonlight.App.Exceptions;
  5. using Moonlight.App.Models.Google.Requests;
  6. using RestSharp;
  7. namespace Moonlight.App.Services.OAuth2;
  8. public class GoogleOAuth2Service
  9. {
  10. private readonly bool EnableGoogle;
  11. private readonly string GoogleClientId;
  12. private readonly string GoogleClientSecret;
  13. private readonly bool EnableOverrideUrl;
  14. private readonly string OverrideUrl;
  15. private readonly string AppUrl;
  16. public GoogleOAuth2Service(ConfigService configService)
  17. {
  18. var config = configService
  19. .GetSection("Moonlight")
  20. .GetSection("OAuth2");
  21. EnableGoogle = config
  22. .GetSection("Google")
  23. .GetValue<bool>("Enable");
  24. if (EnableGoogle)
  25. {
  26. GoogleClientId = config.GetSection("Google").GetValue<string>("ClientId");
  27. GoogleClientSecret = config.GetSection("Google").GetValue<string>("ClientSecret");
  28. }
  29. EnableOverrideUrl = config.GetValue<bool>("EnableOverrideUrl");
  30. if (EnableOverrideUrl)
  31. OverrideUrl = config.GetValue<string>("OverrideUrl");
  32. AppUrl = configService.GetSection("Moonlight").GetValue<string>("AppUrl");
  33. }
  34. public Task<string> GetUrl()
  35. {
  36. if (!EnableGoogle)
  37. throw new DisplayException("Google OAuth2 not enabled");
  38. var endpoint = GetBaseUrl() + "/api/moonlight/oauth2/google";
  39. var scope = "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email";
  40. return Task.FromResult(
  41. $"https://accounts.google.com/o/oauth2/auth?response_type=code&client_id={GoogleClientId}&redirect_uri={endpoint}&scope={scope}"
  42. );
  43. }
  44. public async Task<User?> HandleCode(string code)
  45. {
  46. // Generate access token
  47. var endpoint = GetBaseUrl() + "/api/moonlight/oauth2/google";
  48. var googleEndpoint = "https://oauth2.googleapis.com/token";
  49. // Setup payload
  50. var payload = new GoogleOAuth2CodePayload()
  51. {
  52. Code = code,
  53. RedirectUri = endpoint,
  54. ClientId = GoogleClientId,
  55. ClientSecret = GoogleClientSecret
  56. };
  57. using var client = new RestClient();
  58. var request = new RestRequest(googleEndpoint);
  59. request.AddBody(payload);
  60. var response = await client.ExecutePostAsync(request);
  61. if (!response.IsSuccessful)
  62. {
  63. //TODO: Maybe add better error handling
  64. Logger.Debug("oAuth2 validate error: " + response.Content!);
  65. return null;
  66. }
  67. // parse response
  68. var data = new ConfigurationBuilder().AddJsonStream(
  69. new MemoryStream(Encoding.ASCII.GetBytes(response.Content!))
  70. ).Build();
  71. var accessToken = data.GetValue<string>("access_token");
  72. // Now, we will call the google api with our access token to get the data we need
  73. var googlePeopleEndpoint = "https://people.googleapis.com/v1/people/me";
  74. var getRequest = new RestRequest(googlePeopleEndpoint);
  75. getRequest.AddHeader("Authorization", $"Bearer {accessToken}");
  76. getRequest.AddParameter("personFields", "names,emailAddresses");
  77. var getResponse = await client.ExecuteGetAsync(getRequest);
  78. if (!getResponse.IsSuccessful)
  79. {
  80. //TODO: Maybe add better error handling
  81. Logger.Debug("OAuth2 api access error: " + getResponse.Content!);
  82. return null;
  83. }
  84. // Parse response
  85. var getData = new ConfigurationBuilder().AddJsonStream(
  86. new MemoryStream(Encoding.ASCII.GetBytes(getResponse.Content!))
  87. ).Build();
  88. var firstName = getData
  89. .GetSection("names")
  90. .GetChildren()
  91. .First()
  92. .GetValue<string>("givenName");
  93. var lastName = getData
  94. .GetSection("names")
  95. .GetChildren()
  96. .First()
  97. .GetValue<string>("familyName");
  98. var email = getData
  99. .GetSection("emailAddresses")
  100. .GetChildren()
  101. .First()
  102. .GetValue<string>("value");
  103. return new()
  104. {
  105. Email = email,
  106. FirstName = firstName,
  107. LastName = lastName
  108. };
  109. }
  110. private string GetBaseUrl()
  111. {
  112. if (EnableOverrideUrl)
  113. return OverrideUrl;
  114. return AppUrl;
  115. }
  116. }