-1

Just for some background, I have been trying to set up Azure AD OAuth authentication using flask dance. The actual issue I'm having is when redirecting to the authorization URL, flask is not redirecting as I would expect it to.

I've tried using a simple redirect like this:

@oauth_blueprint.route('/')
def route_oauth():
    return flask.redirect('https://login.microsoftonline.com/tenant/oauth2/v2.0/authorize')

Now, if I access the page directly at localhost:5000/oauth then it works as expected and redirects me to the URL.

However, our web application is set up using a reverse proxy. The flask application is accessed at www.example.com/flask/xxx which returns the corresponding page at localhost:5000/xxx. So if I go to www.example.com/flask/oauth then I should get the same page as localhost:5000/oauth.

So the problem is when I go to www.example.com/flask/oauth the redirect does not work correctly. Instead of taking me to https://login.microsoftonline.com/tenant/oauth2/v2.0/authorize, I instead get redirected to www.example.com/tenant/oauth2/v2.0/authorize. I can't make sense of this as the URL is clearly not a relative URL.

In case it's relevant, we are using URL Rewrite in IIS. There is a simple rewrite rule which matches any URL starting with flask/. This has worked fine for all our other pages.

This is what the rule looks like in IIS: IIS Inbound Rule

I've tried using FRT to trace the rewrite. Below is the output I got. It changes to the undesired URL at line 27 but I don't understand why.

