Reputation: 4728
I have a small .net Maui app which uses Google login to access files in Google Drive.
The code I am using to get the UserCredential
is as follows:
Note that the sensitive values are fake and shown here as an example.
const string userEmailKey = "UserEmail";
const string redirectUrl = "com.mytestapp.mytestapp://";
var clientId = "82cef48b-9e0e-46b3-ae05-ab53227e9862.apps.googleusercontent.com";
var tokenUrl = "https://oauth2.googleapis.com/token";
var authUrl = $"https://accounts.google.com/o/oauth2/auth?response_type=code" +
$"&redirect_uri={redirectUrl}" +
$"&client_id={clientId}" +
$"&scope=https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/spreadsheets" +
$"&include_granted_scopes=true" +
$"&state=state_parameter_passthrough_value";
var userEmail = Preferences.Get(userEmailKey, null);
if (!string.IsNullOrEmpty(userEmail))
{
authUrl += $"&login_hint={userEmail}"; // I thought this would force login with the email saved in preferences
}
var authResult = await WebAuthenticator.Default.AuthenticateAsync(
new Uri(authUrl),
new Uri(redirectUrl));
var codeToken = authResult.Properties["code"];
var parameters = new FormUrlEncodedContent(
[
new KeyValuePair<string,string>("grant_type","authorization_code"),
new KeyValuePair<string,string>("client_id", clientId),
new KeyValuePair<string,string>("redirect_uri",redirectUrl),
new KeyValuePair<string,string>("code",codeToken)
]
);
HttpClient client = new HttpClient();
var accessTokenResponse = await client.PostAsync(tokenUrl, parameters);
accessTokenResponse.EnsureSuccessStatusCode();
var responseContent = await accessTokenResponse.Content.ReadAsStringAsync();
var accessTokenResponseDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(responseContent);
if (accessTokenResponseDict == null)
{
throw new NullReferenceException("tokenResponse found to be null");
}
// save email to preferences
var idToken = accessTokenResponseDict["id_token"];
var jwt = new JwtSecurityTokenHandler().ReadJwtToken(idToken);
var email = jwt.Claims.FirstOrDefault(c => c.Type == "email")?.Value;
Preferences.Set(userEmailKey, email);
Google.Apis.Auth.OAuth2.Responses.TokenResponse tokenResponse = new TokenResponse()
{
AccessToken = accessTokenResponseDict["access_token"],
ExpiresInSeconds = Convert.ToInt64(accessTokenResponseDict["expires_in"]),
RefreshToken = accessTokenResponseDict["refresh_token"],
Scope = accessTokenResponseDict["scope"],
TokenType = accessTokenResponseDict["token_type"],
};
Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow googleAuthFlow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer()
{
ClientSecrets = new ClientSecrets()
{
ClientId = clientId
}
});
var credential = new UserCredential(googleAuthFlow, "user", tokenResponse);
But the account selection page, consent page keep appearing every time the code above runs.
If I add prompt=none
to the auth url, the process fails.
Is there a different pattern to cache some value so that once user has logged in and consented, they wont be asked again?
Upvotes: 0
Views: 72