I've been using Microsoft Translator service from my C# applications for a while. However, since I created my Azure subscription, the function below keeps returning: "Could not translate". As I understand, now I need to use Microsoft Translator somehow differently. I searched the Web actively but could not find any working examples or/and similar questions. Below I provide my code that used to work but now it does not:
public static String TranslateToEnglish(String str)
{
return Translate(GetTokenWrapper(), str, "en");
}
public static String GetTokenWrapper()
{
AdmAccessToken admToken;
AdmAuthentication admAuth = new AdmAuthentication("..", "..");
admToken = admAuth.GetAccessToken();
return "Bearer " + admToken.access_token;
}
public static String Translate(HttpRequestMessageProperty httpRequestProperty,string authToken, string what, string to)
{
// Add TranslatorService as a service reference, Address:http://api.microsofttranslator.com/V2/Soap.svc
LanguageServiceClient client = new LanguageServiceClient();
HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Method = "POST";
httpRequestProperty.Headers.Add("Authorization", authToken);
using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
{
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
string sourceText = what;
string translationResult;
try
{
translationResult = client.Translate("", sourceText, "", to, "text/plain", "general", "");
}
catch(Exception ex) { return ex.ToString(); }
return translationResult;
}
You use Microsoft translator in exactly the same way on Azure as you did before the move. The only difference is you need to use the Azure key and get a token from the new end point for tokens.
This shows you how to get an azure token:
https://github.com/MicrosoftTranslator/GetAzureToken
Related
I'm creating a C# application that uses DialogFlow's detectIntent. I need help passing the Google Cloud credentials explicitly.
It works with the GOOGLE_APPLICATION_CREDENTIALS environment variable. However I want to pass the credentials explicitly. I need a C# version of the solution provided here.
I'm using the following quick-start provided with the documentation:
public static void DetectIntentFromTexts(string projectId,
string sessionId,
string[] texts,
string languageCode = "en-US")
{
var client = df.SessionsClient.Create();
foreach (var text in texts)
{
var response = client.DetectIntent(
session: new df.SessionName(projectId, sessionId),
queryInput: new df.QueryInput()
{
Text = new df.TextInput()
{
Text = text,
LanguageCode = languageCode
}
}
);
var queryResult = response.QueryResult;
Console.WriteLine($"Query text: {queryResult.QueryText}");
if (queryResult.Intent != null)
{
Console.WriteLine($"Intent detected: {queryResult.Intent.DisplayName}");
}
Console.WriteLine($"Intent confidence: {queryResult.IntentDetectionConfidence}");
Console.WriteLine($"Fulfillment text: {queryResult.FulfillmentText}");
Console.WriteLine();
}
}
Currently you need to create a gRPC channel directly, and pass that into the client:
GoogleCredential credential = GoogleCredential.FromFile("...");
ChannelCredentials channelCredentials = credential.ToChannelCredentials();
Channel channel = new Channel(SessionsClient.DefaultEndpoint, channelCredentials);
var client = df.SessionsClient.Create(channel);
Very soon, this will be a lot easier via a builder pattern:
var client = new SessionsClientBuilder
{
CredentialsPath = "path to file",
}.Build();
... or various other ways of specify the credential. I'm hoping that'll be out in the next couple of weeks.
I have a web API2 application which is consumed by a third party application. When the application hits my end-point, my application send oAuth credentials for authentication and gets the results from the third party application.
Recently some of the transactions are failing and when i added some logs, i saw that the error: The remote server returned an error: (410) Gone is occurring for all failed transactions. Unfortunately I am unable to reproduce this issue when I am calling my application. The following is the code that I am using. What could be the issue that is causing this error?
public async Task<customerModel> SendSigned(string url)
{
customerModel customermodel = null;
try
{
OAuthBase oauthBase = new OAuthBase();
string oAuthKey = ConfigurationManager.AppSettings["oAuthKey"];
string oAuthSecret = ConfigurationManager.AppSettings["oAuthSecret"];
string timestamp = oauthBase.GenerateTimeStamp();
string nonce = oauthBase.GenerateNonce();
string normalizedUrl;
string normalizedRequestParameters;
string sig = HttpUtility.UrlEncode(oauthBase.GenerateSignature(
new Uri(url), oAuthKey, oAuthSecret, string.Empty, string.Empty,
"GET", timestamp, nonce, out normalizedUrl, out normalizedRequestParameters));
string requestUrl = String.Format("{0}?{1}&oauth_signature={2}", normalizedUrl, normalizedRequestParameters, sig);
HttpWebRequest request = null;
request = (HttpWebRequest)HttpWebRequest.Create(requestUrl);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
myXMLDocument = new XmlDocument();
customermodel = GetCustomerInformation(response);
}
return await Task.Run(() => customermodel);
}
catch (Exception ex)
{
_logger.Error("Error in SendSigned method", ex.InnerException);
return customermodel;
}
}
The explanation of 410 is The target resource is no longer available at the origin server and that this condition is likely to be permanent based on
this link (similar to a 404)
I would suggest you to think about recent changes you made to your
API signatures
Folder restructure/reorganization of assets/resources
Routing changes
Rename of resources
I am using HybridConnectionNamespace and create multiple HybridConnections via Azure portal. The question is quite simple. How can I create it programmatically (Azure SDK, PowerShell scripts, etc.)?
According to this article, there are currently two different ways to create a relay namespace.
Azure portal and Azure Resource Manager templates
If you want to create it programmatically, I suggest you could use azure rest api to send the deployment templates by codes.
More details, you could refer to this article and codes:
Notice: If you want to use rest api to send request to azure, you need firstly create an Azure Active Directory application and service principal. After you generate the service principal, you could get the applicationid,access key and talentid. More details, you could refer to this article.
Rest Body(json.txt):
Notice: You need change the parameters' name and location value.
{"properties":{"mode":"incremental","debugSetting":{"detailLevel":"RequestContent, ResponseContent"},"parameters":{"name":{"value":"yourrelayname"},"location":{"value":"location"}},"template":{"$schema":"http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#","contentVersion":"1.0.0.0","parameters":{"name":{"type":"string"},"location":{"type":"string"}},"resources":[{"apiVersion":"2016-07-01","name":"[parameters('name')]","location":"[parameters('location')]","type":"Microsoft.Relay/namespaces","properties":{"namespaceType":"Relay"}}]}}}
Code:
string body = File.ReadAllText(#"D:\json.txt");
// Display the file contents to the console. Variable text is a string.
string tenantId = "tenantId";
string clientId = "clientId(applicationid)";
string clientSecret = "applicationSecret";
string subscription = "subscriptionId";
string resourcegroup = "Youresourcegroup";
string authContextURL = "https://login.windows.net/" + tenantId;
var authenticationContext = new AuthenticationContext(authContextURL);
var credential = new ClientCredential(clientId, clientSecret);
var result = authenticationContext.AcquireTokenAsync(resource: "https://management.azure.com/", clientCredential: credential).Result;
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Resources/deployments/Microsoft.Relay?api-version=2016-07-01", subscription, resourcegroup));
request.Method = "PUT";
request.Headers["Authorization"] = "Bearer " + token;
request.ContentType = "application/json";
try
{
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(body);
streamWriter.Flush();
streamWriter.Close();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
//Get the response
var httpResponse = (HttpWebResponse)request.GetResponse();
Console.WriteLine(httpResponse.StatusCode);
Console.ReadLine();
Result:
Use PowerShell CmdLets | Hybrid Connection Manager:
Add-HybridConnection
Update-HybridConnection
Remove-HybridConnection
Get-HybridConnection
Set-HybridConnectionManagerConfiguration
https://msdn.microsoft.com/en-us/library/azure/dn789178.aspx
GoodLuck
Update2
This post is getting old but still relevant.. Below is whe way I solved it. I marked the other guys answer because I think it answers the question better. I'm calling a similar method(I'am about to refactor:)) in accountcontroller. The string should be a list... I think you get it.
/// <summary>
/// Use this method when an action fails due to lack of priviligies. It will redirect user to facebook with provided permission request.
/// Refactor to handle list of request.
/// </summary>
/// <param name="permission"></param>
private static void AddAdditionalPermissions(string permission)
{
System.Diagnostics.Trace.TraceInformation(permission + " not authorized for user.");
string facebook_urlAuthorize_base = "https://graph.facebook.com/oauth/authorize";
string scope = permission; //see: https://developers.facebook.com/docs/authentication/permissions/ for extended permissions
string urlAuthorize = facebook_urlAuthorize_base;
urlAuthorize += "?client_id=" + AppId;
urlAuthorize += "&redirect_uri=" + "https://fbd.anteckna.nu/";
urlAuthorize += "&scope=" + scope;
//redirect the users browser to Facebook to ask the user to authorize our Facebook application
HttpContext.Current.Response.Redirect(urlAuthorize, true); //this cannot be done using WebRequest since facebook may need to show dialogs in the users browser
}
Then every method making a call to facebook like /me/home with facebok C# SDK catches FacebookOAuthException and redirects to the folling method. This is how we apply the best practise of not asking permissions from users up front but when needed. This method should have aredirect url that matches as well but we've just get going :)
Hope it helps!
/// <summary>
/// Check for what permissions to request or different ways to handle FacebookOAuthExceptions.
/// </summary>
/// <param name="foae">The exception object</param>
public static void HandleAuthorizationsExceptions(FacebookOAuthException foae)
{
if (foae.Message.Contains("publish_permissions"))
{
AddAdditionalPermissions("publish_permissions");
}
else if (foae.Message.Contains("read_stream"))
{
AddAdditionalPermissions("read_stream");
}
else
{
System.Diagnostics.Trace.TraceError("Unhandled error at:" + foae.StackTrace);
}
}
Update: This behaviour is caused by .Net oauth implementation which has the scope hard coded in a sealed class. Added figure 4 to show the request parameter where the lack of additional scopes besides "email"(which is sent with all requests by .net oauth provider). Adding ",publish_stream" to the query string gives me the wanted behaviour. Anyone knows how to achieve this?
Please do not submit answers or comments about facebook best practices or alternative solutions. I have an alternative solution but would like this to work with default registerfacebookclient parameters. I have updated the application to oly use publish_stream according to the two answers specifying on what permissions I'm asking for.
figure 4
Original question:
I'm setting up an application (C#.Net4.5 MVC4, razor views) which need pretty much all available user permissions from facebook.
You can see code examples below how I have set it all up.
The problem is that when clicking "okay" in figure 1, Facebook sends me back to my application. As I understand there should be an additional screen(figure2) asking for the "heavier" permissions. As of now I only get the permissions stated in figure one. That part works...
Figure 1
Figure 2
So, using basic
AuthConfig.cs
var facebooksocialData = new Dictionary<string, object>();
facebooksocialData.Add("scope", "email,publish_stream,read_stream,publish_actions,manage_pages,create_event,offline_access");
OAuthWebSecurity.RegisterFacebookClient(
appId: "165359673639901",
appSecret: "15091cb2094a1996ae6c7b324f0300e6",
displayName: "Facebook",
extraData: facebooksocialData);
This is how I handle the response but here facebook has not prompted the user for the extended permissions but only for email,
AccountController.cs
//
// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public ActionResult ExternalLoginCallback(string returnUrl)
{
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
if (!result.IsSuccessful)
{
return RedirectToAction("ExternalLoginFailure");
}
// Save the accesstoken into session
Session["accesstoken"] = result.ExtraData["accesstoken"];
Session["id"] = result.ExtraData["id"];
if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))
{
return RedirectToLocal(returnUrl);
}
if (User.Identity.IsAuthenticated)
{
// If the current user is logged in add the new account
OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name);
return RedirectToLocal(returnUrl);
}
else
{
// User is new, ask for their desired membership name
string loginData = OAuthWebSecurity.SerializeProviderUserId(result.Provider, result.ProviderUserId);
ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
ViewBag.ReturnUrl = returnUrl;
return View("ExternalLoginConfirmation", new RegisterExternalLoginModel { UserName = result.UserName, ExternalLoginData = loginData });
}
}
The closest to an answer I could find was a wp plugin which had the same issue. Their problem was solved by setting domain to localhost. This is how my application is set up.
I got the same problem. As you did, I configured the RegisterFacebookClient with dictionary to define my app's scope, and unfortunately the request didn't include the scope as I configured. So I found that. It seems that would work, but it wasn't enough. So I found this.
So here is what solve my problems:
First of all I added this new client to my code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using DotNetOpenAuth.AspNet;
using Newtonsoft.Json;
namespace MyApp.UI.Infrastructure
{
public class FacebookScopedClient : IAuthenticationClient
{
private string appId;
private string appSecret;
private string scope;
private const string baseUrl = "https://www.facebook.com/dialog/oauth?client_id=";
public const string graphApiToken = "https://graph.facebook.com/oauth/access_token?";
public const string graphApiMe = "https://graph.facebook.com/me?";
private static string GetHTML(string URL)
{
string connectionString = URL;
try
{
System.Net.HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(connectionString);
myRequest.Credentials = CredentialCache.DefaultCredentials;
//// Get the response
WebResponse webResponse = myRequest.GetResponse();
Stream respStream = webResponse.GetResponseStream();
////
StreamReader ioStream = new StreamReader(respStream);
string pageContent = ioStream.ReadToEnd();
//// Close streams
ioStream.Close();
respStream.Close();
return pageContent;
}
catch (Exception)
{
}
return null;
}
private IDictionary<string, string> GetUserData(string accessCode, string redirectURI)
{
string token = GetHTML(graphApiToken + "client_id=" + appId + "&redirect_uri=" + HttpUtility.UrlEncode(redirectURI) + "&client_secret=" + appSecret + "&code=" + accessCode);
if (token == null || token == "")
{
return null;
}
string access_token = token.Substring(token.IndexOf("access_token="), token.IndexOf("&"));
string data = GetHTML(graphApiMe + "fields=id,name,email,username,gender,link&" + access_token);
// this dictionary must contains
Dictionary<string, string> userData = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
return userData;
}
public FacebookScopedClient(string appId, string appSecret, string scope)
{
this.appId = appId;
this.appSecret = appSecret;
this.scope = scope;
}
public string ProviderName
{
get { return "facebook"; }
}
public void RequestAuthentication(System.Web.HttpContextBase context, Uri returnUrl)
{
string url = baseUrl + appId + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString()) + "&scope=" + scope;
context.Response.Redirect(url);
}
public AuthenticationResult VerifyAuthentication(System.Web.HttpContextBase context)
{
string code = context.Request.QueryString["code"];
string rawUrl = context.Request.Url.OriginalString;
//From this we need to remove code portion
rawUrl = Regex.Replace(rawUrl, "&code=[^&]*", "");
IDictionary<string, string> userData = GetUserData(code, rawUrl);
if (userData == null)
return new AuthenticationResult(false, ProviderName, null, null, null);
string id = userData["id"];
string username = userData["username"];
userData.Remove("id");
userData.Remove("username");
AuthenticationResult result = new AuthenticationResult(true, ProviderName, id, username, userData);
return result;
}
}
}
I put it on a folder "infrastructure" in my asp.net solution with oder stuff, next I change my old configuration, in order to use the new facebook client, as follows:
Old code:
OAuthWebSecurity.RegisterFacebookClient(
appId: "<app-id>",
appSecret: "<app-secret>",
displayName: "Facebook",
extraData: facebookExtraData);
New Code:
OAuthWebSecurity.RegisterClient(
new FacebookScopedClient(
"<app-id>",
"<app-secret>",
"scope"),
"Facebook",
null);
That's it. It may help you, as helped me.
Is your app registered for these scopes? I'm familiar with Google OAuth, they have a separate scope that maps to one permission. Your app should be registered for the scopes, in order to get the 2nd window. Else, you'll have access only to the public info that your 1st popup asks for..
First of all, offline_access does not exist any more, so it from the permissions you are asking for.
"[app] which need pretty much all available user permissions from facebook"
Facebook actively discourages asking for heaps of permissions straight from the beginning "just in case" because they might be needed later. One should only ask for an extended permission when it is actually needed for an action the user just triggered for the first time.
Also, you are supposed to ask for "read" and "write" permissions separately.
I don't know if these aspects are actually triggering your error - but I know that Facebook has already been sending out developer alerts for the read/write thing; although an FB employee confirmed that those alerts can be ignored for now, they might start enforcing this at some point in the future.
I'm starting to tear my hair out with Twitter and trying to signin a user!!! I have Facebook, Google, OpenId all working fine, just Twitter being a PAIN.
I am constantly getting 401 Unauthorized when I try to run my code and for the life of me cannot figure out why.
I have created a twitter client and and I'm using it with the InMemoryTokenManager from the DotNetOpenAuth sample solution. My Twitter client is here
public class TwitterClient
{
private string UserName { get; set; }
private static readonly ServiceProviderDescription ServiceDescription =
new ServiceProviderDescription
{
RequestTokenEndpoint = new MessageReceivingEndpoint(
"https://api.twitter.com/oauth/request_token",
HttpDeliveryMethods.GetRequest |
HttpDeliveryMethods.AuthorizationHeaderRequest),
UserAuthorizationEndpoint = new MessageReceivingEndpoint(
"https://api.twitter.com/oauth/authorize",
HttpDeliveryMethods.GetRequest |
HttpDeliveryMethods.AuthorizationHeaderRequest),
AccessTokenEndpoint = new MessageReceivingEndpoint(
"https://api.twitter.com/oauth/access_token",
HttpDeliveryMethods.GetRequest |
HttpDeliveryMethods.AuthorizationHeaderRequest),
TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
};
IConsumerTokenManager _tokenManager;
public TwitterClient(IConsumerTokenManager tokenManager)
{
_tokenManager = tokenManager;
}
public void StartAuthentication()
{
var request = HttpContext.Current.Request;
using (var twitter = new WebConsumer(ServiceDescription, _tokenManager))
{
var callBackUrl = new Uri(request.Url.Scheme + "://" + request.Url.Authority + "/Members/TwitterCallback");
twitter.Channel.Send(
twitter.PrepareRequestUserAuthorization(callBackUrl, null, null)
);
}
}
public bool FinishAuthentication()
{
using (var twitter = new WebConsumer(ServiceDescription, _tokenManager))
{
var accessTokenResponse = twitter.ProcessUserAuthorization();
if (accessTokenResponse != null)
{
UserName = accessTokenResponse.ExtraData["screen_name"];
return true;
}
}
return false;
}
}
And I have the following in the constructor of my MembersController which is instantiating the InMemoryTokenManager with the correct credentials
_tokenManager = new InMemoryTokenManager(ConfigUtils.GetAppSetting("TwitterAppId"), ConfigUtils.GetAppSetting("TwitterAppSecret"));
And my two Actions are
public ActionResult LogonTwitter()
{
var client = new TwitterClient(_tokenManager);
client.StartAuthentication();
return null;
}
public ActionResult TwitterCallback()
{
var client = new TwitterClient(_tokenManager);
if (client.FinishAuthentication())
{
return new RedirectResult("/");
}
// show error
return View("LogOn");
}
The error appears in the StartAuthentication() in my TwitterClient. As soon as it calls this line
twitter.Channel.Send(
twitter.PrepareRequestUserAuthorization(callBackUrl, null, null)
);
I get the following error
Error occurred while sending a direct message or getting the response.
Inner Exception: The remote server returned an error: (401) Unauthorized.
Anyone got any advice? I have spent most of yesterday and this morning trying to sort this. All the online examples I have tried also seem to get 401 Unauthorized back? Is there a known issue with DotNetOpenAuth and Twitter?
Any help very much appreciated.
I can't remember the exact terminology but have you set up a callback URL in the twitter app (as well as in the code)? I've had similar problems recently, even when developing locally I believe you need to set that value, even if its just a placeholder