Web Pushnotification PUSH API and service worker C# - Not seeing notifcation - c#

have followed the steps mentioned in the Push code lab Push Notifications site to integrated Push notification in my dot net ``site
1.register Service worker and also was able to see the Subscription on the page.
Subscription:
Step: have down Loaded the C# Library to send the Push Notifications and have added Test Program to test this C#code. i am able to run the code and no Error were shown but i am not seeing any Push Notification in the Chrome Browser( Kept the same Browser tab opened where i have my Site Running / Also closed the browser and Relaunched to see any Notification).In Either case i am not seeing any Notifications
I am not seeing any Error from the Code an
below is the Response from Web pushClient.
{StatusCode: 201, ReasonPhrase: 'Created', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: { X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN X-XSS-Protection: 1; mode=block Alt-Svc: quic=":443"; ma=2592000; v="39,38,37,36,35" Cache-Control: max-age=0, private Date: Wed, 05 Jul 2017 15:59:43 GMT Location: https://fcm.googleapis.com/fcm/0:1499270383802342%e609af1cf9fd7ecd Server: GSE Content-Length: 0 Content-Type: text/plain Expires: Wed, 05 Jul 2017 15:59:43 GMT }}
var pushEndpoint = #"https://fcm.googleapis.com/fcm/send/dKUDjOvvyjg:APA91bF3jr2gsX--KjonylSL_25TfCGG5mVsFZoYgnESYLep2rlWOI6KK1T9Dghr9E8o1e7a0wtOCH2LqmcCV0pjW7ZuDW7wPptJnnXy3XBu4Eo_CX0fLYGqsqy8voU9pFg6eZyaDFab";
var p256dh = #"BMEI2Zz1LPeFBeBtEZlTV_St0PHb6v_OlldbUoE6wrnnx8ychyz4o7tMt_S_Z0bKQj3vOAS0lMuZRRrgO7-LEGo=";
var auth = #"hwrfOP0UUevO5UdB6WRIQw==";
var subject = #"mailto:megan#gmail.com";
var publicKey = #"BK4ITwwSPZpxelX-oaycWnPuRSnRetbu3QBY4hSm5f1Up24PTrktIrJxRXR9bUIqrGx2YFcDCv48sDwFW50jdmI";
var privateKey = #"PEW_j759M2Q218O9le3GS8OnejmwlWYI1-LtNAP31bg";
var subscription = new PushSubscription(pushEndpoint, p256dh, auth);
var vapidDetails = new VapidDetails(subject, publicKey, privateKey);
//var gcmAPIKey = #"[your key here]";
var webPushClient = new WebPushClient();
try
{
webPushClient.SendNotification(subscription, "payload", vapidDetails);
//webPushClient.SendNotification(subscription, "payload", gcmAPIKey);
}
catch (WebPushException exception)
{
Console.WriteLine("Http STATUS code" + exception.StatusCode);
}

After looking at your service worker source, I think you need to move the showNotification call inside the event.waitUntil call. So something like this:
event.waitUntil(self.registration.showNotification(title, options));
However if you're getting notifications on your home network and not your work network, that leads me to believe something on your work network is blocking it.

Related

How to set up .net core teradata connection in c#?

I am trying to connect to Teradata with dotnet core driver: Teradata.Client.Provider 17.10.2.
I have set-up a Teradata Vantage Express instance and I am able to connect to it via DBeaver (JDBC) with default credentials dbc/dbc.
Based on docs and this answer https://stackoverflow.com/a/21267030/3120219 I'm now trying to connect via a C# driver with the following code:
using System;
using Teradata.Client.Provider;
using Xunit;
namespace MyProject.Test
{
public class TeradataConnectionTest
{
public void TestConnection()
{
var connectionStringBuilder = new TdConnectionStringBuilder
{
DataSource = "localhost",
Database = "dbc",
UserId = "dbc",
Password = "dbc",
AuthenticationMechanism = "TD2" // Tried also "LDAP" and "TDNEGO"
};
using TdConnection cn = new TdConnection();
cn.ConnectionString = connectionStringBuilder.ConnectionString;
cn.Open(); // exception here
TdCommand cmd = cn.CreateCommand();
cmd.CommandText = "SELECT DATE";
using (TdDataReader reader = cmd.ExecuteReader())
{
reader.Read();
DateTime date = reader.GetDate(0);
}
}
}
}
But I'm receiving this exception on connection open:
Teradata.Client.Provider.TdException
[.NET Data Provider for Teradata] [115057] The WebSocket handshake response is invalid. Details: Unexpected or invalid response received.
HTTP/1.1 302 Found
Cache-Control: public, no-store, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:
Strict-Transport-Security: max-age=15768000; includeSubDomains
Location: /login.html
Transfer-Encoding: chunked
Date: Tue, 01 Feb 2022 17:30:07 GMT
Server: Teradata-Viewpoint
It seems that the client is trying to connect to the webserver instead of the data provider services.
What am I missing ?

how to impersonate a user via odata

We have been succesful in using the odata v8.1 endpoint in 2016 to impersonate a user.
Please note that the intended request flow is: Postman-->LocalHost Microservice-->CRM
Example of a working request from Postman-->CRM (directly, without going through the microservice)
Accept:application/json
Content-Type:application/json; charset=utf-8
OData-MaxVersion:4.0
OData-Version:4.0
MSCRMCallerID:d994d6ff-5531-e711-9422-00155dc0d345
Cache-Control:no-cache
Against the odata endpoint: ..../api/data/v8.1/leads
Note that this has been successful only when issued directly against the odata v8.1 endpoint via postman.
When attempting to do the same, having a service running locally (Postman-->LocalHost Service-->CRM), this fails, and simply ignores??? the MSCRMCallerID header.
Upon examining headers that were passed to the LocalHost Microservice from Postman, the request, as examined by the debugger in VS 2017:
{Method: POST, RequestUri: 'https://.../api/data/v8.1/leads', Version: 1.1, Content: System.Net.Http.StringContent, Headers:
{
OData-Version: 4.0
OData-MaxVersion: 4.0
MSCRMCallerID: D994D6FF-5531-E711-9422-00155DC0D345
Cache-Control: no-cache
Accept: application/json
Content-Type: application/json; charset=utf-8
}}
The record is created succesfully, however on the CreatedBy field is the service username NOT the MSCRMCallerID username (d994d6ff-5531-e711-9422-00155dc0d345), and the CreatedOnBehalf field is empty.
What are we doing wrong?
How do we get this impersonation working from our service?
EDIT + More Info
Please note that I do believe that I've included all the relevant info, but if I have not, please let me know what other input I should provide on this issue.
What have I tried?
changed the order of headers
played with the case of the headers
ensured that the guid is correct of the user for impersonation
ensured that the user has both delegate and sys admin role (although this is irrelevant because this works when executing requesting directly against crm odata endpoint, rather than the endpoint that the our service exposes
have tried to execute the request against both https AND http
fiddler trace as shown below
Please note that this fiddler trace is a trace showing Postman --> Microservice request. It does not show the communication from the localhost microservice to CRM. (I'm not sure why, perhaps because it is encrypted)
POST https://localhost:19081/.....Leads/API/leads HTTP/1.1
Host: localhost:19081
Connection: keep-alive
Content-Length: 84
Cache-Control: no-cache
Origin: chrome-extension://aicmkgpgakddgnaphhhpliifpcfhicfo
MSCRMCallerID: D994D6FF-5531-E711-9422-00155DC0D345
X-Postman-Interceptor-Id: d79b1d2e-2155-f2ec-4ad7-e9b63e7fb90d
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
Content-Type: application/json; charset=UTF-8
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: ai_user=Ka2Xn|2017-05-25T17:30:57.941Z
{
"subject": "created by mscrmcaller user2: d994d6ff-5531-e711-9422-00155dc0d345"
}
#Ram has suggested that we use the organization service to authenticate, is this an option, considering we are executing against Web API? Will the requested token still be valid. (Please note that this may be a silly question, and the reason is because I am not understanding how authentication works).
The following is a code snippet from how we are authenticating currently on every call:
//check headers to see if we got a redirect to the new location
var shouldAuthenticate = redirectUri.AbsoluteUri.Contains("adfs/ls");
if (!shouldAuthenticate)
{
return;
}
var adfsServerName = redirectUri.Authority;
var queryParams = HttpUtility.ParseQueryString(redirectUri.Query);
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
WSTrustChannelFactory factory = null;
try
{
// use a UserName Trust Binding for username authentication
factory = new WSTrustChannelFactory(
new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
$"https://{adfsServerName}/adfs/services/trust/13/usernamemixed")
{
Credentials =
{
UserName =
{
UserName = $"{credential.Domain}\\{credential.UserName}",
Password = credential.Password
}
},
TrustVersion = TrustVersion.WSTrust13
};
var rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
AppliesTo = new EndpointReference(_client.BaseAddress.AbsoluteUri),
TokenType = "urn:oasis:names:tc:SAML:1.0:assertion",
KeyType = KeyTypes.Bearer
};
var channel = factory.CreateChannel();
channel.Issue(rst, out RequestSecurityTokenResponse rstr);
var fedSerializer = new WSFederationSerializer();
var rstrContent = fedSerializer.GetResponseAsString(rstr, new WSTrustSerializationContext());
// construct a authentication form
var crmauthenticaionPostDictionary = new Dictionary<string, string>
{
{"wa", queryParams["wa"]},
{"wresult", rstrContent},
{"wctx", queryParams["wctx"]}
};
// post the authentication form to the website.
var crmAuthorizationPostResponse = _client.PostAsync(_client.BaseAddress.AbsoluteUri, new FormUrlEncodedContent(crmauthenticaionPostDictionary)).Result;
var crmAuthorizationPostResponseString = crmAuthorizationPostResponse.Content.ReadAsStringAsync().Result;
//we should be authenticated here
if (
!(
// we are correctly authorized if we got redirected to the correct address that we
// were trying to reach in the first place.
crmAuthorizationPostResponse.StatusCode == HttpStatusCode.Redirect
&& crmAuthorizationPostResponse.Headers.Location == authenticationTestUri
)
)
{
throw new Exception("ADFS Authentication to CRM failed.");
}
When you are doing Postman to CRM request, its direct call & CRM handles it in expected way.
But in Postman -> Microservice -> CRM, the header get lost between Microservice to CRM.
In your Microservice, you have to handle the Header forward manually to CRM SDK call.
HttpWebRequest myHttpWebRequest1= (HttpWebRequest)WebRequest.Create(uri);
myHttpWebRequest1.Headers.Add("MSCRMCallerID", "D994D6FF-5531-E711-9422-00155DC0D345");
Or HTTP Header Forwarding (Sorry I could not find one for Azure / C#)
Update:
Am assuming you are following this MSDN samples to do your CRM web api call in c# microservice. I have included our header in need - MSCRMCallerID. See if it helps you.
public async Task BasicCreateAndUpdatesAsync()
{
Console.WriteLine("--Section 1 started--");
string queryOptions; //select, expand and filter clauses
//First create a new contact instance, then add additional property values and update
// several properties.
//Local representation of CRM Contact instance
contact1.Add("firstname", "Peter");
contact1.Add("lastname", "Cambel");
HttpRequestMessage createRequest1 =
new HttpRequestMessage(HttpMethod.Post, getVersionedWebAPIPath() + "contacts");
createRequest1.Content = new StringContent(contact1.ToString(),
Encoding.UTF8, "application/json");
createRequest1.Headers.Add("MSCRMCallerID", "D994D6FF-5531-E711-9422-00155DC0D345");
HttpResponseMessage createResponse1 =
await httpClient.SendAsync(createRequest1);
if (createResponse1.StatusCode == HttpStatusCode.NoContent) //204
{
Console.WriteLine("Contact '{0} {1}' created.",
contact1.GetValue("firstname"), contact1.GetValue("lastname"));
contact1Uri = createResponse1.Headers.
GetValues("OData-EntityId").FirstOrDefault();
entityUris.Add(contact1Uri);
Console.WriteLine("Contact URI: {0}", contact1Uri);
}
else
{
Console.WriteLine("Failed to create contact for reason: {0}",
createResponse1.ReasonPhrase);
throw new CrmHttpResponseException(createResponse1.Content);
}
}
There are fews things that you have to take care while impersonating
1. To impersonate a user, set the CallerId property on an instance of
OrganizationServiceProxy before calling the service’s Web methods.
2. The user (impersonator) must have the ActOnBehalfOf privilege or be a member of the PrivUserGroup group in Active Directory
Code Example
SystemUser user = null;
user = new SystemUser(systemUser);
OrganizationServiceProxy service = CrmService.Proxy;
service.CallerID = user.Id;
Since your code is not available please ensure all the above fields are set properly
For detailed understanding use the link
https://crmbusiness.wordpress.com/2015/07/21/crm-2015-understanding-impersonation-in-plugins-and-knowing-when-to-use-it/

SignalR not working since migrating to server

I built a webservice that processes notification requests and a website that receives the push notifications using SignalR. This all worked fine when running both the webservice and Website on my box using Visual Studio and whatever webserver VS uses to run projects.
However since moving to a test server which runs IIS 7, the signalR no longer works. Both the webservice and website are on the same server, website on port 8088 and webservice on port 8089.
This is the error I get
10-12-2015 14:56:26,864 [UK\!kerslaj1][35] ERROR Centrica.CE.SEFlex.Common.Logging.ConsoleLogger - There was an error opening the connection 'http://localhost:8088/'
Microsoft.AspNet.SignalR.Client.HttpClientException: StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Connection: close
Date: Thu, 10 Dec 2015 14:56:26 GMT
Server: Microsoft-HTTPAPI/2.0
Content-Length: 334
Content-Type: text/html; charset=us-ascii
}
at Microsoft.AspNet.SignalR.Client.Http.DefaultHttpClient.<>c__DisplayClass2.<Get>b__1(HttpResponseMessage responseMessage)
at Microsoft.AspNet.SignalR.TaskAsyncHelper.TaskRunners`2.<>c__DisplayClass42.<RunTask>b__41(Task`1 t)
10-12-2015 14:56:26,866 [UK\!kerslaj1][41] DEBUG Centrica.CE.SEFlex.Common.Logging.ConsoleLogger - Connection started
10-12-2015 14:56:26,866 [UK\!kerslaj1][41] DEBUG Centrica.CE.SEFlex.Common.Logging.ConsoleLogger - User: kerslaj1
10-12-2015 14:56:26,866 [UK\!kerslaj1][41] DEBUG Centrica.CE.SEFlex.Common.Logging.ConsoleLogger - Added username: UK\!kerslaj1
10-12-2015 14:56:26,867 [UK\!kerslaj1][41] ERROR Centrica.CE.SEFlex.Common.Logging.ConsoleLogger - There was an error notifying using the connection http://localhost:8088/
System.InvalidOperationException: Data cannot be sent because the connection is in the disconnected state. Call start before sending any data.
at Microsoft.AspNet.SignalR.Client.Connection.Send(String data)
at Microsoft.AspNet.SignalR.Client.Hubs.HubProxy.Invoke[TResult,TProgress](String method, Action`1 onProgress, Object[] args)
at Microsoft.AspNet.SignalR.Client.Hubs.HubProxy.Invoke[T](String method, Object[] args)
at Centrica.CE.SEFlex.Common.Notification.SignalRHandler.Notify(EventNotification notification, IEnumerable`1 subscribers, String hubConnection) in c:\Development\TFS\Atlas\SE\DEV\SEFLEX\Build\Common\Centrica.CE.SEFlex.Common\Notification\SignalRHandler.cs:line 66
10-12-2015 14:56:26,868 [UK\!kerslaj1][41] DEBUG SEFlex - Subscriber notified
On my website the SignalR is configured as so
public class OwinStartup
{
public void Configuration(IAppBuilder app)
{
var container = new UnityContainer();
container.RegisterType<NotificationHub, NotificationHub>(new ContainerControlledLifetimeManager());
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => new UnityHubActivator(container));
var idProvider = new PrincipalUserIdProvider();
GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => idProvider);
// Any connection or hub wire up and configuration should go here
app.MapSignalR();
}
}
And my layout html page
#Scripts.Render("~/bundles/signalr")
<script src="/signalr/hubs"></script>
<script>
var notifyProxy = $.connection.notification, // the generated client-side hub proxy
$notificationTable = $('#NotificationTable'),
$notificationTableBody = $notificationTable.find('tbody'),
rowTemplate = '<tr data-symbol="{EventNotificationId}"><td style="text-align:left;width:115px;vertical-align:text-top;"><nobr>{EventDate} : </nobr></td><td><span class="{Class}"><small class="text-uppercase">{ClassLabel}</small></span></td><td style="text-align:left;">{Description}</td></tr>';
function formatNotification(notification) {
return $.extend(notification, {
EventDate: notification.EventTime.substr(0, 10).concat(' ').concat(notification.EventTime.substr(11, 8)),
Description: notification.FriendlyText,
Class: notification.Class
});
}
function init() {
notifyProxy.server.getCurrentNotifications().done(function (notifications) {
$notificationTableBody.empty();
$.each(notifications, function () {
var notification = formatNotification(this);
$notificationTableBody.prepend(rowTemplate.supplant(notification));
});
});
}
// Add a client-side hub method that the server will call
notifyProxy.client.addNotification = function (notification) {
$notificationTableBody.prepend(rowTemplate.supplant(formatNotification(notification)));
};
// Start the connection
$.connection.hub.start().done(init);
</script>
This is a bit of a stab in the dark, but could it be that it expects SignalR to be listening by default on port 80, and you're running your site on port 8088. Or that SignalR is still listening on port 80 and your site is on 8088?
Maybe setting the connection URL might do the trick?
$.connection.hub.url = "http://[HOST URL HERE]:8080/signalr";

Google Groups Migration C# API Not Working

I'm trying to use the C# Google Groups Migration API and not having much luck.
I have the following code:
public static void Main(string[] args)
{
var body =
#"Received: by 10.143.160.15 with HTTP; Mon, 16 Jul 2007 10:12:26 -0700 (PDT)
Message-ID: NNNN#mail.samplegroup.com
Date: Mon, 16 Jul 2007 10:12:26 -0700
From: ""xxx""
To: ""xxx""
Subject: SUBJECT
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Delivered-To: xxx
This is the body of the migrated email message.";
var bytes = ASCIIEncoding.ASCII.GetBytes(body);
var messageStream = new MemoryStream(bytes);
var auth = new OAuth2LeggedAuthenticator("xxx.com", "xxx", "xxx", "xxx");
var service = new GroupsmigrationService(auth);
service.Key = "xxx";
var request = service.Archive.Insert("xxx", messageStream, "message/rfc822");
request.Upload();
}
...but this results in an Invalid Credentials exception.
I also tried the following:
public static class Program
{
public static void Main(string[] args)
{
var body =
#"Received: by 10.143.160.15 with HTTP; Mon, 16 Jul 2007 10:12:26 -0700 (PDT)
Message-ID: NNNN#mail.samplegroup.com
Date: Mon, 16 Jul 2007 10:12:26 -0700
From: ""xxx""
To: ""xxx""
Subject: SUBJECT
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Delivered-To: xxx
This is the body of the migrated email message.";
var bytes = ASCIIEncoding.ASCII.GetBytes(body);
var messageStream = new MemoryStream(bytes);
// Register the authenticator.
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
provider.ClientIdentifier = "xxx";
provider.ClientSecret = "xxx";
var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
// Create the service.
var service = new GroupsmigrationService(auth);
service.Key = "xxx";
var request = service.Archive.Insert("xxx", messageStream, "message/rfc822");
request.Upload();
Console.ReadKey();
}
private static IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
// Get the auth URL:
// IAuthorizationState state = new AuthorizationState(new[] { TasksService.Scopes.Tasks.GetStringValue() });
IAuthorizationState state = new AuthorizationState(new[] { "https://www.googleapis.com/auth/apps.groups.migration" });
state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
Uri authUri = arg.RequestUserAuthorization(state);
// Request authorization from the user (by opening a browser window):
Process.Start(authUri.ToString());
Console.Write(" Authorization Code: ");
string authCode = Console.ReadLine();
Console.WriteLine();
// Retrieve the access token by using the authorization code:
return arg.ProcessUserAuthorization(authCode, state);
}
}
...but that fails with: Backend Error. The inner exception is:
The remote server returned an error: (503) Server Unavailable.
Ideally I'd prefer the to use the 2 Legged Authenticator approach as it doesn't require manual intervention in copying and pasting an auth-key, but right now getting anything to work would be a plus.
Any help gratefully appreciated!
503 error usually indicated that you are hitting the API quota
https://developers.google.com/google-apps/groups-migration/v1/limits
Would you wait a 24 hours period and try to re-run again? The quota resets itself on a daily basics.
Additionally, you should tag your migration related question with google-email-migration and for group migration with google-groups-migration
I had same problem, and asked to google's support team.
In result, we found that this problem reproduce because "Message-ID" header in example has invalid format.
This typo has been fixed at August 12, 2013.
Please try to change Message-ID from NNNN#mail.samplegroup.com to <NNNN#mail.samplegroup.com>.

