How to add subdomain to Azure WebSite via API - c#

My website is hosted as Azure WebSite and I need to allow users create their own subdomains.
I already implemented this on local machine using DNS and CNAME option, but I can't do it in Azure. When I try to add Azure host name for the site I receive error that hostname must ends with '.azurewebsites.net'.
Here is my code:
var client = new WebSiteManagementClient(new CertificateCloudCredentials(ConfigurationManager.AppSettings["AzureSubscriptionId"],
new X509Certificate2(Path.Combine(AppDomain.CurrentDomain.RelativeSearchPath, "{certificate}"), "{password}")));
var configuration = client.WebSites.Get(webSpaceName, webSiteName, new WebSiteGetParameters());
if (configuration.StatusCode != HttpStatusCode.OK)
throw new Exception("AzureGet: " + subdomain);
configuration.WebSite.HostNames.Add(hostName);
var response = client.WebSites.Update(webSpaceName, webSiteName, new WebSiteUpdateParameters());
Is there any other methods to add custom HostName like 'sub.mydomain.net'?

You could use a wildcard custom domain name for your website, and then check the hostname in your application code by inspecting the headers (host or X-Forwarded-Host) of the incoming request.
i.e. your domain name would point *.mydomain.net to your web app, and then your DB keeps track of the user registered domains, and then your web app does the routing.

Related

How to Add CNAME in Azure DNS via C# code

I have requirement to have multiple subdomain.
My site is hosted in virtual machine with name test.mydomain.com
I have manually added CNAME Testing1 in azureDNS and configure that in IIS site bindings Testing1.mydomain.com. and this is working
But i want to make it automatic.intead of manual process. need to do it from code or from powershell.
Anyone having knowledge about this please help me
Thanks
You'll need to start by creating a Service Principal account since it's the authority you'll use to authenticate via the SDK into Azure.
Here's the documentation to create a service principal:
Authenticating with a password
Authenticating with a certificate
Install the following packages to your C# project:
Microsoft.Azure.Management.Dns
Microsoft.Rest.ClientRuntime.Azure.Authentication
Microsoft.Azure.Management.ResourceManager (note this is a preview package)
You'll need to populate the following variables for the sample below:
tenantID: The ID of the tenant your Service Principal and DNS resource are on
clientId: The Service Principal identifier
secret: Whatever your secret mechanism is for the Service Principal you picked above
subscriptionId: The ID of the Azure subscription your DNS resource is on
resourceGroupName: The name of the resource group your DNS resource is located in
zoneName: The name of the DNS zone you're modifying (the host name)
recordSetName: A name to assign to the record set
Then you'll use the following logic to create the necessary CNAMEs necessary in Azure DNS using the Service Principal values.
var dnsClient = new DnsManagementClient(serviceCreds);
dnsClient.SubscriptionId = subscriptionId;
// Create record set parameters
var recordSetParams = new RecordSet();
recordSetParams.TTL = 3600;
recordSetParams.CnameRecord = new CnameRecord
{
Cname = "<Your CNAME Value>"
};
//Create the record in Azure DNS
await dnsClient.RecordSets.CreateOrUpdateAsync(resourceGroupName, zoneName, recordSetName, RecordType.Cname, recordSetParams);

How to consume Azure REST API App with Azure Active Directory authorization On

