ChatGpt and Gemini both are loaded with the old information and hence I was not able to get the answer initially, but after having a good discussion with Gemini (after all it is Google LLM ha ha ha and I am trying to use Google OAuth), Gemini took me in the right direction. Here is the way I have implemented it and it is working all right for me now.
I am using .Net 9, MAUI for Android
Nuget package : Duende.IdentityModel.OidcClient (6.0.1)
public sealed class GoogleLoginService
{
const string clientId = "Your-client-id";
const string redirectUri = "com.company.app:/oauth2redirect"; // You can set the first part as your android package name
const string authority = "https://accounts.google.com/o/oauth2/v2/auth";
const string scope = "openid profile email";
const string userInfoEndpoint = "https://openidconnect.googleapis.com/v1/userinfo";
public async Task<string> PerformOAuthLogin()
{
try
{
var browser = new WebAuthenticatorBrowser();
var options = new OidcClientOptions
{
Authority = authority,
ClientId = clientId,
Scope = scope,
RedirectUri = redirectUri,
Browser = browser,
ProviderInformation = new ProviderInformation
{
IssuerName = "accounts.google.com",
AuthorizeEndpoint = authority,
TokenEndpoint = "https://www.googleapis.com/oauth2/v4/token",
UserInfoEndpoint = userInfoEndpoint,
KeySet = new JsonWebKeySet()
},
};
var oidcClient = new OidcClient(options);
var loginResult = await oidcClient.LoginAsync();
if (loginResult.IsError)
{
throw new Exception($"Failed to authenticate with Google: {loginResult.Error}");
}
return loginResult.AccessToken;
}
catch (Exception)
{
throw;
}
}
class WebAuthenticatorBrowser : Duende.IdentityModel.OidcClient.Browser.IBrowser
{
public async Task<BrowserResult> InvokeAsync(BrowserOptions options,
CancellationToken cancellationToken = default)
{
try
{
WebAuthenticatorResult result =
await WebAuthenticator.AuthenticateAsync(
new Uri(options.StartUrl),
new Uri(options.EndUrl));
var url = new RequestUrl(redirectUri)
.Create([.. result.Properties]);
return new BrowserResult
{
Response = url,
ResultType = BrowserResultType.Success,
};
}
catch (TaskCanceledException ex)
{
return new BrowserResult()
{
ResultType = BrowserResultType.UserCancel,
Error = ex.Message
};
}
}
}
}
There could be better ways to do it but for the time being I am going ahead with this approach.