Does a lightweight server with HTTPS support exist?🥺

I am looking for a lightweight server that can run inside an app. The key requirement is that it must support local IP communication over HTTPS.

I have searched Google and found several frameworks, but as far as I know, support for HTTPS in this environment has been discontinued or is no longer available.

If anyone knows a solution that meets these criteria, I would greatly appreciate your guidance. Thank you in advance!😀

Answered by DTS Engineer in 824037022

There are two separate issues here:

  • Implementing the HTTP protocol

  • Local TLS

Those are very different problems. There are lots of good HTTP servers out there [1] but none of them tackle the local TLS issue. And for good reason. A good general-purpose solution isn’t possible because:

  • HTTPS is usually consumed by web browsers.

  • Web browsers assume the default PKI-based TLS, as described in TLS for App Developers.

  • PKI-based TLS doesn’t work for local communication.

So, something has to give:

  • You can choose not to support web browser clients. If you only supports clients that you control, you have a lot more options available to you. I talk about this in some detail in TLS For Accessory Developers.

  • If you must support web browsers, you have to live with the dire security warnings that they’ll present when you connect to a local server.

If you post details about the context of your question, I’d be happy to go into this in more depth.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] A good place to start is here:

https://www.areweserveryet.org/

There are two separate issues here:

  • Implementing the HTTP protocol

  • Local TLS

Those are very different problems. There are lots of good HTTP servers out there [1] but none of them tackle the local TLS issue. And for good reason. A good general-purpose solution isn’t possible because:

  • HTTPS is usually consumed by web browsers.

  • Web browsers assume the default PKI-based TLS, as described in TLS for App Developers.

  • PKI-based TLS doesn’t work for local communication.

So, something has to give:

  • You can choose not to support web browser clients. If you only supports clients that you control, you have a lot more options available to you. I talk about this in some detail in TLS For Accessory Developers.

  • If you must support web browsers, you have to live with the dire security warnings that they’ll present when you connect to a local server.

If you post details about the context of your question, I’d be happy to go into this in more depth.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] A good place to start is here:

https://www.areweserveryet.org/

@DTS Engineer Thank you so much for your response!

Here is my situation: I am running an older version of Mongoose Server (an embedded web server) to serve files. The web server uses a loopback address (127.0.0.x) and is primarily used to download necessary files for my app.

However, recently, accessing this web server has started triggering security warnings, which negatively impact the user experience (UX). I am looking for a solution to this issue.

I have a few questions:

  1. "If you must support web browsers, you have to live with the dire security warnings that they’ll present when you connect to a local server" > Does this mean there is no possible solution to remove these security warnings?

  2. I found a method online to bypass certificate validation. Would this affect security even though I am using a loopback address?


func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    print("[Gyeom] HTTPS Host: \(challenge.protectionSpace.host)")
    if challenge.protectionSpace.host.contains("127.0.0") {
        let urlCredential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
        completionHandler(.useCredential, urlCredential)
    } else {
        completionHandler(.performDefaultHandling, nil)
    }
}
  1. Are there any other possible solutions to this problem?

Thank you!! 😊

I’m not sure I understand your requirements. Let’s start with stuff I’m confident about:

  • You’re building an iOS app (based on your other thread).

  • That app has an embedded web server.

Right?

Written by _dayexx in 824150022
The web server uses a loopback address (127.0.0.x) and is primarily used to download necessary files for my app.

OK. I’m not sure how Safari fits into this. Can you walk me through this process end-to-end? Are there multiple users involved? Are there multiple devices? On each device, which apps are involved? And what is each user doing that results in these HTTP[S] transfers?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Overall Flow:

  • When the user clicks a button, an embedded HTML page is opened in Safari. This serves as a UI to display instructions and allows the user to download a single file.
  • There are no additional functionalities beyond this.
  • To ensure lightweight operation and prevent external access, we do not use external servers or domains.

Answers to Your Questions:

1. Are multiple users using this feature?

  • Yes, multiple users are using it. However, they can only download the designated file from the server; they cannot modify any data.

2. Does this run on multiple devices?

  • Yes, it does.

3. Which apps are involved on each device?

  • Only my app (which includes an embedded web server) and Safari are involved.

4. What actions do users take to trigger HTTP[S] requests?

  • When the user clicks a button, the Mongoose server starts, loads an HTML file stored within the app, and displays the page to the user via Safari.

I hope my explanation is clear. Thank you! 😄

Written by _dayexx in 824405022
When the user clicks a button, the Mongoose server starts, loads an HTML file stored within the app, and displays the page to the user via Safari.

When you do this Safari comes to the front, and thus your app moves to the background. Shortly thereafter your app will be suspended, which means that it’ll stop responding to networking requests. How do you handle that?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Before answering, I would like to make a correction. I have confirmed that Safari is not opened as a third-party browser but is instead launched in-app using SFSafariViewController.

