Call Azure API from WebJob/ Shared code between WebJob and web api - api

I have a web api in an ASE and an associated web job. I am trying to call this web api from the web job but it always fails with winhttpexception: a security error has occurred. I have put in all the tls related settings but still getting the error.
Any suggestions on the error?
Also is there a way to share code between WebJob and web api?

I was able to resolve the issue by setting the below in my code.This resolved the Security Error.
using(var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (sender,certificate,chain,sslPolicyErrors) => true
})

You could create a console app and publish it as Azure WebJobs. For username and password you could click Get Publish Profile in your Azure webapp overview to get them.
Then you could use the following code in Console App to call your Azure Webapi.
string userName = "$xxxxxx";
string userPassword = "xxxxxxxxxxxxx";
string webAppName = "xxxxxx";
var base64Auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{userName}:{userPassword}"));
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Basic " + base64Auth);
var baseUrl = new Uri($"https://{webAppName}.azurewebsites.net/api/values");
var result = client.GetAsync(baseUrl).Result;
if (result.IsSuccessStatusCode)
{
var readTask = result.Content.ReadAsStringAsync();
readTask.Wait();
var value = readTask.Result;
Console.WriteLine(value.ToString());
}
}
Console.WriteLine("run successfully");
Output as below:

Related

Youtrack and RestSharp Permissions issue

I'm trying to create a youtrack client using RestSharp. I can log in, but when I try to get a project, I receive the following response:
{"value":"You do not have permissions to read project. You are logged in as ****"}
However, when I log into YouTrack on my browser, I can access the project and make changes, etc. Attached is my code (I am using RestSharp):
var client = new RestClient(Site);
var request = new RestRequest(String.Format("rest/user/login?login={0}&password={1}", Username, Password), Method.POST);
//reuse the client
client.CookieContainer = new System.Net.CookieContainer();
IRestResponse response = client.Execute(request);
var content = response.Content;
//returns <login>ok</login> - so it's logging in
Console.WriteLine("LOGIN \n" + content);
String projectId = "PW";
request = new RestRequest(String.Format("rest/admin/project/projectId={0}", projectId), Method.GET);
response = client.Execute(request);
content = response.Content;
Console.WriteLine("Get Project: \n\n" + content);
Is there something in the code I'm missing? Or is this a YouTrack setup issue that I need to take up with my administrator?
For future reference:
I do not have permissions for the /rest/admin resources, but I do have them for /rest/issue. These permissions can be set by the system administrator, if they check the "Groups" in their dashboard.

The request was aborted: Could not create SSL/TLS secure channel. (RestSharp, SSL Client Certificates)

I have following code which is calling an API using basic authentication and SSL client certificate but its throwing exception and giving me following error.
"The request was aborted: Could not create SSL/TLS secure channel."
I tried to find a solution on Google but failed to find any solution. Can anyone help me out on this. Thanks.
// Variables
string basicAuthenticationUserName = "username";
string basicAuthenticationPassword = "password";
string clientCertificateFilePath = "Path-To-Certificate-File";
string clientCertificatePassword = "certificate-password";
string url = "https://" + basicAuthenticationUserName + ":" + basicAuthenticationPassword + "#apiserverurl/apimethod";
// Creating RestSharp Request Object
var request = new RestRequest(Method.POST)
{
RequestFormat = DataFormat.Json,
OnBeforeDeserialization = resp =>
{
resp.ContentType = "application/json";
}
};
// Adding Headers
request.AddHeader("Content-Length", "0");
request.AddHeader("Accept", "application/x-null-message");
// Importing Certificates
var certificates = new X509Certificate();
certificates.Import(clientCertificateFilePath, clientCertificatePassword, X509KeyStorageFlags.PersistKeySet);
// Creating RestSharp Client Object
var client = new RestClient
{
BaseUrl = new Uri(url),
ClientCertificates = new X509CertificateCollection { certificates },
Authenticator = new HttpBasicAuthenticator(managingLou, basicAuthenticationPassword)
};
// Executing Request
var response = client.Execute<T>(request);
I have faced the similar issue. Let me mention the steps here for your help.
After the installation of windows service, I went through the following steps to fix the issue:
Go To Start > Run and type Services.msc
Select your service > Right click and choose Properties
Select the 2nd tab "Log On"
Select the radio button "This account"
Enter the username and password of currently log in user. (Make sure Its the same user who has installed the service)
Apply the changes
Start the service

Office365 authentication without login redirection