.NET Google GData Docs API with OAuth 2.0 returning 401

I'm currently writing a .NET WPF application that uses the Google Docs and Calendar APIs. I'm planning to integrate some of the newer APIs, like Tasks, at a later stage so I want to start using OAuth 2.0 now in preparation. I've been able to obtain and store both a refresh and access token and I've implemented some logic to retrieve further access tokens when the current ones expire. However I'm having a lot of trouble uploading a document to google docs. It seems that the GData client libraries don't natively support OAuth 2.0 and I don't want to move to the newer client libraries (e.g. for Tasks) because I don't want a dependency on DotNetOpenAuth at this stage. Instead I've implemented my own OAuth2Authenticator which adds the required OAuth 2 header and I'm using this with the GData ResumableUploader. When I try to send the request to upload a document with the ResumableUploader I get a 401 Unauthorised response with the message Token Invalid - Invalid AuthSub token.
I'm making the call like this:
ResumableUploader ru = new ResumableUploader(512);
Document entry = new Document();
entry.Title = documentName;
entry.MediaSource = new MediaFileSource(localDocumentPath, "application/pdf");
entry.Type = Document.DocumentType.PDF;
Uri createUploadUrl = new Uri("https://docs.google.com/feeds/upload/create-session/default/private/full");
AtomLink link = new AtomLink(createUploadUrl.AbsoluteUri);
link.Rel = ResumableUploader.CreateMediaRelation;
entry.DocumentEntry.Links.Add(link);
ru.Insert(new OAuth2Authenticator("MyApplicationName", "MyAccessToken"), entry.DocumentEntry);
Which results in this request (from Fiddler):
POST https://docs.google.com/feeds/upload/create-session/default/private/full
HTTP/1.1 Authorization: OAuth sOmeTThing+SomThNig+etc==
Slug: DOC_0108.pdf
X-Upload-Content-Type: application/pdf
X-Upload-Content-Length: 175268
GData-Version: 3.0
Host: docs.google.com
Content-Type: application/atom+xml; charset=UTF-8
Content-Length: 508 Connection: Keep-Alive
<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:gd="http://schemas.google.com/g/2005"
xmlns:docs="http://schemas.google.com/docs/2007">
<title type="text">DOC_0108.pdf</title>
<link href="https://docs.google.com/feeds/upload/create-session/default/private/full"
rel="http://schemas.google.com/g/2005#resumable-create-media" />
<category term="http://schemas.google.com/docs/2007#pdf"
scheme="http://schemas.google.com/g/2005#kind" label="pdf" />
</entry>
And associated 401 response:
HTTP/1.1 401 Unauthorized
Server: HTTP Upload Server Built on Sep 27 2011 04:44:57 (1317123897)
WWW-Authenticate: AuthSub realm="http://www.google.com/accounts/AuthSubRequest"
Content-Type: text/html; charset=UTF-8
Content-Length: 38
Date: Thu, 13 Oct 2011 08:45:11 GMT
Pragma: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate
Token invalid - Invalid AuthSub token.
I've tried both 'Authorization: OAuth' and 'Authorization: Bearer' in the headers, as the API and OAuth 2.0 documentation seems divided, and I've also tried appending the token as a query string (?access_token= and ?oauth_token=) but all of those things give the same response.
I've been through all the Google API and OAuth questions, blog posts, documentation I can find and tried numerous ways of performing this call (multiple implementations with the .NET GData APIs, a REST client NuGet package, my own REST client implementation, etc.) and I can't get past this issue.
Any help will be most appreciated.
I am able to get and create documents with OAuth. Once I've authenticated with Google to have access to the docs scope, I do the following:
// get the list of available google docs
RequestSettings settings = new RequestSettings(kApplicationName);
settings.AutoPaging = false;
if (settings != null)
{
DocumentsRequest request = new DocumentsRequest(settings);
request.Service.RequestFactory = GetGoogleOAuthFactory();
Feed<Document> feed = request.GetEverything();
List<Document> all = new List<Document>(feed.Entries);
// loop through the documents and add them from google
foreach (Document entry in all)
{
// first check to see whether the document has already been selected or not
bool found = model.Docs.Any(d => d.GoogleDocID == entry.ResourceId);
if (!found)
{
GoogleDocItem doc = new GoogleDocItem();
doc.GoogleDocID = entry.ResourceId;
doc.ETag = entry.ETag;
doc.Url = entry.DocumentEntry.AlternateUri.Content;
doc.Title = entry.Title;
doc.DocType = entry.Type.ToString();
doc.DocTypeID = entry.Type;
if (entry.ParentFolders.Count == 0)
{
// add the doc to the list
model.AvailableDocs.Add(doc);
// if the doc is a folder, get the children
if (doc.DocTypeID == Document.DocumentType.Folder)
{
AddAllChildrenToFolder(ref doc, entry, all);
}
}
}
}
}
public GOAuthRequestFactory GetGoogleOAuthFactory()
{
// build the base parameters
OAuthParameters parameters = new OAuthParameters
{
ConsumerKey = kConsumerKey,
ConsumerSecret = kConsumerSecret
};
// check to see if we have saved tokens and set
var tokens = (from a in context.GO_GoogleAuthorizeTokens select a);
if (tokens.Count() > 0)
{
GO_GoogleAuthorizeToken token = tokens.First();
parameters.Token = token.Token;
parameters.TokenSecret = token.TokenSecret;
}
// now build the factory
return new GOAuthRequestFactory("anyname", kApplicationName, parameters);
}
I posted my authorization sample over here: .net - Google / OAuth 2 - Automatic logon. The DocumentsRequest is from the .NET binaries from Google. While I haven't created a new document with this yet, I do use similar classes to create Calendar items.

Categories