When the app enters the foreground, the server stops, and when it moves to the background, the server starts running. Before transitioning to the background, the following code is used to define a background task:

- (void)didEnterBackground
{
    if(_willEnterBackground && _bgTask == UIBackgroundTaskInvalid) {
        NSAssert(_bgTask == UIBackgroundTaskInvalid, nil);
        _bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{
            dispatch_async(dispatch_get_main_queue(), ^{
                [[UIApplication sharedApplication] endBackgroundTask:self->_bgTask];
                self->_bgTask = UIBackgroundTaskInvalid;
            });
        }];
    }
}

Your background task code will only keep your app running in the background for a short period of time. I talk about this in much detail in UIApplication Background Task Notes.

If you’re using SFSafariViewController then your app never leaves the foreground, which obviates my concern on that front. It also indicates that you don’t need to support Safari per se. You could potentially move to WKWebView. The advantage of doing that is that WKWebView lets your override HTTPS server trust evaluation.

So, lemme further clarify your workflow:

  1. Your app has a button.

  2. When the user taps that button, it starts your app’s embedded web server.

  3. And presents SFSafariViewController to display a page on that web server.

  4. That page “allows the user to download a single file”.

What do mean by “download” in this context? Is the user just viewing the file? Or do you expect them to, for example, download the file, saving it in a place accessible to the Files app?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

You are not checking your email. The file you want to download is an MDM profile! Thank you.😀

Written by _dayexx in 825228022
You are not checking your email.

Nah, I just got a lot of email, so it can take a while to respond. Anyway, I prefer to discuss these things in the forums; that way everyone can benefit from my work.

Written by _dayexx in 825228022
The file you want to download is an MDM profile!

Ah, tricky. There are two parts to this:

  • App Review

  • Technical

I don’t work for App Review, so I can’t give definitive answers on that topic. However, my understanding is that configuration profiles are intended to be used by site admins, not as an API for developers. If you ship an app that uses them, you should review the App Review Guidelines carefully.

On the technical side, you are indeed in a bind:

  • SFSafariViewController doesn’t have a mechanism to override HTTPS server trust evaluation. This makes sense, because it’s meant to act just like Safari.

  • The infrastructure used to install configuration profiles is internal to Safari. It’s not available as an API, and nor is it accessible via WKWebView.

The only technical solution to the problem you’re trying to solve is to upload the configuration profile to a server with trusted a HTTPS certificate, and then point Safari at that.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I am attempting to apply NSAllowsLocalNetworking in the Plist, despite the risk of it affecting the review process, as I am using a loopback address.

However, it is not being applied.

  1. According to the documentation, local network access should not be blocked on iOS 17 and above. I am testing on iOS 18.2, but it is still being blocked.
  2. If the "Not Secure Connection Warnings" is enabled in Settings > App > Safari, are HTTP connections not allowed under any circumstances?

Reference: https://developer.apple.com/documentation/bundleresources/information-property-list/nsapptransportsecurity/nsallowslocalnetworking

Thank you for your help!

NSAllowsLocalNetworking is irrelevant to SFSafariViewController. That view is intended to act just like Safari, and Safari is not limited by App Transport Security.

Written by _dayexx in 825384022
If the "Not Secure Connection Warnings" is enabled in Settings > App > Safari, are HTTP connections not allowed under any circumstances?

I don’t know. That’s a Safari policy, and I’m hardly a Safari expert. You could try asking this in a new thread over in Safari & Web > General. Feel free to link to this thread for context.

However, I’d be disinclined to pursue this further. IMO the whole concept of apps installing profiles is on shaky ground support-wise, and that just gets worse if you insist on doing this via loopback.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I also feel bad because I'm not the decision maker. Anyway, I want to ask more questions to try to resolve as much as possible.

You mentioned

The infrastructure used to install configuration profiles is internal to Safari. It’s not available as an API, and nor is it accessible via WKWebView.

does that mean it is impossible to implement other communication methods such as SFTP for MDM profiles instead of the web?

If it's possible, could you let me know the optimal results, aside from the web option?

Thank you for your comment ! :)

Written by _dayexx in 825455022
does that mean it is impossible to implement other communication methods such as SFTP for MDM profiles instead of the web?

What do you mean by “SFTP” in this context?

My usual reading of that acronym is as the SSH File Transfer Protocol, and it’s certainly possible to implement that on our platforms. Hence my request for clarification.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

As you mentioned, I currently have an SSH server. I would like to know if it's possible to download the MDM profile via SFTP instead of Safari in the app.

If that is possible, I am considering implementing it through an SFTP client library.

Thank you!

I can’t see any connection between SFTP and configuration profiles. Safari doesn’t implement SFTP, which means you’d be doing the work in your app. And that results in the same problem you have with WKWebView: There’s no API for your app to install a configuration profile.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Does a lightweight server with HTTPS support exist?🥺
 
 
Q