I'm trying to load data from Office365 email without need for user interaction. I've created Azure App and I have Client ID and Client secret.
I also have user information (email + password).
I need to call Office365 API to download emails from mailbox. But I need application to download them in background without user interaction (redirecting to MS/Office365 login page) to get authenticated/logged into mailbox.
Is there any way how to do this only through Office API, without need of redirection?
Thanks for any info.
Yes, you are able to create a daemon service app using the Client Credential flow to authenticate the app.
Here is a code sample to retrieve the mails using Microsoft Graph SDK with this flow:
string clientId = "";
string clientsecret = "";
string tenant = "";
string resourceURL = "https://graph.microsoft.com";
string authority = "https://login.microsoftonline.com/" + tenant + "/oauth2/token";
string userMail = "user1#yourdomain.onmicrosoft.com";
var credential = new ClientCredential(clientId, clientsecret);
AuthenticationContext authContext =new AuthenticationContext(authority);
var authResult = await authContext.AcquireTokenAsync(resourceURL, credential);
var graphserviceClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
(requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", authResult.AccessToken);
return Task.FromResult(0);
}));
var items = await graphserviceClient.Users[userMail].Messages.Request().OrderBy("receivedDateTime desc").GetAsync();
foreach (var item in items)
{
Console.WriteLine(item.Subject);
}
And we need to register the app on the Azure AD portal and grant the app Mail.Read scope like figure below:
Refer to here for more detail about calling Microsoft Graph in a service or daemon app

Signing in to an application with ws-federation from front-end application

I have two applications, one web-api application (y.x.com) and a front-end application (z.x.com). To authenticate the user who visits z.x.com I use ws-federation or microsoft live login following the web api template code provided by visual studio 2015. If I talk directly to the web api application (y.x.com) from my browser, postman, fiddler or anything similar the authentication works fine but if I try to sign in from the front-end application I get error: invalid_request (status 400).
Now I wonder if it should be possible to sign in from application z.x.com by calling y.x.com/Account/ExternalLogin?provider=Federation&response_type=token&client_id=self&redirect_uri=http://y.x.com.
My startup.auth in y.x.com looks like this
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
var wsOptions = new WsFederationAuthenticationOptions
{
MetadataAddress = "https://login.microsoftonline.com/afd2d5a6-bdb1-43f8-a42b-83ec49f1f22d/federationmetadata/2007-06/federationmetadata.xml",
Wtrealm = "http://y.x.com/",
Notifications = new WsFederationAuthenticationNotifications()
};
app.UseWsFederationAuthentication(wsOptions);
I can provide more code but I'm mostly interested in if should work at all.
Thanks.
This is possible. After som digging and help it turns out that in the web-api template there is a method named ValidateClientRedirectUri in the class ApplicationOAuthProvider. If I change that method to
public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
context.Validated();
return Task.FromResult<object>(null);
}
and then from my front end application I can now have any return url I want, making it possible to sign in from the front-end application via the web-api application to an external source.

How to delegate Facebook SecurityToken to WCF service

I have the following components:
WPF Application,
Identity Server,
WCF Web Service,
WPF Application uses WebBrowser control to authenticate using Thintecture Identity Server using WS-Federation. Identity Server has enabled Home Realm Discovery and allow authentication using Facebook, Live ID and Google. After authentication I get ReqquestSecurityTokenResponse message, which I convert into SecurityToken.
After getting this SecurityToken I want to call WebService. I think I need create ActAsToken issued again by Thintecture Identity Server, but I can't configure it.
var serviceAddress = "http://localhost:7397/Service1.svc";
var token3 = token2.ToSecurityToken();
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.Message);
binding.Security.Message.IssuedKeyType = System.IdentityModel.Tokens.SecurityKeyType.SymmetricKey;
binding.Security.Message.IssuerAddress = new EndpointAddress("https://dev3.example.com/Identity/issue/wsfed");
binding.Security.Message.IssuerBinding = new WS2007HttpBinding();
var factory = new ChannelFactory<IService1Channel>(binding,
new EndpointAddress(
new Uri(serviceAddress),
new DnsEndpointIdentity("dev3.example.com")));
factory.Credentials.SupportInteractive = false;
var proxy = factory.CreateChannelWithActAsToken(token3);
{
try
{
var output = proxy.GetData(1);
MessageBox.Show(output);
proxy.Dispose();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
But I get exceptions.
WebService is configured using Identity and access... VS extension.
Is this scenario possible?
you don't need an ActAs - you can use the CreateChannelWithIssuedToken method to create your WCF proxy.
You also need to configure bearer keys on the WCF service and client (instead of SymmetricKey).