The following code is throwing returning response from google with the required parameter is missing: response_type. Either the error is misleading with something else or the value might be wrong. Here is the documentation: https://cloud.google.com/docs/authentication/#oauth-2.0-clients
var client = new RestClient("https://accounts.google.com/o/oauth2/auth");
var request = new RestRequest(Method.POST);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddParameter("application/x-www-form-urlencoded", "grant_type=client_credentials&client_id=501819637859-6ng1c949htt0admmpa19vm6tfle04jdc.apps.googleusercontent.com&client_secret=nrrIjxFqugLKd24E8xVesA6f", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Yes it is possible to code your own version of Google Oauth2 flow.
The first call is a HTTP GET and is the link to the consent screen displayed to the user.
If this is an installed application like a desktop app or console app. Then redirect uri should be urn:ietf:wg:oauth:2.0:oob.
Scopes should be separated by space if you want more than one, add offline if you want to get a refresh token back.
GET https://accounts.google.com/o/oauth2/v2/auth?client_id={clientid}&redirect_uri={RedirectURI}&scope={scopes}&response_type=code
The response to the first call is an Authentication Code this code needs to be exchanged with google. This is a HTTP POST
POST https://oauth2.googleapis.com/token
code=4/X9lG6uWd8-MMJPElWggHZRzyFKtp.QubAT_P-GEwePvB8fYmgkJzntDnaiAI&client_id=
{ClientId}&client_secret={ClientSecret}&redirect_uri={RedirectURI}&grant_type=authorization_code
The post data for this call is one long string do not try to parse it. Just post it in the body of your call. You are correct that the content type is "application/x-www-form-urlencoded";
The response to this call will contain an access token and a refresh token
{
"access_token" : "ya29.1.AADtN_VSBMC2Ga2lhxsTKjVQ_ROco8VbD6h01aj4PcKHLm6qvHbNtn-_BIzXMw",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "1/J-3zPA8XR1o_cXebV9sDKn_f5MTqaFhKFxH-3PUPiJ4"
}
The access token will expire after one hour so you will need to refresh it thats what the refresh token is for.
The following call is also a HTTP POST
https://oauth2.googleapis.com/token
client_id={ClientId}&client_secret={ClientSecret}&refresh_token={Refresh token from previous call}&grant_type=refresh_token
class Program
{
private const string Clientid = "Add yours";
private const string Secret = "Add yours.";
static async Task Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.WriteLine($"open the following link in your browser window: {Helper.BuildConsentURL(Clientid, new []{ "profile" })}");
Console.WriteLine("Please paste the Authorization code here:");
var authorizationCode = Console.ReadLine();
var tokenResponse = await Helper.ExchangeAuthorizationCode(authorizationCode, Clientid, Secret);
var refreshTokenResponse = await Helper.ExchangeRefreshToken(tokenResponse.refresh_token, Clientid, Secret);
}
}
public class Helper
{
/// <summary>
///
/// </summary>
/// <param name="clientId"></param>
/// <param name="scope">string array of scopes</param>
/// <param name="redirectUri">leave empty for installed application</param>
/// <returns></returns>
public static string BuildConsentURL(string clientId, string[] scope, string redirectUri = null)
{
if (string.IsNullOrEmpty(redirectUri))
{
redirectUri = "urn:ietf:wg:oauth:2.0:oob"; // for installed application
}
return
$"https://accounts.google.com/o/oauth2/auth?client_id={clientId}&redirect_uri={redirectUri}&scope={string.Join(" ", scope)}&response_type=code";
}
private static string BuildAuthorizationCodeRequest(string code, string clientId, string secret,
string redirectUri)
{
return
$"code={code}&client_id={clientId}&client_secret={secret}&redirect_uri={redirectUri}&grant_type=authorization_code";
}
private static string BuildRefreshAccessTokenRequest(string refreshToken, string clientId, string secret)
{
return
$"client_id={clientId}&client_secret={secret}&refresh_token={refreshToken}&grant_type=refresh_token";
}
private static async Task<AuthResponse> PostMessage(string postData)
{
AuthResponse result;
var client = new HttpClient();
client.BaseAddress = new Uri("https://accounts.google.com/");
var request = new HttpRequestMessage(HttpMethod.Post, "o/oauth2/token");
request.Content = new StringContent(postData, Encoding.UTF8, "application/x-www-form-urlencoded");
var response = await client.SendAsync(request);
using (var content = response.Content)
{
var json = content.ReadAsStringAsync().Result;
result = JsonSerializer.Deserialize<AuthResponse>(json);
}
return result;
}
public static async Task<AuthResponse> ExchangeAuthorizationCode(string code, string clientId, string secret,
string redirectUri = null)
{
var result = new AuthResponse();
if (string.IsNullOrEmpty(redirectUri))
{
redirectUri = "urn:ietf:wg:oauth:2.0:oob"; // for installed application
}
var postData = BuildAuthorizationCodeRequest(code, clientId, secret, redirectUri);
return await PostMessage(postData);
}
public static async Task<AuthResponse> ExchangeRefreshToken(string refreshToken, string clientId, string secret)
{
var postData = BuildRefreshAccessTokenRequest(refreshToken, clientId, secret);
return await PostMessage(postData);
}
}
public class AuthResponse
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public string refresh_token { get; set; }
}