:定位/摘要: 我有一个使用Google DialogFlow开发的动作应用程序,我希望用户能够使用该应用程序(来自Google智能助理)创建Google日历活动。换句话说,验证用户是否允许我的应用程序使用他的日历创建活动。
做了什么:
在我的DialogFlow Webhook方法的第一行写日志以记录以下响应:
{
"originalRequest":{
"source":"google",
"version":"2",
"data":{
"isInSandbox":true,
"surface":{
"capabilities":[
{
"name":"actions.capability.AUDIO_OUTPUT"
},
{
"name":"actions.capability.WEB_BROWSER"
},
{
"name":"actions.capability.MEDIA_RESPONSE_AUDIO"
},
{
"name":"actions.capability.SCREEN_OUTPUT"
}
]
},
"inputs":[
{
"rawInputs":[
{
"query":"test",
"inputType":"KEYBOARD"
}
],
"arguments":[
{
"rawText":"test",
"textValue":"test",
"name":"text"
}
],
"intent":"actions.intent.TEXT"
}
],
"user":{
"lastSeen":"2018-05-03T11:40:57Z",
"accessToken":"4CfRs-Lt5lWVQuyOYODvf1xxxxxxx",
"locale":"en-US",
"userId":"15229245xxxxx"
},
"conversation":{
"conversationId":"15253476xxxxx",
"type":"ACTIVE",
"conversationToken":"[\"authentication\",\"wh_patient-details\"]"
},
"availableSurfaces":[
{
"capabilities":[
{
"name":"actions.capability.AUDIO_OUTPUT"
},
{
"name":"actions.capability.SCREEN_OUTPUT"
}
]
}
]
}
},
"id":"1d6ed865-0803-49ca-bbac-xxxx",
"timestamp":"2018-05-03T11:42:22.835Z",
"lang":"en-us",
"result":{
"source":"agent",
"resolvedQuery":"test",
"speech":"",
"action":"v00.xxxxx",
"actionIncomplete":false,
"parameters":{
"CallEnum":"Test"
},
"contexts":[
{
"name":"authentication",
"parameters":{
"CallEnum":"Test",
"CallEnum.original":""
},
"lifespan":1
},
{
"name":"actions_capability_screen_output",
"parameters":{
"CallEnum":"Test",
"CallEnum.original":""
},
"lifespan":0
},
{
"name":"actions_capability_audio_output",
"parameters":{
"CallEnum":"Test",
"CallEnum.original":""
},
"lifespan":0
},
{
"name":"wh_patient-details",
"parameters":{
"patientId":0,
"CallEnum":"Test",
"fallbackLifespan":0,
"providerId":0,
"practiceId":0,
"CallEnum.original":"",
"fullDob":"01 January, 0001"
},
"lifespan":199
},
{
"name":"google_assistant_input_type_keyboard",
"parameters":{
"CallEnum":"Test",
"CallEnum.original":""
},
"lifespan":0
},
{
"name":"actions_capability_web_browser",
"parameters":{
"CallEnum":"Test",
"CallEnum.original":""
},
"lifespan":0
},
{
"name":"actions_capability_media_response_audio",
"parameters":{
"CallEnum":"Test",
"CallEnum.original":""
},
"lifespan":0
}
],
"metadata":{
"intentName":"v00xxxx",
"isResponseToSlotfilling":false,
"intentId":"c7bd9113-d5b4-4312-8851-xxxxxxx",
"webhookUsed":"true",
"webhookForSlotFillingUsed":"false",
"nluResponseTime":556
},
"fulfillment":{
"speech":"Test",
"messages":[
{
"type":0,
"speech":"Test"
}
]
},
"score":0.8399999737739563
},
"status":{
"code":200,
"errorType":"success"
},
"sessionId":"152534xxxxxxx",
"isStackdriverLoggingEnabled":false
}
相关部分是:
"user":{
"lastSeen":"2018-05-03T11:40:57Z",
"accessToken":"4CfRs-Lt5lWVQuyOYODvf1xxxxxxx",
"locale":"en-US",
"userId":"15229245xxxxx"
}
身份验证令牌(您已发出,因为您是OAuth 服务器)将在JSON对象中发送 originalRequest.data.user.accessToken。
所以我在下面的代码中使用了上面的授权令牌:
string clientId = "361385932727-ksg6jgjxxxxxSNIP";
string clientSecret = "rc2K1UUyntxxxxxxSNIP";
string accessToken = jsonObject.SelectToken("originalRequest.data.user.accessToken");
string userId = jsonObject.SelectToken("originalRequest.data.user.userId");
IAuthorizationCodeFlow flow =
new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = clientId,
ClientSecret = clientSecret
},
Scopes = new[] { CalendarService.Scope.Calendar }
});
TokenResponse token = flow.ExchangeCodeForTokenAsync(userId, accessToken,
"https://oauth-redirect.googleusercontent.com/r/xxxxxxxxx", CancellationToken.None).Result;
UserCredential credential = new UserCredential(flow, userId, new TokenResponse { AccessToken = token.AccessToken });
CalendarService service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Test Auth0",
});
var list = service.CalendarList.List().Execute().Items;
例外:
Error:"invalid_grant", Description:"Malformed auth code.", Uri:""
Stacktrace: at Google.Apis.Auth.OAuth2.Requests.TokenRequestExtenstions.<ExecuteAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Google.Apis.Auth.OAuth2.Flows.AuthorizationCodeFlow.<FetchTokenAsync>d__35.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Google.Apis.Auth.OAuth2.Flows.AuthorizationCodeFlow.<FetchTokenAsync>d__35.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Google.Apis.Auth.OAuth2.Flows.AuthorizationCodeFlow.<ExchangeCodeForTokenAsync>d__30.MoveNext()
当我将上面代码中的ClientId / ClientSecret更改为auth0.com中的那个时,例外是:
Error:"invalid_client", Description:"The OAuth client was not found.", Uri:""
Stacktrace: at Google.Apis.Auth.OAuth2.Requests.TokenRequestExtenstions.<ExecuteAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Google.Apis.Auth.OAuth2.Flows.AuthorizationCodeFlow.<FetchTokenAsync>d__35.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Google.Apis.Auth.OAuth2.Flows.AuthorizationCodeFlow.<FetchTokenAsync>d__35.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Google.Apis.Auth.OAuth2.Flows.AuthorizationCodeFlow.<ExchangeCodeForTokenAsync>d__30.MoveNext()
我在这里缺少什么?有人可以帮忙。
答案 0 :(得分:3)
以下是&#34;缺失&#34;之后,我让这件事工作了。我确信必须有其他方法可以做到这一点,但我会满足于此,直到我得到一些反馈。
注意:Google Actions控制台用户界面已更改,因此原始问题中的屏幕可能不同(但已完成)。
返回https://manage.auth0.com&gt;蜜蜂。编辑列出的System API&gt;机器到机器应用。授权您列出的应用程序并选择/勾选以下两个范围:
读:用户
读:user_idp_tokens
originalRequest.data.user.accessToken
中的授权令牌调用https://[domain].auth0.com/userinfo(请参阅第7和第8点)。成功的回复应该给你userId
access_token
C。将授权令牌从点11.b更改为新获取的access_token,并调用https://[domain].auth0.com/api/v2/users/[userId],其中userId是您从点11.a开始的那个。成功的回复应该会给你一个&#34; Google&#34; access_token和userId(在身份下)
d。使用点11.c中的一个更改标题中的授权令牌。这是您用来调用Google API的令牌。例如,对于日历,请致电https://www.googleapis.com/calendar/v3/users/me/calendarList。您将获得所需的响应。 这是代码(我已经重用了变量):
string responseText = string.Empty;
string clientId = "DCuPWHknmv_k2xxxxxxxxxxxxxxxxx"; //Auth0 ClientId
string clientSecret = "7G3xlreFIULPZ9OtwlOxCX99xxxxxxxxxxxxxxxxxxx"; //Auth0 ClientSecret
string accessToken = jsonObject.SelectToken("originalRequest.data.user.accessToken").ToString();
try
{
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
var url = "https://xxx.auth0.com/userinfo";
responseText = httpClient.GetStringAsync(url).Result;
JObject jsonUserInfo = JObject.Parse(responseText);
string userId = jsonUserInfo.SelectToken("sub").ToString();
url = "https://xxx.auth0.com/oauth/token";
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("client_id", clientId),
new KeyValuePair<string, string>("client_secret", clientSecret),
new KeyValuePair<string, string>("audience", "https://[domain].auth0.com/api/v2/"),
new KeyValuePair<string, string>("grant_type", "client_credentials")
});
var postResult = httpClient.PostAsync(url, content).Result;
jsonUserInfo = JObject.Parse(postResult.Content.ReadAsStringAsync().Result);
accessToken = jsonUserInfo.SelectToken("access_token").ToString();
httpClient.DefaultRequestHeaders.Remove("Authorization");
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
url = "https://xxx.auth0.com/api/v2/users/" + userId;
jsonUserInfo = JObject.Parse(httpClient.GetStringAsync(url).Result);
accessToken = jsonUserInfo.SelectToken("identities[0].access_token").ToString();
userId = jsonUserInfo.SelectToken("identities[0].user_id").ToString();
httpClient.DefaultRequestHeaders.Remove("Authorization");
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
url = "https://www.googleapis.com/calendar/v3/users/me/calendarList";
responseText = httpClient.GetStringAsync(url).Result;
}
}