I have deployed an API App to Azure, but I am having problems creating API Client if Authentication (with AAD) is set to ON.
When I try to generate service client (when Authentication is OFF), then client code is generated (it's done with Autorest) and code is working, but when I switch Authentication ON (and Action to take when request is not authenticated is set to Login with Azure Active Directory), then
1) service call returned 401 Unauthorized (without redirecting to AAD login page)
2) Then I tried to generate service client once more (from Project's context menu -> Add -> REST API Client -> then in the dialog box I chose "Select Azure Asset" and pressed OK and got a message "Failed to download metadata file for Microsoft Azure API App: ...app name..." (and "no additional information available")
I was implementing AAD according to this Azure manual (using express settings):
https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-how-to-configure-active-directory-authentication/
Was working according to this video, too and everything what is shown in this video was working, except that AAD was not demonstrated... and for me it's not working...
https://azure.microsoft.com/en-us/documentation/videos/connect-2015-what-s-new-in-app-service-api-apps/
Any suggestions?
EDIT
1) If I enter the request url (that REST API client uses) in web browser - then it returns valid results
2) I found out that I am using REST API without credentials (I thought Azure AD login screen should be presented in this case... but it isn't)
EDIT 2
I got some progress - got to the AAD login screen, but after entering credentials I get the bearer token, but when I try to query the service, I get an error message:
AADSTS65005: The client application has requested access to resource 'https....azurewebsites.net'. This request has failed because the client has not specified this resource in its requiredResourceAccess list.
Trace ID: 4176e...
Correlation ID: 1d612d...
Timestamp: 2016-11-13 18:28:34Z
These are the steps I've done to get this far:
0) Added Microsoft.IdentityModel.Clients.ActiveDirectory nuget pack to client project
1) registered my client app in Azure Active Directory
2) when calling REST API from client application, I am adding ServiceClientCredentials
3) when creating ServiceClientCredentials I provide 4 elements
-authority = this is from AAD App registrations -> Endpoints => Federation Metadata Document vērtība (without the starting part http://login.windows.net/)
-resource => this is REST API uri (=>Identifier of the target resource that is the recipient of the requested token)
-clientId => this is application id I get after I registered client app in AAD
-redirect Uri => since my client app is a Native application, then this is just any valid url
How can I specify this resource in my client app?
client has not specified this resource in its requiredResourceAccess list
I managed to find a solution on how to enable AAD authorization to Azure REST API App. Just in case anyone has the same challenge, I hope this will be helpful.
These are the steps I did:
1) In App services -> Authentication/authorization
App Service Authentication => On
Action to take when request is not authenticated => Login with AAD
Configured AAD with Express settings (there you have to create Azure
AD App for you API App - i.e. "App registration" for your service)
2) In Azure Active Directory -> App registrations
Add registration for your client app
Edit Manifest of your client app - in the requiredResourceAccess section you must add information about REST API App:
resourceAppId -> insert REST API App id here
resourceAccess {id} -> OauthPermission id value of REST API (you can get it in REST API's manifest!)
3) In your client application
generate your REST client using Autorest (from solution explorer: Add\REST API client) or create it manually
add Microsoft.IdentityModel.Clients.ActiveDirectory nuget pack
get and use token to access your API with code similar to this:
//request
(..)
var tokenCreds = getToken();
ServiceClientCredentials credentials = tokenCreds;
using (var client = new YourAPI(credentials)) {
...
}
(..)
//getting token
private static TokenCredentials getToken()
{
//get this from Federation Metadata Document in
//Azure Active Directory App registrations -> Endpoints
var authority = "f1...";
//Identifier of the target resource that is the recipient of the requested token
var resource = "https://yourapi.azurewebsites.net";
//client application id (see Azure Active Directory App registration
//for your client app
var clientId = "a71...";
//return url - not relevant for Native apps (just has to be valid url)
var redirectUri = "https://just-some-valid-url.net";
AuthenticationContext authContext =
new AuthenticationContext(string.Format
("https://login.windows.net/{0}",
authority));
AuthenticationResult tokenAuthResult =
authContext.AcquireTokenAsync(resource,
clientId,
new Uri(redirectUri),
new PlatformParameters(PromptBehavior.Auto)).Result;
return new TokenCredentials(tokenAuthResult.AccessToken);
}

Setting Cookie in Response from WEB API of a different domain

I have a Web API project and a separate web app. they have two different port numbers for their local host address. I am trying to set a cookie on the web app passed from the WEB API response. I can see it the cookie in the header, however the browser does not save the cookie. Also, if I set a cookie on the web app and try read it in the API request, it can not be seen.
task.Result.Headers.AddCookies(new CookieHeaderValue[] {
new CookieHeaderValue(MemberToken, Guid.NewGuid().ToString()){
Domain = request.RequestUri.Host == "localhost" ? null : request.RequestUri.Host,
Expires = DateTime.Now.AddDays(30),
Path = "/"
}
});

How to pass default credentials in Windows Authentication

