We are using IIS Aplication Request routing and URL Rewrite rules to reverse proxy access to an internal webserver.
This works when IIS is configured with Anonymous authentication, but adding Basic Authentication causes problems. Without getting into too much detail about the internal webserver's authentication mechanisms, what I would like to do is not pass the Authorization Header from the IIS Proxy to the target webserver.
clientIP proxyIP HTTP GET /resource HTTP/1.1
Cache-Control: max-age=0\r\n
...
Authorization: Basic Base64EncodedCredentials
....
proxyIP serverIP HTTP GET /resource HTTP/1.1
Cache-Control: max-age=0\r\n
...
Authorization: Basic Base64EncodedCredentials <--need to remove this
....
Any tips would be greatly appreciated!
Related
I'm trying to set up an API Management Gateway using a custom domain. However, when I go to test it out, I get an SSL error. I am not sure if I've missed any steps or I've misconfigured my custom domain. The API returns a 200 response when I use the default Gateway URL but returns a 400 when I use my custom domain.
Any help in this domain is appreciated. Thanks
I've described the steps I've followed below:
Steps followed to create a custom domain:
Setup a CNAME for my custom domain api.something.com in Route 53 with Value as .azure-api.net
When creating a custom domain, I added my PFX certificate to the custom domain. When creating my certificate, I set CN="*.something.com. Additional settings such as Negotiate Client Certificate: false and Default SSL binding: true
Created an API with the suffix app1 so that my API is reachable at api.something.com/app1
Now, when I try to test it out through the portal, I get the error
HTTP/1.1 400 Bad Request
content-length: 123
content-type: application/json
vary: Origin
{
"error": "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."
}
This is the request header. ALs I've turned off Require Subscription Key but I'm not sure why the subscription key is still included in the header
GET https://api.something.com/app1/api/heartbeat HTTP/1.1
Host: api.something.com
Ocp-Apim-Subscription-Key: xxxxxxxxx
Ocp-Apim-Trace: true
I am currently following this guide on setting up authorization for an azure function. I'm currently trying to test the auth portion in fiddler separately from my web app to ensure I can get a valid token. I am able to successfully retrieve an authorization code however after that, I need to post some data to exchange the authorization code for a token. When trying to do that, I am being returned a 502 with message: DNS Lookup for "mytenantname.onmicrosoft.com" failed. System.Net.Sockets.SocketException No such host is known as if the host does not exist at all. My post to the endpoint looks as follows where B2C_1_FunctionsPlaygroundSignInRegister is the name of my user flow:
POST https://mytenantname.onmicrosoft.com/oauth2/v2.0/token?p=B2C_1_FunctionsPlaygroundSignInRegister HTTP/1.1
User-Agent: Fiddler
Content-Type: application/x-www-form-urlencoded
Host: mytenantname.onmicrosoft.com
Body:grant_type=authorization_code&client_id=MyApplicationIdForTheAzure-AD-B2C-ap-here&code=myCodeHere&redirect_uri=jwt.ms
For reference, here is the working get request I send that I can type in a browser, be prompted with a login/register screen, and be returned an authorization code after logging in:
https://mytenantname.b2clogin.com/tfp/mytenantname.onmicrosoft.com/B2C_1_FunctionsPlaygroundSignInRegister/oauth2/v2.0/authorize?client_id=yApplicationIdForTheAzure-AD-B2C-ap-here&nonce=2&redirect_uri=https://functionapi.azurewebsites.net/.auth/login/aad/callback&scope=https://mytenantname.onmicrosoft.com/api/read&response_type=code
Can someone please point out where I'm going wrong here? I've now spent a great deal of time on this issue and am out of ideas.
Your POST url and Host header are wrong.
See this section -
OAuth 2.0 authorization code flow in Azure Active Directory B2C
POST fabrikamb2c.onmicrosoft.com/oauth2/v2.0/token?p=b2c_1_sign_in HTTP/1.1
Host: https://fabrikamb2c.b2clogin.com
Note the Host header. That means your Fiddler request should read something like this:
POST https://mytenantname.b2clogin.com/mytenantname.onmicrosoft.com/oauth2/v2.0/token?p=...
Host: mytenantname.b2clogin.com
P.S. This is way better than Fiddler for what you're trying to do -
https://oauthdebugger.com/
Following on from this question:
AADSTS50013: Assertion audience claim does not match the required value
I've now successfully got the web apps running with this security model:
SPA application using adal.js/adal_angular.js to authenticate via AAD.
Returned token is passed to web api [API1] that runs on the same machine.
That web api gets a new token on behalf of the user to access a downstream API [API2].
The downstream api gets a new token on behalf of the user to access another downstream API [API3].
Now, when I have [API2] running locally, this is all working.
However, when I deploy that web app to my Azure subscription, and attempt to call it (without changing anything else other than the url in the REST API call from [API1]), I get the following:
{"Message":"Authorization has been denied for this request."}
There doesn't appear to be any other error details returned or in the Fiddler trace. Comparing the jwt token payloads between the call that works and the one that doesn't, doesn't reveal much. They appear the same other than the expiry claims and the "aio" (not sure what that is).
The only change is the URL of the deployed web app (from http://localhost:8080/ to http://mywebappname.azurewebsites.net/)
Note that the web app is deployed into a different AD tenant to the one where the app registrations and [API3] are located, but I didn't think this mattered.
Any thoughts out there on what I might need to change when I deploy, or how to troubleshoot this further?
Update: Request works with Curl
Making the same request using curl is working:
curl -H "Authorization: Bearer ey..." http://mywebapi.azurewebsites.net/api/resource
So the issue appears to be how I'm making the request in my C# code? Comparing the headers in Fiddler, I don't see any difference.
This is the Fiddler trace from curl that is working:
GET http://mywebapi.azurewebsites.net/api/resource HTTP/1.1
Host: mywebapi.azurewebsites.net
User-Agent: curl/7.46.0
Accept: */*
Connection: Keep-Alive
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJ<snip>
This is the Fiddler trace from my code that is not working:
GET http://mywebapi.azurewebsites.net/api/resource HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJ<snip>
Accept: */*
User-Agent: RestSharp/100.0.0.0
Host: mywebapi.azurewebsites.net
Accept-Encoding: gzip, deflate
Here is the request from C#:
var restClient = new RestClient(serviceUrl) { Timeout = timeout};
var restRequest = new RestRequest(apiEndpoint, Method.GET);
var bearerToken = $"Bearer {securityToken}";
restRequest.AddParameter("Authorization", bearerToken, ParameterType.HttpHeader);
var response = restClient.Execute(restRequest);
On the Azure web site logs, I can see that the authentication type for the successful curl request is "JWT", however for the failed requests from my code they are "anonymous".
Somehow the header must be being stripped despite it showing up correctly in the Fiddler trace? Is this possible?
In an unrelated issue, I had to delete all untrusted certificates from my machine (Internet Options->Content->Certificates).
And I noticed after doing this, my problem was resolved. It was a very long list of certificates, so I don't know which one(s) were causing the problem, or why.
Given the lack of responses, its obviously a very obscure issue, but unfortunately we didn't get to the bottom of it. If it occurs again, I can be a bit more methodical when I do it.
I've a Azure Linux VM created with the domain something.cloudapp.net which I'm using to host a REST API for a app. Now for some reason I've to host the API on some other server, which will change the endpoint to which the app is sending requests.
My question is, can we redirect any request to something.cloudapp.net to my new domain. So that I don't need to update the url in the app. Because if I change it in the app, a new update has to be released and the users who don't update the app will not be able to use it.
Thank you in advance,
Assuming you've hardcoded the .cloudapp.net URL in the app and not your own domain (with a CNAME to .cloudapp.net), then you still need to keep a service running at the original URL that will send a HTTP 301 redirect (Moved Permanently)** back to the clients.
Hopefully your client application understands and follows HTTP redirects. Test that first!
There is no way to CNAME the .cloudapp.net domain to point to something arbitrary since that domain is owned by Microsoft. Only the other way around is possible.
Sample redirect with web.config
(source: https://www.iis.net/configreference/system.webserver/httpredirect):
<system.webServer>
<httpRedirect enabled="true" destination="http://your.new.url/" />
</system.webServer>
Which results in:
$ curl -Li http://{something}.cloudapp.net/api/hey_jim_did_we_push_that_fix_to_prod
HTTP/1.1 302 Redirect
Content-Length: 154
Content-Type: text/html; charset=UTF-8
Location: http://your.new.url/api/hey_jim_did_we_push_that_fix_to_prod
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 02 Jan 2017 20:06:16 GMT
False
We are using IIS 7.5 with only windows authentication enabled. providers are ntlm and negogiate ( since we want it to be accessible via internet).
The client is silverlight calling wcf services. even though we have session established the client sends the negotiate and server return 401 with some authentication token. this happends intermettinetly , with many sucessful calls ( intermingled with failed calls)
Many calls work fine and just send sessionid and everthing works fine.
In fiddler we see below
Client sends
Authorization: Negotiate TlRMTVNTUAABAAAAl4II4gAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw==
ASP.NET_SessionId=0ix0fqf02j1imrpfc4awit3w
Server sends
WWW-Authenticate: Negotiate TlRMTVNTUAACAAAACgAKADgAAAAVgonitqRU/FVLp9EAAAAAAAAAAI4AjgBCAAAABgGxHQAAAA9BAEQATABBAEIAAgAKAEEARABMAEEAQgABAA4AQwBJAFIAVAAtAEQAMwAEABYAYQBkAGwAYQBiAC4AbABvAGMAYQBsAAMAJgBDAEkAUgBUAC0ARAAzAC4AYQBkAGwAYQBiAC4AbABvAGMAYQBsAAUAFgBhAGQAbABhAGIALgBsAG8AYwBhAGwABwAIAMsTFgtFNc4BAAAAAA
I'm not positive I understand your question but I'm guessing that you want to resolve the intermittent NTLM failures?
The headers you describe are part of the challenge response protocol of NTLM. Here's a more complete example:
Client: Get / HTTP/1.1
Server: HTTP/1.1 401 Unauthorized
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
Client: Get / HTTP/1.1
Authorization: Negotiate ###################### (encrypted Negotiate)
Server: HTTP/1.1 401 Unauthorized
WWW-Authenticate: Negotiate ###################### (encrypted Challenge)
Client: Get / HTTP/1.1
WWW-Authenticate: Negotiate ###################### (encrypted Response)
Server: HTTP/1.1 200 OK
It's probably a bad idea to use this Authentication method across the public internet; it's intended to be used within private intranets where both client and server can access a common Windows Active Directory Domain.
I suspect that your issue may be addressed in the "You are intermittently prompted for credentials or experience time-outs when you connect to Authenticated Services" KB article.
Here are some other related references:
NTLM Bottlenecks and the RPC runtime
NTLM and MaxConcurrentApi Concerns
Performance tuning for NTLM authentication