Grettings,
I'm really struggling with the google authentication. I got to the point where I get an authentication code generated for the user, by redirecting him to a page (will provide code below) and that was pretty easy. But I can't find a way to convert that code to the access token.
I tried using ExchangeCodeForTokenAsync but that either led me to a thread lock or other thread problems because the method has to be executed on page load.
I found a solution with HttpWebRequest to make a call to the api, but that gets me a Bad request response (will provide a code for this also)
I'm using DotNetNuke, if I am able to get the user info I can authenticate them (I have a custom login, I am not using the DNN one), but for that I need the access token.
Redirect to google login page:
string redirectUri = "https://url.com/google";
string[] Scopes = { "openid", "email" };
var flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = "client_id",
ClientSecret = "client_secret "
},
Scopes = Scopes,
});
var authorizationUrl = flow.CreateAuthorizationCodeRequest(redirectUri).Build();
Response.Redirect(authorizationUrl.AbsoluteUri);
Current code of the redirection page which gets the code after google auth:
public class GoogleToken
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public string id_token { get; set; }
public string refresh_token { get; set; }
}
public class GoogleInfo
{
public string id { get; set; }
public string email { get; set; }
public bool verified_email { get; set; }
public string name { get; set; }
public string given_name { get; set; }
public string family_name { get; set; }
public string picture { get; set; }
public string locale { get; set; }
public string gender { get; set; }
}
protected void Page_Load(object sender, EventArgs e)
{
string ClientId = "client_id";
string ClientSecret = "client_secret";
string redirecturl = "https://url.com/google";
try
{
if (!IsPostBack)
{
string code = Request.QueryString["code"];
if (!string.IsNullOrEmpty(code))
{
string parameters = string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code", code,
ClientId,
ClientSecret,
redirecturl);
string response = MakeWebRequest("https://oauth2.googleapis.com/token", "POST", "application/x-www-form-urlencoded", parameters);
GoogleToken tokenInfo = new JavaScriptSerializer().Deserialize<GoogleToken>(response);
if (tokenInfo != null)
{
if (!string.IsNullOrEmpty(tokenInfo.access_token))
{
var googleInfo = MakeWebRequest("https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + tokenInfo.access_token, "GET");
GoogleInfo profile = new JavaScriptSerializer().Deserialize<GoogleInfo>(googleInfo);
ltrMSG.Text = googleInfo;
}
}
}
}
}
catch (Exception ex)
{
ltrMSG.Text += "<br/>" + ex.ToString();
}
}
public string MakeWebRequest(string destinationUrl, string methodName, string contentType = "", string requestJSON = "")
{
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(destinationUrl);
request.Method = methodName;
if (methodName == "POST")
{
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(requestJSON);
request.ContentType = contentType;
request.ContentLength = bytes.Length;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
return reader.ReadToEnd();
}
}
}
return null;
}
catch (WebException webEx)
{
return webEx.ToString();
}
}
}
I will be grateful if anyone can provide me with snippets of what I should be doing, tell me what I am doing wrong or point me in the right direction. Thank you!
That's Oauth2 authorization code, not login. Not to mention that GoogleAuthorizationCodeFlow is designed for installed applications and wont work if you try to host it on a web server.
You should check out Google external login setup in ASP.NET Core
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
var configuration = builder.Configuration;
services.AddAuthentication().AddGoogle(googleOptions =>
{
googleOptions.ClientId = configuration["Authentication:Google:ClientId"];
googleOptions.ClientSecret = configuration["Authentication:Google:ClientSecret"];
});