| No. | EventName                      | Details                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | Time         |
| --- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| 1.  | GENERAL_REQUEST_START          | SiteId="2", AppPoolId="App", ConnId="1610613017", RawConnId="1610613017", RequestURL="http://www.example.com/flask/oauth/", RequestVerb="GET"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | 12:35:02.963 |
| 2.  | GENERAL_ENDPOINT_INFORMATION   | RemoteAddress="::1", RemotePort="64068", LocalAddress="::1", LocalPort="81"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | 12:35:02.963 |
| 3.  | GENERAL_REQUEST_HEADERS        | Headers="Connection: keep-alive Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,\*/\*;q=0.8,application/signed-exchange;v=b3;q=0.7 Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9 Host: www.example.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.82 sec-ch-ua: "Not.A/Brand";v="8", "Chromium";v="114", "Microsoft Edge";v="114" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Windows" Upgrade-Insecure-Requests: 1 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document " | 12:35:02.963 |
| 4.  | GENERAL_GET_URL_METADATA       | PhysicalPath="", AccessPerms="513"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | 12:35:02.963 |
| 5.  | HANDLER_CHANGED                | OldHandlerName="", NewHandlerName="StaticFile", NewHandlerModules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule", NewHandlerScriptProcessor="", NewHandlerType=""                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | 12:35:02.963 |
| 6.  | URL_REWRITE_START              | RequestURL="/flask/oauth/", Scope="Distributed", Type="Inbound"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | 12:35:02.963 |
| 7.  | RULE_EVALUATION_START          | RuleName="Flask", RequestURL="flask/oauth/", QueryString="", PatternSyntax="Regex", StopProcessing="true", RelativePath="/"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | 12:35:02.963 |
| 8.  | PATTERN_MATCH                  | Pattern="^flask/(.\*)", Input="flask/oauth/", Negate="false", Matched="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | 12:35:02.963 |
| 9.  | REWRITE_ACTION                 | Substitution="http://localhost:5000/{R:1}", RewriteURL="http://localhost:5000/oauth/", AppendQueryString="true", LogRewrittenURL="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | 12:35:02.963 |
| 10. | RULE_EVALUATION_END            | RuleName="Flask", RequestURL="http://localhost:5000/oauth/", QueryString="", StopProcessing="true", Succeeded="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | 12:35:02.963 |
| 11. | GENERAL_SET_REQUEST_HEADER     | HeaderName="X-Original-URL", HeaderValue="/flask/oauth/", Replace="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | 12:35:02.963 |
| 12. | URL_CHANGED                    | OldUrl="/flask/oauth/", NewUrl="http://localhost:5000/oauth/"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | 12:35:02.963 |
| 13. | URL_REWRITE_END                | RequestURL="http://localhost:5000/oauth/"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | 12:35:02.963 |
| 14. | USER_SET                       | AuthType="", UserName="", SupportsIsInRole="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | 12:35:02.963 |
| 15. | HANDLER_CHANGED                | OldHandlerName="StaticFile", NewHandlerName="ApplicationRequestRoutingHandler", NewHandlerModules="ApplicationRequestRouting", NewHandlerScriptProcessor="", NewHandlerType=""                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | 12:35:02.963 |
| 16. | GENERAL_SET_REQUEST_HEADER     | HeaderName="Max-Forwards", HeaderValue="10", Replace="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | 12:35:02.963 |
| 17. | GENERAL_SET_REQUEST_HEADER     | HeaderName="X-Forwarded-For", HeaderValue="[::1]", Replace="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | 12:35:02.963 |
| 18. | GENERAL_SET_REQUEST_HEADER     | HeaderName="X-ARR-SSL", HeaderValue="", Replace="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | 12:35:02.963 |
| 19. | GENERAL_SET_REQUEST_HEADER     | HeaderName="X-ARR-ClientCert", HeaderValue="", Replace="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | 12:35:02.963 |
| 20. | GENERAL_SET_REQUEST_HEADER     | HeaderName="X-ARR-LOG-ID", HeaderValue="0f2e2610-c6a8-4412-be80-431075354701", Replace="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | 12:35:02.963 |
| 21. | GENERAL_SET_REQUEST_HEADER     | HeaderName="Connection", HeaderValue="", Replace="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | 12:35:02.963 |
| 22. | URL_CHANGED                    | OldUrl="http://localhost:5000/oauth/", NewUrl="/flask/oauth/"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | 12:35:02.963 |
| 23. | GENERAL_SET_RESPONSE_HEADER    | HeaderName="Content-Length", HeaderValue="371", Replace="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | 12:35:02.963 |
| 24. | GENERAL_SET_RESPONSE_HEADER    | HeaderName="Content-Type", HeaderValue="text/html; charset=utf-8", Replace="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | 12:35:02.963 |
| 25. | GENERAL_SET_RESPONSE_HEADER    | HeaderName="Location", HeaderValue="https://login.microsoftonline.com/tenant/oauth2/v2.0/authorize", Replace="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | 12:35:02.963 |
| 26. | GENERAL_SET_RESPONSE_HEADER    | HeaderName="Access-Control-Allow-Origin", HeaderValue="/..", Replace="false"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | 12:35:02.963 |
| 27. | GENERAL_SET_RESPONSE_HEADER    | HeaderName="Location", HeaderValue="http://www.example.com/tenant/oauth2/v2.0/authorize", Replace="true"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | 12:35:02.963 |
| 28. | GENERAL_SET_RESPONSE_HEADER    | HeaderName="X-Powered-By", HeaderValue="ARR/3.0", Replace="false"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | 12:35:02.963 |
| 29. | GENERAL_NOT_SEND_CUSTOM_ERROR  | Reason="SETSTATUS_SUCCESS"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | 12:35:02.963 |
| 30. | GENERAL_FLUSH_RESPONSE_START   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | 12:35:02.963 |
| 31. | GENERAL_RESPONSE_HEADERS       | Headers="Content-Type: text/html; charset=utf-8 Location: http://www.example.com/tenant/oauth2/v2.0/authorize Server: Microsoft-IIS/10.0 Access-Control-Allow-Origin: /.. X-Powered-By: ARR/3.0 "                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | 12:35:02.963 |
| 32. | GENERAL_RESPONSE_ENTITY_BUFFER | Buffer="<!doctype html> <html lang=en> <title>Redirecting...</title> <h1>Redirecting...</h1> <p>You should be redirected automatically to the target URL: <a href="https://login.microsoftonline.com/tenant/oauth2/v2.0/authorize">https://login.microsoftonline.com/tenant/oauth2/v2.0/authorize</a>. If not, click the link. "                                                                                                                                                                                                                                                                                                                                       | 12:35:02.963 |
| 33. | GENERAL_FLUSH_RESPONSE_END     | BytesSent="666", ErrorCode="The operation completed successfully. (0x0)"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | 12:35:02.963 |
| 34. | GENERAL_REQUEST_END            | BytesSent="666", BytesReceived="1028", HttpStatus="302", HttpSubStatus="0"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | 12:35:02.963 |

