IIS Reverse Proxy, Home Assistant, and Google Assistant Component

I have configured home assistant on Windows Server 2012 R2. I have it sitting behind IIS Reverse Proxy using ARR. The home assistant site works perfectly fine inside and outside of my network. I have IIS setup with a valid Let’s Encrypt cert and it converts to http communication with home assistant. I have been wiring up google assistant and to the best of my knowledge it is configured correctly including verifying my domain. I also have an api_password set. When i try to link it up in google assistant on my cell phone, i always get a 404. I see in the console an auth come through and a handshake being sent, but it’s still a 404 on my phone. It is also using some weird url that looks like https://[MY DOMAIN]/r/[client id]#access_token=[access_token]&token_type=bearer&state=[long encoded string]

Any help would be greatly appreciated.

Hi,

I have been doing the same and run into the exact same issues…

After some poking around, I believe that somehow iis is rewriting the Google Authentication URL which is: “https://oauth-redirect.googleusercontent.com/r/YOUR_PROJECT_ID#access_token=ACCESS_TOKEN&token_type=bearer&state=STATE_STRING” which appears to be similar to the URL you have above. (Here’s the page with the OAuth flow info: https://developers.google.com/actions/identity/oauth2-implicit-flow#handle_authorization_requests )

In an attempt to solve this, I put a pattern match on the inbound reverse proxy to only match the domain name for my home assistant but this didn’t appear to make any difference… I have been trying to turn on debug logging on my home assistant google_assistant.auth to inspect the authentication flow to see what message iis is rewriting but for some reason it only logs info. Will probably have to crawl through the iis logs for that one and will let you know if I find anything!

Thank you for your help. Please let me know what you find. I’ll also check logs on my side and if i figure anything out, I’ll post back.

@hydroflax I finally figured it out. After looking at the logs and a bunch of remote debugging, i figured out the headers were being overwritten. Here is a stack overflow that identifies the setting you need change: https://stackoverflow.com/questions/24207254/asp-net-oauth-having-issues-with-url-rewrite

After changing that, everything started working.

1 Like

Richard, @rhessinger
I know it’s a very-very long while ago but what settings are you refering to?
Thanks!

Hey guys,

I’m trying to get IIS working with ARR and URL rewrite, plane URL rewrite give me an authentication error.

I tried creating a server farm, but thats giving me 400: Bad Request

Can you please share your working configs?

Thanks guys :slight_smile:

After all, I decided to split this from IIS with ARR url rewrite, couldnt get it to work.

I’ll dig out my config today and send it over. i ran into similar issues, but mine was fully working. I ran into a different issue though where Home Assistant was pinning my cpu usage and i have not got back to figuring that out yet.

Thanks mate,

I appreciate that :slight_smile:

I actually kinda got it to work, but I can only log in on iPhone Chrome and Safari on my macbook. Its really odd.

Thanks again for the config :slight_smile:

What did you end up doing?

Hi @liminal,

Here is a copy of my config.

  • 127.0.0.1:8123 is my home assistant url
  • my-url-i-use.com is my domain name (not the real one, but can be replaced)
  • I had google verification setup so I could integrate mine with Google Assisstant.
  • The authentication settings looked weird in my config, but my server shows:
    • Anonymous auth enabled
    • Basic auth enabled
    • The rest was disabled
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <outboundRules>
                <rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1" enabled="true">
                    <match filterByTags="A, Form, Img" pattern="^http(s)?://127.0.0.1:8123/(.*)\s" />
                    <action type="Rewrite" value="http{R:1}://my-url-i-use.com/{R:2}" />
                    <conditions>
                    </conditions>
                </rule>
                <rule name="RestoreAcceptEncoding" preCondition="NeedsRestoringAcceptEncoding">
                    <match serverVariable="HTTP_ACCEPT_ENCODING" pattern="^(.*)" />
                    <action type="Rewrite" value="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" />
                </rule>
                <preConditions>
                    <preCondition name="ResponseIsHtml1">
                        <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
                    </preCondition>
                    <preCondition name="NeedsRestoringAcceptEncoding">
                        <add input="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" pattern=".+" />
                    </preCondition>
                </preConditions>
            </outboundRules>
            <rules>
                <clear />
                <rule name="GoogleVerification" stopProcessing="true">
                    <match url="google018b4de25464395e.html" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
                    <action type="Rewrite" url="https://my-url-i-use.com/google-verification-code.html" />
                    <serverVariables>
                        <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
                        <set name="HTTP_ACCEPT_ENCODING" value="" />
                    </serverVariables>
                </rule>
                <rule name="ReverseProxyInboundRule1" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
                    <serverVariables>
                        <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
                        <set name="HTTP_ACCEPT_ENCODING" value="" />
                        <set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" />
                    </serverVariables>
                    <action type="Rewrite" url="http://127.0.0.1:8123/{R:1}" />
                </rule>
            </rules>
        </rewrite>
        <security>
            <authentication>
                <basicAuthentication enabled="true" />
            </authentication>
            <requestFiltering>
                <requestLimits maxUrl="500000" maxQueryString="500000" />
            </requestFiltering>
        </security>
    </system.webServer>
    <system.web>
        <identity impersonate="false" />
        <authentication mode="Windows" />
    </system.web>
