using System; using System.Collections.Generic; using System.Linq; using Wino.Core.Domain.Exceptions; namespace Wino.Core.Domain.Models.Authorization { public class GoogleAuthorizationRequest { public const string RedirectUri = "google.pw.oauth2:/oauth2redirect"; const string authorizationEndpoint = "https://accounts.google.com/o/oauth2/v2/auth"; const string CodeChallangeMethod = "S256"; public GoogleAuthorizationRequest(string state, string codeVerifier, string codeChallange) { State = state; CodeVerifier = codeVerifier; CodeChallange = codeChallange; } // Pre public string State { get; set; } public string CodeVerifier { get; set; } public string CodeChallange { get; set; } public string ClientId { get; set; } // Post public string AuthorizationCode { get; set; } public string BuildRequest(string clientId) { ClientId = clientId; // Creates the OAuth 2.0 authorization request. return string.Format("{0}?response_type=code&scope=https://mail.google.com/ https://www.googleapis.com/auth/gmail.labels https://www.googleapis.com/auth/userinfo.profile&redirect_uri={1}&client_id={2}&state={3}&code_challenge={4}&code_challenge_method={5}", authorizationEndpoint, Uri.EscapeDataString(RedirectUri), ClientId, State, CodeChallange, CodeChallangeMethod); } public void ValidateAuthorizationCode(Uri callbackUri) { if (callbackUri == null) throw new GoogleAuthenticationException(Translator.Exception_GoogleAuthCallbackNull); string queryString = callbackUri.Query; Dictionary queryStringParams = queryString.Substring(1).Split('&').ToDictionary(c => c.Split('=')[0], c => Uri.UnescapeDataString(c.Split('=')[1])); if (queryStringParams.ContainsKey("error")) throw new GoogleAuthenticationException(string.Format(Translator.Exception_GoogleAuthError, queryStringParams["error"])); if (!queryStringParams.ContainsKey("code") || !queryStringParams.ContainsKey("state")) throw new GoogleAuthenticationException(Translator.Exception_GoogleAuthCorruptedCode + queryString); // Gets the Authorization code & state string code = queryStringParams["code"]; string incomingState = queryStringParams["state"]; // Compares the receieved state to the expected value, to ensure that // this app made the request which resulted in authorization if (incomingState != State) throw new GoogleAuthenticationException(string.Format(Translator.Exception_GoogleAuthInvalidResponse, incomingState)); AuthorizationCode = code; } } }