Reputation: 317
I am trying to integrate google authentication in my ASP.NET MVC application, but after Google verification, I am getting the below screen. It is not hitting the GoogleLoginCallback
method. Instead of that, I am getting this screen:
[]
Here's the Javascript code I used for implementing this functionality:
<script type="text/javascript">
document.getElementById('googleLoginButton').onclick = function() {
try {
var clientId = '@GoogleClientId';
var redirectUri = '@GoogleRedirectionUrl';
// Create a state object with additional data
var stateData = {
returnUrl: window.location.pathname || "/Home/Index" // Default to home if no return URL is set
};
// Encode the state object as a JSON string and then base64 encode it
var state = btoa(JSON.stringify(stateData));
// URL-encode the state parameter to handle special characters
var encodedState = encodeURIComponent(state);
// Construct the Google OAuth URL with the encoded state parameter
var googleAuthUrl = `https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=openid%20email%20profile&state=${encodedState}`;
// Redirect the user to Google's authentication page
window.location.href = googleAuthUrl;
} catch (error) {
console.error("Error during Google authentication:", error);
alert("An error occurred during Google authentication. Please try again.");
}
};
</script>
My controller code:
[AllowAnonymous]
public async Task<ActionResult> GoogleLoginCallback(string state, string code, string scope, string authuser, string hd, string prompt)
{
try
{
// Decode the state parameter
var decodedState = HttpUtility.UrlDecode(state);
var stateData = JsonConvert.DeserializeObject<dynamic>(Encoding.UTF8.GetString(Convert.FromBase64String(decodedState)));
// Extract the returnUrl from the state object
var returnUrl = stateData.returnUrl ?? "/Home/Index";
// Step 1: Exchange the authorization code for an access token
var client = new HttpClient();
var tokenRequest = new Dictionary<string, string>
{
{ "code", code },
{ "client_id", ConfigurationManager.AppSettings["GoogleClientId"] },
{ "client_secret", ConfigurationManager.AppSettings["GoogleClientSecret"] },
{ "redirect_uri", ConfigurationManager.AppSettings["GoogleRedirectionUrl"] },
{ "grant_type", "authorization_code" }
};
var tokenResponse = await client.PostAsync("https://oauth2.googleapis.com/token", new FormUrlEncodedContent(tokenRequest));
var tokenResponseString = await tokenResponse.Content.ReadAsStringAsync();
var tokenJson = JsonConvert.DeserializeObject<JObject>(tokenResponseString);
var accessToken = tokenJson["access_token"]?.ToString();
if (string.IsNullOrEmpty(accessToken))
{
throw new Exception("Unable to retrieve access token from Google.");
}
// Step 2: Use the access token to fetch user info from Google
var userInfoResponse = await client.GetAsync($"https://www.googleapis.com/oauth2/v2/userinfo?access_token={accessToken}");
var userInfoResponseString = await userInfoResponse.Content.ReadAsStringAsync();
var userInfoJson = JsonConvert.DeserializeObject<JObject>(userInfoResponseString);
var email = userInfoJson["email"]?.ToString();
var name = userInfoJson["name"]?.ToString();
// Step 3: Redirect to the return URL
return Redirect(returnUrl);
}
catch (Exception ex)
{
// Log the exception for debugging
System.Diagnostics.Debug.WriteLine($"Error in GoogleLoginCallback: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"Stack Trace: {ex.StackTrace}");
// Redirect to an error page or the login page
return RedirectToAction("Login");
}
}
In the startup.cs
file, I have this code:
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/MLALogin/Login"), // Match your login path
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Configure Google Authentication
app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
{
ClientId = ConfigurationManager.AppSettings["GoogleClientId"],
ClientSecret = ConfigurationManager.AppSettings["GoogleClientSecret"],
CallbackPath = new PathString("/MLALogin/GoogleLoginCallback") // Match your callback path
});
}
Here are the configurations made in RouteConfig.cs
:
routes.MapRoute(
name: "GoogleLoginCallback",
url: "MLALogin/GoogleLoginCallback",
defaults: new { controller = "MLALogin", action = "GoogleLoginCallback", id = UrlParameter.Optional }
).RouteHandler = new DebugRouteHandler();
routes.MapRoute(
name: "MlaLogin",
url: "{controller}/{action}/{id}",
defaults: new { controller = "MLALogin", action = "Login", id = UrlParameter.Optional }
).RouteHandler = new DebugRouteHandler();
In my Google console, I have the following settings:
It will be really helpful if anyone can help me to figure out the root cause for failing google authentication implementation.
Showing the token in url is also a security issue. Is there any way to prevent this?
Upvotes: 0
Views: 26