</configuration>

You’re a superstar!

Thanks so much for digging that out, ill see what I can do with it in the next few days :slight_smile:

Might ask you more questions lol

Thanks again!

No problem, I’ll do what I can to help.

Ok, got some time to do this today,

I just copied your outbound rules and your inbound rule for HA, worked, that’s for that!

BUT, broke everything else LOL.Plex, Outlook ect give me 500 errors.

I understand that these outbound rules are to remove and restore headers for compression. Is there a way to have that apply to ONLY the HASS rule.

Interestingly once I turned them off, everything came back and even HA continued to work, but I imagine that’s not going to last.

Appreciate your help with this!!

How is your IIS setup? Do you have everything running through one site and proxying from there?

For plex, I use different plex ports for remote access so I didn’t need to funnel anything through IIS for plex. Then I just connect via plex.tv. In the case of other URLs. I actually had multiple Dynamic DNS based URLs pointing to my server. If you do that, you can create multiple sites and bind them to a port and URL. This would allow you to separate rules that way. Also, if you are using the default site, that has a bunch of bindings to combine everything together. So you might need to remove that site first.

To help more, I would probably need to know more about your setup. Pretty much what’s running, what needs to proxy, and what is unique on each (port, URL, etc…). From there I could most likely give more guidance.

Hey thanks for getting back!

Been trying to work out a whole heap of other stuff with HA lol

So yes, I have Plex and Outlook and a few other things going though the default site. Its just an inbound rule for each that then points it to wherever it needs to go.

I don’t really want to move away from that TBH. websites are not my forte so id like to keep it as simple as possible.

It’s a bit weird though, so as I said, enabled those rules and broke all the other sites, but HA started working. Turned them off and HA kept working with all the other sites. Thought it would be some kind of cache thing, but it seems to be still working even with new devices. So it might be ok actually.

Any ideas on that behavior? or too hard without looking at it (dont worry not going to ask you to look at it HAHA)?

Thanks again for the help :slight_smile:

No problem!

It is a bit tricky to tell without looking at your setup, but I’ll do what I can to help.

Most likely the reason it is still working is most likely because your authentication is cached from when it did work. I bet if you opened an incognito tab in your browser and tried it, it would not work.

The big thing I would ask is how are you determining currently to filter your requests to the different services? I would assume your HA rules would route to a different place than your Outlook rules. If we can figure out what is unique, we can apply that to the HA rules you need to add.

Thanks,
Rich

Hi, I am trying to do a redirect with iis from a working HA http://127.0.0.1:8123/ to an address like: https://meow.mycat.it/.
In IIS I only have one “Default Website” and there are other sites that need to keep responding, such as: https://meow.mycat.it/server/rest.

I don’t know too much about IIS so I drew on your web config and tried to adapt it to my situation.
Initially I set up a new web application to respond on https://meow.mycat.it/ha, but once activated the “js” files were being requested with https://meow.mycat.it without “has” and therefore were not reachable.
Then in the various researches I read that Home Asistant doesn’t support a web application, but only a whole domain. It is true?
So I tried to make HA answer on the request https://meow.mycat.it/ and in fact the Login mask appears, but when I login HA remains in loading data…

Do you have any suggestion?

