I am very new to OAuth Arena and Google ApI but what I am trying to achieve here is very simple.
User Clicks on Google Connect button and my webservice should be able to get all the user Profile Info from Google server:
I have already written code to get AccessToken(I am yet to test it) but assuming that is working fine, now how should I ask Google API to give me user profile? I do see static function called Get Contacts in GoogleConsumer Class but I do not see any option to get profiledata. May be there is something that I am missing?
Here is my code using which i am getting accessToken:
IConsumerTokenManager tokenManager =
new LocalTokenManager(consumerKey,consumerSecret);
var googleConsumer =
new WebConsumer(GoogleConsumer.ServiceDescription, tokenManager);
var tokenResult = googleConsumer.ProcessUserAuthorization();
return tokenResult.AccessToken;
Now, how do I get user profile out of it?
Once you have your Access_Token (access type offline; and scope/permission is set so you can get user information), you can try the following (not tested, please let me know if any errors occur):
string userInfo = "";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(action);
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
StreamReader sr = new StreamReader(resp.GetResponseStream());
userInfo = "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + "YOUR_ACCESSTOKEN";
sr.Close();
JObject jsonResp = JObject.Parse(userInfo);
string info="";
info += "<h3>" + jsonResp.Root["name"] + "</h3>";
info += "<img src='" + jsonResp.Root["picture"] + "' width='120'/><br/>";
info += "<br/>ID : " + jsonResp.Root["id"];
info += "<br/>Email : " + jsonResp.Root["email"];
info += "<br/>Verified_email : " + jsonResp.Root["verified_email"];
info += "<br/>Given_name : " + jsonResp.Root["given_name"];
info += "<br/>Family_name : " + jsonResp.Root["family_name"];
info += "<br/>Link : " + jsonResp.Root["link"];
info += "<br/>Gender : " + jsonResp.Root["gender"];
Response.Write(info);
Flow : Requesting the google userinfo url with the access token, get the response and displaying the information.
let me know what do you think about accessing profile's google info with their GET method, described here https://developers.google.com/+/api/latest/people/get?
This is my C# example.
string urlGoogle = "https://www.googleapis.com/plus/v1/people/me";
HttpWebRequest client = HttpWebRequest.Create(urlGoogle) as HttpWebRequest;
client.Method = "GET";
client.Headers.Add("Authorization", "Bearer " + accessToken);
using (HttpWebResponse response = (HttpWebResponse)client.GetResponse())
{
using (Stream dataStream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(dataStream))
{
if (response.StatusCode == HttpStatusCode.OK)
{
var json = new JavaScriptSerializer();
var data = json.Deserialize<IDictionary<string, object>>(reader.ReadToEnd());
//....... here in data you have all json fields for the profile
Related
Context
I am developing a simple application that requires to receive List Data from a company Online SharePoint site. In order to make REST requests, I must first retrieve an access token from Microsoft's access control service. Despite attempting some tutorials and reading documentation, I am new to REST/HTTP am am failing to do so.
What have I tried?
Used SharePoint appregnew.aspx to register my app, and generate "Client ID" and "Client Secret" values. https://[sitename].sharepoint.com/_layouts/15/appregnew.aspx
Used Sharepoint appinv.aspx to authorize my app with read control and generate a "Tenant ID".
https://[sitename].sharepoint.com/_layouts/15/appinv.aspx
<AppPermissionRequests AllowAppOnlyPolicy="true">
<AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web" Right="Read"/>
</AppPermissionRequests>
Used SharePoint AppPrincipals.aspx to verify Tenant ID. https://[sitename].sharepoint.com/_layouts/15/AppPrincipals.aspx
Attempted several methods of formatting the request with the following being the latest:
Updated
// Variables removed for security
class Program
{
static void Main(string[] args)
{
WebRequest myWebRequest;
string stGetAccessTokenUrl = "https://accounts.accesscontrol.windows.net/{0}/tokens/OAuth/2";
string tenantID = "myTenantID";
string resourceID = "00000003-0000-0ff1-ce00-000000000000";
string stClientID = "myClientID";
string stClientSecret = "myClientSecret";
string stSiteDomain = "[myCompany].sharepoint.com";
// URL Format
stGetAccessTokenUrl = string.Format(stGetAccessTokenUrl, tenantID);
myWebRequest = WebRequest.Create(stGetAccessTokenUrl);
myWebRequest.ContentType = "application/x-www-form-urlencoded";
myWebRequest.Method = "POST";
// Add the below body attributes to the request
var postData = "grant_type=client_credentials";
postData += "&client_id=" + stClientID + "#" + tenantID;
postData += "&client_secret=" + stClientSecret;
postData += "&resource=" + resourceID + "/" + stSiteDomain + "#" + tenantID;
var data = Encoding.ASCII.GetBytes(postData);
using (var stream = myWebRequest.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)myWebRequest.GetResponse();
}
}
What doesn't work?
I receive a 401 Unauthorized error despite the app having been assigned permissions.
Any help would be greatly appreciated!
Apologies, I forgot to return to this question upon resolving the issue. Credit to "Michael Han" within the comments of his own answer.
Answer
By default, the SharePoint app-only permissions is disabled for the tenant. A tenant administrator must first run the following cmdlet in PowerShell:
Set-SPOTenant -DisableCustomAppAuthentication $false
This parameter supersedes all other privilege settings and must first be configured.
You could refer to this article to get the access token : https://social.technet.microsoft.com/wiki/contents/articles/51982.sharepoint-read-online-list-data-from-c-console-application-using-access-token.aspx
#region Get Access Token using TenantID and App secret ID & Password
// URL Format
//https://accounts.accesscontrol.windows.net/tenant_ID/tokens/OAuth/2 Jump
stGetAccessTokenUrl = string.Format(stGetAccessTokenUrl, tenantID);
myWebRequest = WebRequest.Create(stGetAccessTokenUrl);
myWebRequest.ContentType = "application/x-www-form-urlencoded";
myWebRequest.Method = "POST";
// Add the below body attributes to the request
/*
* grant_type client_credentials client_credentials
client_id ClientID#TenantID
client_secret ClientSecret
resource resource/SiteDomain#TenantID resourceid/abc.sharepoint.com#tenantID
*/
var postData = "grant_type=client_credentials";
postData += "&client_id=" + stClientID +"#" +tenantID;
postData += "&client_secret=" + stClientSecret;
postData += "&resource=" + resourceID + "/" + stSiteDomain + "#" + tenantID;
var data = Encoding.ASCII.GetBytes(postData);
using (var stream = myWebRequest.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)myWebRequest.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
string[] stArrResponse = responseString.Split(',');
//get the access token and expiry time ,etc
foreach(var stValues in stArrResponse)
{
if(stValues.StartsWith("\"access_token\":"))
{
//Console.WriteLine(" Result => " + stValues);
accessToken = stValues.Substring(16);
//Console.WriteLine(" Result => " + accessToken);
accessToken = accessToken.Substring(0,accessToken.Length-2);
// Console.WriteLine(" Result => " + accessToken);
}
}
I have read and read and played with this code inside out and I still cant work out how to get the refresh token. This in c#
I have tried different combo of access_type, prompt and approval_prompt params.
I keep revoking access by my user to the app, so when the auth code is being requested it does ask for myself to approve the app to be able to access.
I just want to get the refresh token so i can store it and keep refreshing.
here is the code below. I have removed the parts to get the auth code, but if it is needed i can add in. I wonder if anyone can simply spot something simply wrong.
string GetJsonFromAPICall(string p_url,string p_post_data, string p_b64_id_secret)
{
//string C_TOKEN_URL = "https://oauth2.googleapis.com/token";
string l_auth_string = "Basic " + p_b64_id_secret;
print("p_post_data = ", p_url + "?"+p_post_data);
print("Authorization", l_auth_string);
HttpWebRequest request = WebRequest.Create(p_url) as HttpWebRequest;
string postData = p_post_data;// "grant_type=authorization_code&code=" + p_auth_code + "&redirect_uri=" + p_redirect_url;
request.Headers.Add("Authorization", l_auth_string);
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
print("pos 20 in GetJsonFromAPICall");
print("length ", data.Length.ToString());
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
return responseString;
}
string getAccessToken(string p_b64_id_secret, string p_auth_code, string p_redirect_url)
{
//string l_url = "client_id="+ p_C_GBQ_ONLINE_APP_APP_CLIENT_ID + "&client_secret="+ p_C_GBQ_ONLINE_APP_APP_CLIENT_SECRET + "access_type=offline&prompt=consent&grant_type=authorization_code&code=" + p_auth_code + "&redirect_uri=" + p_redirect_url;
string l_params = "grant_type=authorization_code&code=" + p_auth_code + "&redirect_uri=" + p_redirect_url;
l_params += "&access_type=offline";
l_params += "&prompt=consent";
l_params += "&approval_prompt=force";
//return GetJsonFromAPICall("https://oauth2.googleapis.com/token", l_params, p_b64_id_secret);
return GetJsonFromAPICall("https://www.googleapis.com/oauth2/v4/token", l_params, p_b64_id_secret);
}
var credentials = string.Format("{0}:{1}", C_GBQ_ONLINE_APP_APP_CLIENT_ID, C_GBQ_ONLINE_APP_APP_CLIENT_SECRET_ID);
var b64_id_secret = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials));
string l_auth_code = "xxxxx"; // worked out successfully earlier
l_json_returned = getAccessToken(p_b64_id_secret, l_auth_code, C_GBQ_ONLINE_APP_REDIRECT_URL);
the returned json is
l_json_returned = : {
"access_token": "FFFFFFFF",
"expires_in": 3569,
"scope": "https://www.googleapis.com/auth/cloud-platform.read-only https://www.googleapis.com/auth/bigquery",
"token_type": "Bearer"
}
So I am trying to fetch my classes from my google classroom into my application:
Here is my google url:
var Googleurl = "https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=" + googleplus_redirect_url + "&prompt=consent&response_type=code&client_id=" + googleplus_client_id + "&scope=https://www.googleapis.com/auth/userinfo.profile+https://www.google.com/m8/feeds/+https://www.googleapis.com/auth/drive+https://www.googleapis.com/auth/drive.appdata+https://www.googleapis.com/auth/drive.file+https://www.googleapis.com/auth/drive.metadata+https://www.googleapis.com/auth/classroom.courses+https://www.googleapis.com/auth/classroom.profile.emails+https://www.googleapis.com/auth/classroom.profile.photos+https://www.googleapis.com/auth/classroom.rosters+https://www.googleapis.com/auth/classroom.rosters.readonly&access_type=offline";
After this I request for the access codes through:
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://accounts.google.com/o/oauth2/token");
webRequest.Method = "POST";
Parameters = "code=" + code + "&client_id=" + googleplus_client_id + "&client_secret=" + googleplus_client_sceret + "&redirect_uri=" + googleplus_redirect_url + "&grant_type=authorization_code";
byte[] byteArray = Encoding.UTF8.GetBytes(Parameters);
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ContentLength = byteArray.Length;
Stream postStream = webRequest.GetRequestStream();
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
WebResponse response = webRequest.GetResponse();
postStream = response.GetResponseStream();
StreamReader reader = new StreamReader(postStream);
string responseFromServer = reader.ReadToEnd();
GooglePlusAccessToken serStatus = JsonConvert.DeserializeObject<GooglePlusAccessToken>(responseFromServer);
I am able to get the access code as well as the refresh token all fine.
Now when I wish to fetch my classroom by:
string p="https://classroom.googleapis.com/v1/courses";
string auth = "Bearer "+access_token;
private bool GetClasses(string p,string auth)
{
using (var client = new WebClient())
{
var uri = new Uri(p);
//client.DefaultRequestHeaders.Authorization=new AuthenticationHeaderValue("Bearer", auth);
string req="Authorization: "+ auth;
client.Headers.Add(req);
var response = client.DownloadString(uri);
}
return true;
}
This code return an error of type:System.Net.WebException: {"The remote server returned an error: (403) Forbidden."}
I have used the same access_token to get all other scopes as shown in the scopes parameter in mu Googleurl. However I am unable to access my classes even though I've added the respective scopes for it.
Apparently to use google classroom related functionalities we need to enable the google classroom Api. As silly as it may sound I was ignorant about it(As I had already enabled the google Api service). Just had to activate the classroom api and the code worked like a charm.
This is less a question than an answer. I figured I would want to share this with you, since I was a bit confused finding so litte about the ebay OAuth 2.0 in combination with a C# web application.
I tried starting to use the RESTsharp library, but got stuck at the point, where the body content was created. RESTsharp prefers XML or JSON, ebay want's a string with params.
So to give you all a little help if you run into the same issue, I decided to post my solution (not using RESTsharp).
public class HomeController : Controller {
string clientId = "YOUR_CLIENT_ID";
string clientSecret = "YOUR_CLIENT_SECRET";
string ruName = "YOUR_RU_NAME";
// Redirect the request to get a request token
public ActionResult Index() {
var authorizationUrl =
"https://signin.sandbox.ebay.de/authorize?" +
"client_id=" + clientId + "&" +
"redirect_uri=" + ruName + "&" +
"response_type=code";
Response.Redirect(authorizationUrl);
return View();
}
// I used Test as a method to test the result in the controller, use your apropriate method here
public ActionResult Test(string code)
{
ViewBag.Code = code;
// Base 64 encode client Id and client secret
var clientString = clientId + ":" + clientSecret;
byte[] clientEncode = Encoding.UTF8.GetBytes(clientString);
var credentials = "Basic " + System.Convert.ToBase64String(clientEncode);
HttpWebRequest request = WebRequest.Create("https://api.sandbox.ebay.com/identity/v1/oauth2/token")
as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Headers.Add(HttpRequestHeader.Authorization, credentials);
var codeEncoded = HttpUtility.UrlEncode(code);
var body = "grant_type=authorization_code&code=" + codeEncoded + "&redirect_uri=" + ruName;
// Encode the parameters as form data
byte[] formData = UTF8Encoding.UTF8.GetBytes(body);
request.ContentLength = formData.Length;
// Send the request
using (Stream post = request.GetRequestStream())
{
post.Write(formData, 0, formData.Length);
}
// Pick up the response
string result = null;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
result = reader.ReadToEnd();
}
ViewBag.Response = result;
return View();
}
If you output ViewBag.Response you will see the authorization code. Have fun.
How is your redirect url looking in sandbox? Seems like the url should be https. In this stage in dev environment and don't have server with https. How did you deal with that?
Ta
I'm trying to make windows phone silverlight app that reads web page source. And it does, but only for pages that don't need authentication. I am new to programming and I looked WP8 JumpStart at MVA and their example works fine until I try access specific page that have SSL. For the past two days I tried bunch of thing but nothing worked for me. This is my most recent function that should do the job:
private async void ReadPage()
{
CookieContainer container = new CookieContainer();
var request = HttpWebRequest.Create("url") as HttpWebRequest;
byte[] bytes = System.Text.UTF8Encoding.UTF8.GetBytes("usrname" + ":" + "pass");
string authInfo = Convert.ToBase64String(bytes);
request.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " + authInfo;
request.CookieContainer = container;
request.Accept = "application/json;odata=verbose";
var factory = new TaskFactory();
var task = factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
try
{
var response = await task;
Stream responseStream = response.GetResponseStream();
string data;
using (var reader = new StreamReader(responseStream))
{
data = reader.ReadToEnd();
}
txtContent.Text = data;
}
catch (Exception e)
{
var we = e.InnerException as WebException;
if (we != null)
{
var resp = we.Response as HttpWebResponse;
var code = resp.StatusCode;
MessageBox.Show("RespCallback Exception raised! Message: " + we.Message +
" HTTP Status: " + we.Status);
}
else
throw e;
}
}
Every time I call it, it takes me to the login site which should be already authenticated. At least I think so... I looked at few solutions but nothing helpful for me (or I overlooked something). Does anyone have an idea?
Thanks in advance