I'd really appreciate any help on this issue. I'm happy to provide any more details if necessary. Thank you.

dashingdove
  • 304
  • 1
  • 4
  • 15
  • How did you configure Flask on IIS? HttpPlatformHandler? https://halfblood.pro/running-flask-web-apps-on-iis-with-httpplatformhandler/ – Lex Li Jul 20 '23 at 16:03
  • @LexLi Flask hasn't really been configured on IIS. Our main website is on IIS but the flask application is served by waitress. We use the URL rewrite module in IIS to then serve up the flask application to the users from the main website, using the rewrite rules I described above. – dashingdove Jul 20 '23 at 16:23
  • Either you delete those rewrite rules and switch to HttpPlatformHandler, or you revise the rules to resolve the wrong URL calculation. BTW, to ask a question here, usually people show their rewrite rules directly. The way you described them only forces others to guess what exactly the rules are, and that’s not a good approach. – Lex Li Jul 20 '23 at 16:38
  • If you are using URL Rewrite in IIS, make sure that the rewrite rule is not interfering with the Flask application's routes. You can use FRT to trace rewrite rules and see how the rules are used internally. https://learn.microsoft.com/en-us/iis/extensions/url-rewrite-module/using-failed-request-tracing-to-trace-rewrite-rules – YurongDai Jul 21 '23 at 08:13
  • @LexLi Sorry for the lack of detail on the rewrite rule, I didn't think that would be the cause of the issue. I've added a screenshot from IIS Manager. – dashingdove Jul 21 '23 at 12:56
  • @YurongDai Thanks for the suggestion, I have included output from FRT in my question. It appears at a novice's glance that the rewrite works correctly but then for some reason it changes the redirect location afterwards. If you're able to shed any light on why this might be happening then that would be very much appreciated. – dashingdove Jul 21 '23 at 13:22

2 Answers2

1

I carefully read the FRT logs you provided.

On line 13, after the URL rewrite, the request URL is now "http://localhost:5000/oauth/", which means the rewrite was successful.

On line 25: Set the "Location" response header to "https://login.microsoftonline.com/tenant/oauth2/v2.0/authorize". This could be part of application logic that redirects the client to another URL after processing.

On line 26: Set the "Access-Control-Allow-Origin" header , Replace="false", so the existing value will not be replaced.

Line 27: Re-set the "Location" response header to " http://www.example.com/tenant/oauth2/v2.0/authorize ".

"Access-Control-Allow-Origin" is a CORS (Cross-Origin Resource Sharing) header, I think is a cross-origin request issue. Browsers typically apply same-origin restrictions to network requests. These restrictions will prevent malicious pages from making cross-origin requests from within scripts. For example, this means ordinarily a script served from https://www.example.com cannot make a request to https://login.microsoftonline.com.

For cross-origin resource sharing, you can learn more about it through the link below:

Getting started with the IIS CORS Module

How does the 'Access-Control-Allow-Origin' header work

YurongDai
  • 1,362
  • 1
  • 2
  • 7
0

It turns out that this is a feature of Application Request Routing for IIS. Unchecking "Reverse rewrite host in response headers" under "Server Proxy Settings" resolved the issue.

IIS Application Request Routing Configuration

dashingdove
  • 304
  • 1
  • 4
  • 15