This is my web config:

  • I think the “GoogleVerification” rule doesn’t actually serve me, can I delete it?
  • You’ll also find the “ResponseIsHtml1” rule commented out, I don’t know if I did this right, is this a HA specific setting? preCondition=“ResponseIsHtml1”
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
	    <directoryBrowse enabled="false" />
        <httpErrors errorMode="Detailed" />
        <rewrite>
            <outboundRules><!-- regole per riscrivere le risposte in uscita-->
                <rule name="ReverseProxyOutboundRule1"  enabled="true">   <!-- preCondition="ResponseIsHtml1"-->
                    <!-- <match filterByTags="A, Form, Img" pattern="^http(s)?://172.xx.xx.xx:8123/(.*)\s" /> -->
                    <match filterByTags="A, Form, Img" pattern="^http://172.xx.xx.xx:8123/(.*)\s" />
					<action type="Rewrite" value="https{R:1}://meow.mycat.it/{R:2}" />
                    <conditions>
                    </conditions>
                </rule>
                <rule name="RestoreAcceptEncoding" preCondition="NeedsRestoringAcceptEncoding">
                    <match serverVariable="HTTP_ACCEPT_ENCODING" pattern="^(.*)" />
                    <action type="Rewrite" value="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" />
                </rule>
                <preConditions>
		<!--
                    <preCondition name="ResponseIsHtml1">
                        <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
                    </preCondition> 
		-->
                    <preCondition name="NeedsRestoringAcceptEncoding">
                        <add input="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" pattern=".+" />
                    </preCondition>
                </preConditions>
            </outboundRules>
            <rules>
                <clear />
                <rule name="GoogleVerification" stopProcessing="true">
                    <match url="google018b4de25464395e.html" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
                    <action type="Rewrite" url="https://my-url-i-use.com/google-verification-code.html" />
                    <serverVariables>
                        <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
                        <set name="HTTP_ACCEPT_ENCODING" value="" />
                    </serverVariables>
                </rule>
                <rule name="ReverseProxyInboundRule1" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
                    <serverVariables>
                        <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
                        <set name="HTTP_ACCEPT_ENCODING" value="" />
                        <set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" />
                    </serverVariables>
                    <action type="Rewrite" url="http://172.xx.xx.xx:8123/{R:1}" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

Thanks in advance.
Lontra

Anyone can help me?

Hi @Lontra,

Sorry, I didn’t see a reply to this thread originally. The issue you are running into is that you are trying to make your HomeAssistant a sub-application instead of the root application which is what my original config was set as. This makes sense since you have other applications running through that server, but it will most likely require you to tweak this a bit. You’ll have to update your rules to only look for the sub-application URLs and follow them.

Unfortunately, I’m in a network upgrade at home and cannot test this, but here is what I think your redirect rules should be:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
	    <directoryBrowse enabled="false" />
        <httpErrors errorMode="Detailed" />
        <rewrite>
            <outboundRules><!-- regole per riscrivere le risposte in uscita-->
                <rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1"  enabled="true">
                    <match filterByTags="A, Form, Img" pattern="^http://172.xx.xx.xx:8123/(.*)\s" />
					<action type="Rewrite" value="https://meow.mycat.it/ha/{R:2}" />
                    <conditions>
                    </conditions>
                </rule>
                <rule name="RestoreAcceptEncoding" preCondition="NeedsRestoringAcceptEncoding">
                    <match serverVariable="HTTP_ACCEPT_ENCODING" pattern="^(.*)" />
                    <action type="Rewrite" value="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" />
                </rule>
                <preConditions>
                    <preCondition name="ResponseIsHtml1">
                        <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
                    </preCondition>
                    <preCondition name="NeedsRestoringAcceptEncoding">
                        <add input="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" pattern=".+" />
                    </preCondition>
                </preConditions>
            </outboundRules>
            <rules>
                <clear />
                <rule name="ReverseProxyInboundRule1" stopProcessing="true">
                    <match url="ha/(.*)" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
                    <serverVariables>
                        <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
                        <set name="HTTP_ACCEPT_ENCODING" value="" />
                        <set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" />
                    </serverVariables>
                    <action type="Rewrite" url="http://172.xx.xx.xx:8123/{R:1}" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

Things to note:

  • You only need the google verification if you are integrating with Google Assitant directly (not using the paid integration)
  • I think you still need the is HTML
  • The outbound rule should handle the mapping of images and whatnot to the sub application path (/ha)
  • There still could be some issues if HA is trying to force a rediect to the root of the URL ( https://meow.mycat.it instead of https://meow.mycat.it/ha ), I think this will handle it, but without being able to properly test it I cannot be sure.

Give this a try and let me know how that works for you.

Thanks,
Rich