I'm developing UWP application using C#.net and it has WCF service with Windows Authentication enabled. I struggling to pass default NetworkCredential after consume a service call using Add service reference option.
Please find below my examinations.
When I pass correct windows authentication credentials, it is working as expected.
var service = new ServiceReference.Service1Client();
service.ClientCredentials.Windows.ClientCredential =new NetworkCredential("pradeep","****");
var test = await service.GetDataAsync(1);
but, I wanted pass default network credentials while using my service methis
var service = new ServiceReference.Service1Client();
service.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
var test = await service.GetDataAsync(1);
I also tried below option.
service.ClientCredentials.Windows.ClientCredential = (NetworkCredential)CredentialCache.DefaultCredentials;
When I pass default credentials. I'm getting below exception.
The HTTP request is unauthorized with client authentication scheme
'Negotiate'. The authentication header received from the server was
'Negotiate, NTLM'.
I tested same service call with default NetworkCredential in WPF application which is working as expected.
In order to pass the default credentials for the WCF Windows Authentication in UWP by using the System.Net.CredentialCache.DefaultNetworkCredentials, first please make sure that you have added the Enterprise Authentication and Private Networks(Client & Server) capabilities as following:
For the Enterprise Authentication capability, it is because that Windows domain credentials enable a user to log into remote resources using their credentials, and act as if a user provided their user name and password. The enterprise Authentication special capability is typically used in line-of-business apps that connect to servers within an enterprise.
For the Private Networks(Client & Server) capability, it is because that currently in Windows Runtime we can only pass the default credential in the Intranet. For the Internet we have to use the Username and Password as credential.
For more information about the Capabilities, please check:
https://msdn.microsoft.com/en-us/library/windows/apps/hh464936.aspx .
After that please try to use your Computer name or Fully Qualified Computer name instead of the IP address for your WCF Services like this: http://YourComputerName:YourPortNumber/Service1.svc.
At last please use another computer as client to test the WCF Windows Authentication in UWP with the System.Net.CredentialCache.DefaultNetworkCredentials, then it should work fine.
Thanks.

SharePoint search web service error (NTLM) when called from HttpHandler

Here is my scenario: I have a SharePoint site I am working on, and it is on one server farm. In this site, I have created an HttpHandler that uses a SharePoint search webservice that is located on a different server. So that looks something like this:
SharePoint Server A, where my site lives
Has a service reference to SharePoint search web service on Server B
Has an http handler that uses the service reference to call the search service
SharePoint Server B, where the search service lives
My code looks like this:
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
QueryServiceSoapClient _queryService = new QueryServiceSoapClient(binding, new EndpointAddress("http://easearch.ea.com/_vti_bin/search.asmx"));
_queryService.ClientCredentials.Windows.AllowNtlm = true;
_queryService.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
_queryService.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
//_queryService.ClientCredentials.Windows.ClientCredential = new NetworkCredential("MyUsername", "MyPassword", "MyDomain"); //This is the only way it seems to work
//NetworkCredential userCredential = CredentialCache.DefaultCredentials.GetCredential(_queryService.Endpoint.ListenUri, "NTLM");
//_queryService.ClientCredentials.Windows.ClientCredential = userCredential;
string status = _queryService.Status();
If I use this code from a console application on my dev box, it works as expected. But when I try to use the same code from my http handler, it gives the error
The HTTP request is unauthorized with
client authentication scheme 'Ntlm'.
The authentication header received
from the server was 'NTLM'.
I've tried a number of different combinations of the code above and the only one that works from my HttpHandler is when I directly provide my credentials. Anyone have any ideas?
Thanks.
NTLM cannot delegate credentials to a remote server.
This is known as the "double hop" issue. http://blogs.technet.com/b/askds/archive/2008/06/13/understanding-kerberos-double-hop.aspx
You'll have to configure Kerberos. Basically:
Configure SharePoint to use Kerberos (in "authentication provider" in central administration)
Create a SPN for SharePoint on your application pool account (with command line "setspn")
Create a SPN for the website runnong on server B on the application account running this site
Configure delegation between the 2
Yes, Kerberos is not that easy to put in place...

Categories