In defense of «macOS 10.15 Vista»

With the release of macOS 10.15 Catalina, people are all up in arms about the additional security popups, comparing it to what happened when Windows Vista introduced UAC and its constant prompting for Administrator permission.

I can understand where people are coming from, I do have a slightly contrarian opinion which I would like to voice here as this requires more space than what a comment field on some third-party site offers me.

First, after you read the article I linked above, keep in mind that while these prompts after the first boot after the upgrade are certainly very annoying, there’s a difference to Windows Vista and later:

UAC constantly prompts for elevation when elevation is needed, but the macOS permission given out with the prompts is persistent. Once you have authorized an application, the authorization remains and the same prompt will not appear for the same application.

The screenshot presented in the original article happens after the first boot after the upgrade when a lot of applications are launched the first time. None of the prompts seen in the screenshots will ever appear again.

Blanket permission

OK. But the prompts are still annoying. Isn’t there a way how the OS could ask ahead of time and the user could blanket allow all requests?

That would be cool but it could not possibly work without requiring changes to be made to applications: The applications installed on your machine expect to be able to get access to the things the OS now prompts for permission. In most cases, this even involves synchronous API calls, so the application is suspended while the OS is waiting for user input on the permission prompt.

Finally, knowing ahead of time what APIs an application is going to use is impossible to know, so it’s impossible to list the things an application needs ahead of time. You could run static analysis on a binary, but it would be full of false positives (scaring the user with accesses an application doesn’t need) and false negatives (still showing dialogs).

For an ahead-of-time permission request, an app would need to declare the permissions it needs and then also be prepared for API calls to fail, even though they used to always succeed (and might not even have an option to signal an error to the caller). This means apps need to be updated.

And you know what: At least for some of the features (namely filesystem related things), such a declaration is now possible via the application’s .plist file though, guess what, nobody updated their applications for catalina yet

Off-switch

Fine, so the apps aren’t updated yet. Why isn’t there a way for me to turn this off?

There is a way though: If you boot from the recovery partition (by holding Cmd-R while turning the machine on), you can configure system integrity prevention and gatekeeper to your liking using the command line tool csrutil

Macs with system integrity prevention disabled will not to any of this prompting.

Oh – but disabling system integrity prevention is a security issue? Well – so is letting applications roam free on your disk, control other windows or read keystrokes not sent to themselves.

Oh – but why do I have to reboot to disable this? I want an UI to be able to do so in the running system. If you allow this, then «helpful» applications will silently do that for you which means Apple wouldn’t even had to bother implementing SIP to begin with.

Ok. But why does it have to be such a complicated command-line tool? In order to protect users from themselves. This is a very powerful sledgehammer. With great power comes great responsibility and by making the steps required as complicated as possible, the likelihood it’s going to give somebody pause before blindly following the steps presented by the «Flash Player Installer» increases.

In conclusion

I think the prompts are annoying, but once you’ve gone though the initial flood, they appear very rarely. For me it was a mild inconvenience, but even though I consider myself a somewhat technical user, I love the protection of SIP. In light of ever more devious dark patterns and phishing attempts (that last link was on HN the same day as the article complaining about Catalina, btw).

Longer-term I wish that privacy sensitive APIs will all get asynchronous and will all require declaration ahead of time (like Android – but there, people are complaining too) and I wish that applications would update to these APIs or be forced into adopting them (causing another slew of articles about Apple breaking thousands of old applications), but in the mean time, I’m gladly accepting a prompt here and then if it means I’m harder to phish and harder to have my data exfiltrated from.

Fun* with SwiftUI Beta 5 and 6

After a lot of momentum in Beta 4 where I finally got my rogue smide.ch client for the watch to work, Beta 5 and 6 were a bit of a letdown with regards to real-world usability.

Already with Beta 4, Apple has deprecated @ObjectBinding and BindableObject, both of which total staples of SwiftUI and totally required for you to do any kind of meaningful application because they provide the glue by which you hook your UI up to you actual application.

With this, even the last pieces of sample code shown at WWDC sessions about SwiftUI were now invalidated. What a breakneck speed of development.

On the other hand, this was also a case of parallel evolution inside Apple because all the old pair provided was also provided by the Combine framework with latter having the advantage of actually be usable not just in SwiftUI but anywhere in your applications.

So I can completely understand the reasoning behind the deprecation. If you are willing to clean this up, then the beta period is the time to do it.

However in Beta 4 on watchOS, while the old method was deprecated, the new way only worked partially: If you changed your class that was previously inheriting from BindableObject to now inherit from the correct Combine.ObservableObject, none of your publishes would actually be picked up by SwiftUI and the UI would remain static.

So in Beta 4, even though it was deprecated, I kept using BindableObject because that’s what was working. @ObjectBinding on the other hand, I could replace with @ObservedObject

But then, Beta 5 happened and the Beta 4 app crashed on startup.

Trying to compile it lead to a linker error because BindableObject now was gone for good. Note that the compiler was still just complaining about it being deprecated, but at link time, the symbol was missing and linking failed. This would also explain the crash at startup of the old Beta 4 app.

I’ve quickly replaced BindableObject with Combine.ObservableObject which made the app build again and run fine – on the simulator

On the real hardware, it would continue crashing on launch.

Even after installing the logging profile on the watch in order to get some information via the Console, all I got was a single log line entry from Carousel complaining about the launched process shutting down.

As this is just a fun project after all, this is where I stopped again, waiting what further betas will bring.

After a while, Beta 6 came and went. It brought no change.

Then, Beta 7 happened, but I didn’t even bother trying to recompile without an updated Xcode which finally happened today and, spoiler alert, my App is back in a running state. No further changes were required.

So it all wasn’t my fault after all.

Next time I’ll talk about the changes I’ve done since Beta 7 and Xcode Beta 6

Fun with SwiftUI – Beta 4

After hitting yet another wall with Beta 3, the moment Beta 4 was released I’ve updated all my devices, recompiled the application and looked at it on the watch.

This time, without any change on my part, things just fell into place:

Location permission worked correctly. I had my list of Bikes sorted by location

What I didn’t like as much though were all the deprecation warnings I was already accumulating. During this years Beta Period, none of the APIs presented at WWDC were finalized. SwiftUI and Combine are still very much in flux and the APIs change on a biweekly basis.

At the time of this writing, Beta 5 has already removed all older deprecations and has added even more deprecations. We’re now at a point where most of the videos from WWDC sessions that are explaining SwiftUI and combine are not applicable to the real world any more, but that’s for another post.

Some lipstick on the pig

With things mostly working right, there was one thing that was bugging me in the list of bikes you’re seeing in the screenshot above: The distances to my current location were manually formatted in meters, but I knew that Apples platforms come with very good locale dependent unit formatters, so I wanted to fix that.

MeasurementFormatter has a .naturalScale unit option that’s supposed to pick scale and unit automatically dependent on the user’s locale. In case of distances, here in Switzerland, I would expect a distance to be shown in meters up until 1 km at which point I would expect a distance to be shown in km with one fractional digit of accuracy.

But that’s now what MeasurementFormatter does: It insisted on using km and it insisted on three fractional digits of accuracy. That’s why I’ve decided to format on my own. But I knew there must be a proper solution.

It tuns out, there is – but it’s part of MapKit, not of Foundation: There’s MKDistanceFormatter to use for this and while MeasurementFormatter has a unitOptions property, the MKDistanceFormatter has a unitStyle property which you can set to .abbreviated to get to the proper effect.

So I have added that and also used battery icons based on SFSymbols to display the bikes battery levels like so:

we’ll never know why there’s no battery.50 image. Only .100, .25 and .0

Reactive warts in SwiftUI

Remember when I said that the whole UI hierarchy was going to be built from one parent SwiftUI view that would decide on a state object? That’s the design I totally went with:

My main ContentView is just a big switch statement, completely exchanging its subview hierarchy dependent on what the global state handler object thinks should be currently active.

As you can see in above code, there’s only .ListingBikes – there’s no state to list a single bike. That’s fine, because that’s up to that BikeList view to decide to instead of listing a list of bikes it wants to show a single bike.

I did this using a NavigationLink nee NavigationButton setting its destination to the detail view:

What’s nice is that you get a free sliding animation and a free back button out of this. However, what’s not as nice is that if you do this, the detail view gets pushed as another native view on top of the existing view.

Which means that even when the big switch statement from the screenshot above causes a different sub-view to be rendered (and it does get rendered), then the additional view pushed by the NavigationLink remains shown on top and does not get closed.

In the end, here on Beta 4, I went with a NavigationDestinationLink so I could first close the detail view and then tell the state handler I wanted to create a booking.

At the time of this writing (Beta 5 has just been released), NavigationDestinationLink is already deprecated again and the state whether the destination is showing or not can be passed as a $binding, however, also at the time of this writing, this currently messes with the free back button

Another thing that falls in the same bucket of re-painting the whole hierarchy does not in fact repaint the whole hierarchy is a SwiftUI View’s navigationBarTitle modifier: if you set that once on any subview, it will persist even through you removing that subview and replacing it by another which doesn’t use the navigationBarTitle modifier.

Meaning that setting a property on a subview as an effect on global state.

This feels wrong to me.

First booking

Anyways – enough complaining. With all of this in place, I did my very first commute with a smide bike using nothing but my watch. Here you see me at the end of the trip, ready to end the booking:

That felt great.

What doesn’t feel great is the mess Beta 5 made out of my nicely layouted UI. But that’s for another day.

Fun with SwiftUI – Beta 3

After being abruptly stopped last time by a compilation step that would not complete in a finite amount of time, I let the project rest until Beta 3 was released.

I could probably have found my mistake, but I was also willing to give it another two weeks and then see whether the compiler would just tell me what I was doing wrong.

Which, when Beta 3 was released, it actually did. Trying to recompile the project would immediately be stopped at a clear error message (I don’t actually remember the details any more), but the fix was very easy after all.

Motivated to finally move on, I finished hooking up my state handler to the UI itself and I was finally at a point where I would run this skeleton in the simulator.

Simulator says: nope.

First the good news: Apple was right when they proudly said that they have improved the watch simulator workflow: Launching the simulator in stand-alone mode finally is a sub-second endeavor and so is actually launching your app in the debugger.

Working this way is actual honest-to-god fun.

Yes, things should just work like this out of the box, but until now, they never did: Running the watch simulator meant also running the phone simulator and proxying all debugger operations through the phone simulator, including breaking connections and horrible, horrible lag.

But none of this still happens in WatchOS 6: The simulator can run on its own and it launches instantly. No connection issues.

At least not to talk to Xcode…

My initial excitement about things working so well was abruptly dampened by the fact that all network access I was trying to do in the simulator ended up failing with a generic error and in the log output some backend component would complain about losing connection to the background transfer service.

Of course I first assumed to be the source of the problem and I spent two hours trying to find out what I was doing wrong.

I shouldn’t have, because my last resort was to check the Apple Beta forums and there, I didn’t even have to bother posting a question: Others had the issue too and the solution is to just use a real device.

Onwards to the real device

Updating a watch to a Beta OS is a tricky proposition: There is no (official) way to ever downgrade and stuff is known to be shaky.

Also, my watch is the one single computer I use that produces data for which I have no backup and re-creating the data is a (literally) painful experience.

I’m talking about workout data.

For two years now I’m running 10ish km every day and while I know rationally that the actual act of running is what counts, unfortunately, my subconscious only accepts a run as having happened when it’s also tracked in the Activity app and when the rings are closed.

So would I dare updating to a beta version knowing that I can’t downgrade and that the watch is producing irreplaceable data that I heavily rely on?

Of course I would. 🤓

But only after checking our local electronics retailer to make sure that they had a replacement watch on stock if worse comes to worst. Yes. I know that you can ask Apple to downgrade a bricked/unsuable watch, but that would mean days without the watch and days without my runs being tracked.

Inacceptable.

Anyways. Updating to watchOS 6 went fine and a small test walk around my house has shown that tracking workouts was still generally working fine. So I was all set to try it on the real device.

Moving forward on the device

The good news: While not as fast as the simulator, deploying and debugging on the watch still is considerably quicker and more reliable than it ever was on any previous combination of Xcode, iOS and watchOS.

Debugging still involves proxying though the phone, but now it’s reliable. Over the course of 4 weeks of doing this (spoiler alert), I only had one or two instances where Xcode wouldn’t talk to the watch and more and I had to restart my computer, my phone and my watch to get connectivity restored.

Judging by other people’s prior experiences, this is a huge step forward.

The other good news: Network requests to indeed work on the real device. My client could fetch a JWT token from the smide.ch service and it could get a list of currently available bikes.

Impressive rendering speed

I have chosen the most naïve implementation possible and just fed the whole list of ~200 bikes directly into the UI framework. No dealing with cell reuse, no limiting the size of the list, nothing. Just “hey SwiftUI, please render this list of 200 bikes”.

And render it does: It’s quick and scrolling through the whole list is buttery smooth without doing any kind of optimization work. And once the next roadblock is fixed (see below) and the list gets dynamically re-sorted as my location changes, that too is buttery smooth.

I’m getting away with telling the framework that the list has changed and needs repainting and I just pass it a new updated list of bikes. The change is instantaneous. Even though it’s a new list of 200 items.

This is so much fun. I shouldn’t need to care about minimizing updates. I shouldn’t need to care about cell reuse. I shouldn’t need to deal with this. And with SwiftUI, I don’t have to.

Location roadblocks

Excited, I moved forward to asking for location access and using location to sort the list of bikes.

And this is where things ground to a halt.

Whenever my independent watch app extension would be launched, I would be calling CLLocationManager.authorizationStatus() which would tell me that my status was .notDetermined, so I would ask for permission.

My delegate callback would be called with .authorizedWhenInUse, but CLLocationManager.authorizationStatus() would still return .notDetermined and all attempts at calling location specific API would be ignored.

As this was my first strides into CoreLocation, I assumed this to be my fault and spent a lot of time debugging this, moving code around and trying out things, but not matter what I did, the effects didn’t change.

Then I tried Apple’s Sample Code from 2016 which of course worked fine even after I changed the integrated watch app to be usable independently.

After a few more hours of trial and error, I finally was able to pin it down though: In Beta 3 (and presumably earlier Betas too), the CoreLocation permission management is broken if your watch app is a completely independent watch app.

If it has a companion iOS app, then requesting location permission is fine, but when you have a watch app without any iOS app which has a plist that looks like this:

<key>WKWatchOnly</key>
<true/>

Then requesting location permission would trigger a race condition where your permission is simultaneously granted and not granted.

I could have caved and made an empty iOS companion app at this point, but I decided to report this issue using Feedback Assistant and call it another two weeks.

The relief I felt when I’ve seen Apple’s official code sample to fail the same way as my sample code did the moment I set that WKWatchOnly flag was one hell of a feeling.

I wasn’t doing it wrong. I wasn’t losing my mind.

Next time, things will finally fall into place, but only after dealing with deprecations.

Fun with SwiftUI – Beta 2

After spending the first two weeks of the beta period to get a foundation going, I was eager to start working on the actual watch app.

This was right about the time when Beta 2 hit, so first I’ve upgraded to that and then started with the Watch project.

Building the UI

Eager to play around with SwiftUI, the first thing I have done was to actually just create a skeleton UI:

What immediately sprang to my mind as I was working on this was the fact that the built-in preview feature of SwiftUI forces you to keep your views self-contained and to keep the dependencies small and to keep your data easily mockable.

Otherwise you will suddenly be in the position where your Xcode preview requires working network connections and a lot of application state.

I’ve also learned that Beta 2 was still on very shaky grounds before running the actual code even once: My attempts to display a map view caused Xcode to crash completely the moment it tried to paint the UI preview, so I’ve stubbed that out to just be a rectangle

But overall, designing (if you can call it that) the skeleton UI went very quickly (a matter of a few hours) and I was eager to hook everything up.

A hard stop

After working on the UI, the next step was to produce a backend that orchestrates the actual application state. This single class is the only thing that keeps track of state in the application and based on which the UI decides what to paint and how and where the UI will call into in order to change the overall state (for example when the user logs in or when they start a booking)

This is what (at the time) you would use @ObjectBinding and BindableObject for.

My next step, thus, was to create what I called the ApplicationStateHandler which I had implement the BindableObject protocol.

That handler itself would expose a state property which could have one of various values of an ApplicationState enum. The main SwiftUI view would basically be a huge select statement over that state property and then decide what actual view to render based on the state.

This was my plan, but no matter what I did, the moment I had ApplicationStateHandler implement the BindableObject protocol, I would put Xcode 11 Beta 2 in a state where it was using 100% of each of my 8 CPU cores while trying to compile my code.

So in the end, I wasn’t stopped by incomprehensible error messages (I got my share of those too), but by a compilation run that did not seem to want to complete in finite time.

Instead of solving the halting problem, I decided to wait another two weeks because I already had other non-project related things on my plate.

Stay tuned for next time to see what stopped me hard in Beta 3

Fun with SwiftUI – Beta 1

As explained before, I’ve decided to scratch my own itch and write an independent Apple Watch client for the smide.ch bike sharing service.

The first step to getting from the idea to the final watch app wasn’t actually involving the Watch at all: Before I could get started, I needed to know how the existing smide clients actually work and how to talk to their server.

Then I wanted to have a unit-tested library that I could use from the Watch Frontend.

On top of that library, I wanted to have a command-line client for easier debugging of the library itself.

And only then would I start working on the frontend on the watch.

Preliminaries

So as the Developer Beta 1 for XCode 11, WatchOS 6 and Catalina rolled out, the first few days of development I spent reverse-engineering the official Smide Client.

As always, the easiest solution was to just de-compile their Android Client and lo and behold, they are making use of retrofit to talk to their server which lead to a very nice and readable interface documentation right in my decompiler

Armed with this information, a bit of grepping through the rest of the decompiled code and my trusty curl client, I was able to document the subset of the API that I knew I was going to need for the minimal feature-set I wanted to implement.

In order to have a reference for the future, I have documented the API for myself in the OpenAPI format

This is useful documentation for myself and if I should ever decide to make the source code of this project available, then it’ll be useful for anybody else wanting to write a Smide client.

Moving to XCode: SmideKit

Now that I had the API documentation I needed, the next step was to start getting my SmideKit library going.

Even though there are tools out there that generate REST clients automatically based on an OpenAPI spec, all the tools I looked at produce code that relies on third-party libraries, often Alamofire. As XCode 11 was in a very rough shape already on its own, I wanted to minimize the dependencies on third-party libraries, so in the end, I’ve opted to write my own thin wrapper on top of URLSession

The SmideKit library

SmideKit is a cross-platform (by Apple’s definition) library in that the code itself works across all of Apple’s OSes, but there are individual targets for the individual OSes

But by manually setting the Bundle Name to $(PRODUCT_NAME) in the individual Info.plist files, I can make sure that all projects can just import SmideKit without any suffixes.

As this library is the most crucial part of the overall project, I have written unit testes for all methods to make sure we correctly deal with expiring tokens, unresponsive servers and so on.

The command line client

The first user of SmideKit would be a macOs command-line frontend called smidecli. It would offer various subcommands for listing bikes, booking them and ending bookings.

Here’s a screenshot of me booking a bike

Going from nowhere to the working command-line client has taken me the whole period of Beta 1. Two weeks is a long time but between my actual day job and my newly put upon me parenting duties, my time was a bit limited.

Still. It felt good to go from nowhere to writing a library, writing a command-line frontend and then actually using it to book a bike. On the other hand: None of the code written at this point had anything to do with the announcements of WWDC. All work done could just as well have been done on the old SDKs. But still: Having a good foundation to stand on, I was sure was going to pay off.

Next time: Adventures in Beta 2

Fun project in SwiftUI

This year’s WWDC really shook the Apple Ecosystem with probably the most announcements ever happening at a single conference.

Three of the announcements when put together finally pushed me over the line to scratch a personal itch of mine that I was having for a bit more than a year: I’m a very happy customer of the smide.ch bike sharing service here in Zürich, Switzerland: Their electric bikes are well maintained, extremely fun to use and readily available to the point that they have become my main means for transport for my daily commute.

On the other hand, as the Apple Watch has become more and more capable over time between updates to the OS and to the hardware itself to the point where I can now theoretically leave my phone at home and just rely on the watch.

The last remaining hard stopping block was the smide client which so far is only available on the phone, but not on the watch.

So there you see my itch that needed scratching.

In this context, this year’s WWDC was the perfect storm for me: independent Watch apps, SwiftUI and especially SwiftUI on the watch as a real native UI framework unshackled from the constraints of the purely Storyboard based hacks in WatchKit.

The moment I dug through the announcements, I knew: I need to make myself a Smide client and after 3 Beta releases from Apple, that’s what I have done:

After launching the App and assuming you’re logged in, it lists the bikes around you, sorted by distance to your current location (they have both black (smaller) and white (bigger) bikes – hence the coloring):

Tap any bike and you get a detail view including a map

Start the booking and you get some booking information

This feature-set is very limited compared to the official client:

  • Logging in only works for accounts that were created with an email address and a password. There is no way for my third-party client to possibly work with any oAuth provider
  • There is no way to report an issue with a bike
  • The client doesn’t currently take into account the free 10 minute reservation
  • The official client does some additional user interface activity reporting which my rogue client doesn’t do.
  • There is zero payment related functionality: As I personally have a 3 year subscription, I don’t need it and besides, this is a rogue client and I can’t and don’t want to deal with their payment system.

Still. This was a fun experience to develop and to keep up-to-date between the various Beta releases, all of which deprecated some essential functionality that was also shown off during conference sessions.

Over the next few days I’m going to write down a development diary like I have done for tempalias back in the days.

To put a bit of a damper on your expectations: As this work is not sanctioned by Smide themselves and as it’s based on reverse-engineering their existing client and because this year’s API for SwiftUI and Combine is still very much in flux, I’m reluctant to release the source code of this.

Fiber7 TV behind PFSense

As I’ve stated previously, I’m subscribed to what is probably the coolest ISP on earth. Between the full symmetric Gbit/s, their stance on network neutrality, their IPv6 support and their awesome support even for advanced things like setting up an IPv6 reverse DNS delegation(!), there’s nothing you could ever wish for from an ISP.

For some time now, they have also provided an IPTV solution as an additional subscription called tv7.

As somebody who last watched live tv around 20 years ago, I wasn’t really interested to subscribe to that. However, contrary to many other IPTV solutions what’s special about the Fiber7 solution is that they are using IP multicast to deliver the unaltered DVB frames to their users.

For people interested in TV, this is great because it’s, for all intents and purposes, lag free as the data is broadcast directly through their network where interested clients can just pick it up (of course there will be some <1ms lag for the data to move through their network plus some additional <1ms lag as your router forwards the packets to your internal network).

As I never dealt with IP multicast, this was an interesting experiment for me, and when they released their initial offering, they provided a test-stream to see whether your infrastructure was multicast ready or not.

Back then, I never got it to work behind my PFSense setup but as I wasn’t interested in TV, I never bothered spending time on this, though it did hurt my pride.

Fast forward to about three weeks ago where I made a comment on twitter about that pride being hurt to the CEO of fiber7. He informed me that the test stream was down, but then he also sent me a DM to ask me whether I was interested in trying out their tv7 offering, including the beta version of their app for the AppleTV.

That was one evil way to nerd-snipe me, so naturally, I told him that, yes, I would be interested, but that I wasn’t really ever going to use it aside of just getting it to work, because live TV just doesn’t interest me.

Despite the fact that it was past 10pm, he sent me another DM, telling me that he has enabled tv7 for my account.

The rest of the night I spent experimenting with IGMP Proxy and the PFSense firewall to some varying success, but on the next day I was finally successful

You might notice that this is a screenshot of VLC. That’s no coincidence: While Fiber7 officially only supports the AppleTV app, they also offer links on a support page of theirs to m3u and xspf playlists that can be used by advanced users (which is another case of Fiber7 being awesome), so while debugging to make this work, I definitely preferred to using VLC which had a proper debug log.

After I got it to work, I also found a bug in the Beta version of the Fiber7 app where it would never unsubscribe from a multicast group, causing the traffic to my LAN to increase whenever I would switch channels in the app. The traffic wouldn’t decrease even if the AppleTV went to sleep – only a reboot would help.

I’ve reported this to Fiber7 and within a day or two, a new release was pushed to TestFlight in order to fix the issue.

Since this little adventure happened, Fiber7 has changed their offering: Now every Fiber7 account gets free access to tv7 which will probably broaden the possible audience quite a bit.

Which brings me to the second point of this post: To show you the configuration needed if you’re using a PFSense based gateway and you want to make use of tv7.

First, you have to enable the IGMP proxy:

Screen Shot 2018-05-22 at 16.31.15.png

For the LAN interface, please type in the network address and netmask of your internal IPv4 LAN.

What IGMP Proxy does is to listen to clients in your LAN joining to a multicast group and then joining on their behalf on the upstream interface. It will then forward all traffic received on the upstream aimed at the group to the group on the downstream interface. This is where the additional small bit of lag is added, but this is the only way to have multicast cross routing barriers.

This is also mostly done on your routers CPU, but at the 20MBit/s a stream consumes, this shouldn’t be a problem on more or less current hardware.

Anyways – if you want to actually watch TV, you’re not done yet because even though this service is now running, the built-in firewall will drop any packets related to multicast joining and all actual multicast packets containing the video frames.

So the next step is to update the firewall:

Create the following rules for your WAN interface:

Screen Shot 2018-05-22 at 16.39.07.png

You will notice that little gear icon next to the rule. What that means is that additional options are enabled. The extra option you need to enable is this one here:

Screen Shot 2018-05-22 at 16.41.31.png

I don’t really like the second of the two rules. In principle, you only need to allow a single IP: The one of your upstream gateway. But that might change whenever your IPv4 address changes and I don’t think you will want to manually update your firewall rule every time.

Instead, I’m allowing all IGMP traffic from the WAN net, trusting Fiber7 to not leak other subscriber’s IGMP traffic to my network.

Unfortunately, you’re still not quite done.

While this configures the rules for the WAN interface, the default “pass all” rule on the LAN interface will still drop all video packets because the above “Allow IP options” checkbox is off by default for the default pass all rule.

You have to update that too on the “LAN” interface:

Screen Shot 2018-05-22 at 16.46.47.png

And that’s all.

The network I’m listing there, 77.109.128.0/19 is not documented officially. Fiber7 might change that at any time at which point your nice setup will stop working and you’ll have to update the IGMP Proxy and Firewall configuration.

In my case, I’ve determined the network address by running

/usr/local/sbin/igmpproxy -d -vvvv /var/etc/igmpproxy.conf

and checking out the error message where igmpproxy was not allowing traffic to an unknown network. I’ve then looked up the network of the address using whois and updated my config accordingly.

Why I recommend against JWT

Json Web Tokens are all the rage lately. They are lauded as being a stateless alternative to server-side cookies and as the perfect way to use authentication in your single-page app and some people also sell them as a work around for the EU cookie policy because, you know, they work without cookies too.

If you ask me though, I would always recommend against the use of JWT to solve your problem.

Let me give you a few arguments to debunk, from worse to better:

Debunking arguments

It requires no cookies

General “best” practice stores JWT in the browsers local storage and then sends that off to the server in all authenticated API calls.

This is no different from a traditional cookie with the exception that transmission to the server isn’t done automatically by the browsers (which a cookie would be) and that it is significantly less secure than a cookie: As there is no way to set a value in local storage outside of JavaScript, there consequently is no feature equivalent to cookies’ httponly. This means that XSS vulnerabilities in your frontend now give an attacker access to the JWT token.

Worse, as people often use JWT for both a short-lived and a refresh token, this means that any XSS vulnerability now gives the attacker to a valid refresh token that can be used to create new session tokens at-will, even when your session has expired, in the process completely invalidating all the benefits of having separate refresh and access tokens.

“But at least I don’t need to display one of those EU cookie warnings” I hear you say. But did you know that the warning is only required for tracking cookies? Cookies that are required for the operation of your site (so a traditional session cookie) don’t require you to put up that warning in the first place.

It’s stateless

This is another often used argument in favour of JWT: Because the server can put all the required state into them, there’s no need to store any thing on the server end, so you can load-balance incoming requests to whatever app server you want and you don’t need any central store for session state.

In general, that’s true, but it becomes an issue once you need to revoke or refresh tokens.

JWT is often used in conjunction with OAuth where the server issues a relatively short-lived access token and a longer-lived refresh token.

If a client wants to refresh its access token, it’s using its refresh token to do so. The server will validate that and then hand out a new access token.

But for security reasons, you don’t want that refresh token to be re-used (otherwise, a leaked refresh token could be used to gain access to the site for its whole validity period) and you probably also want to invalidate the previously used access token otherwise, if that has leaked, it could be used until its expiration date even though the legitimate client has already refreshed it.

So you need a means to black-list tokens.

Which means you’re back at keeping track of state because that’s the only way to do this. Either you black-list the whole binary representation of the token, or you put some unique ID in the token and then blacklist that (and compare after decoding the token), but what ever you do, you still need to keep track of that shared state.

And once you’re doing that, you lose all the perceived advantages of statelessness.

Worse: Because the server has to invalidate and blacklist both access and refresh token when a refresh happens, a connection failure during a refresh can leave a client without a valid token, forcing users to log in again.

In todays world of mostly mobile clients using the mobile phone network, this happens more often than you’d think. Especially as your access tokens should be relatively short-lived.

It’s better than rolling your own crypto

In general, yes, I agree with that argument. Anything is better than rolling your own crypto. But are you sure your library of choice has implemented the signature check and decryption correctly? Are you keeping up to date with security flaws in your library of choice (or its dependencies).

You know what is still better than using existing crypto? Using no crypto what so ever. If all you hand out to the client to keep is a completely random token and all you do is look up the data assigned to that token, then there’s no crypto anybody could get wrong.

A solution in search of a problem

So once all good arguments in favour of JWT have dissolved, you’re left with all their disadvantages:

  • By default, the JWT spec allows for insecure algorithms and key sizes. It’s up to you to chose safe parameters for your application
  • Doing JWT means you’re doing crypto and you’re decrypting potentially hostile data. Are you up to this additional complexity compared to a single primary key lookup?
  • JWTs contain quite a bit of metadata and other bookkeeping information. Transmitting this for every request is more expensive than just transmitting a single ID.
  • It’s brittle: Your application has to make sure to never make a request to the server without the token present. Every AJAX request your frontend makes needs to manually append the token and as the server has to blacklist both access and refresh tokens whenever they are used, you might accidentally end up without a valid token when the connection fails during refresh.

So are they really useless?

Even despite all these negative arguments, I think that JWT are great for one specific purpose and that’s authentication between different services in the backend if the various services can’t trust each other.

In such a case, you can use very short-lived tokens (with a lifetime measured in seconds at most) and you never have them leave your internal network. All the clients ever see is a traditional session-cookie (in case of a browser-based frontend) or a traditional OAuth access token.

This session cookie or access token is checked by frontend servers (which, yes, have to have access to some shared state, but this isn’t an unsolvable issue) which then issue the required short-lived JW tokens to talk to the various backend services.

Or you use them when you have two loosely coupled backend services who trust each other and need to talk to each other. There too, you can issue short-lived tokens (given you are aware of above described security issues).

In the case of short-lived tokens that never go to the user, you circumvent most of the issues outlined above: They can be truly stateless because thank to their short lifetime, you don’t ever need to blacklist them and they can be stored in a location that’s not exposed to possible XSS attacks against your frontend.

This just leaves the issue of the difficult-to-get-right crypto, but as you never accept tokens from untrusted sources, a whole class of possible attacks becomes impossible, so you might even get away with not updating on an too-regular basis.

So, please, when you are writing your next web API that uses any kind of authentication and you ask yourself “should I use JWT for this”, resist the temptation. Using plain opaque tokens is always better when you talk to an untrusted frontend.

Only when you are working on scaling our your application and splitting it out into multiple disconnected microservices and you need a way to pass credentials between them, then by all means go ahead and investigate JWT – it’ll surely be better than cobbling something up for yourself.

sensational ag is hiring an iOS developer

Sensational AG is the company I founded together with a collegue back in 2000. Ever since then, we had a very nice combination of fun, interesting work and a very successful business.

We’re a very small team – just six programmers, one business guy and a product designer. Me personally, I would love to keep the team as small and tightly-knit as possible as that brings huge advantages: No politics, a lot of freedoms for everybody and mind-blowing productivity.

I’m still amazed to see what we manage to do with our small team time and time again and yet still manage to keep the job fun. It’s not just the stuff we do outside of immediate work, like UT2004 matches, Cola Double Blind Tests, Drone Flights directly from the roof of our office, sometimes hosting JSZurich and meetups for the Zurich Clojure User group and much more – it’s also the work itself that we try to make as fun as possible for everybody.

Sure – sometimes, work just has to be done, but we try as much as possible to distribute the fun parts of the work between everybody. Nobody has to be a pure code monkey; nobody constanly pulls the “change this logo there for the customer” card (though, that card certainly exists to be pulled – we just try to distribute it).

Most of the work we do flows into our big eCommerce project: Whenever you order food in a restaurant here in Switzerland, if the restaurant is big enough for them to get the food delivered to them, the stuff you eat will have been ordered using the product of ours.

Whenever you visit a dentist, the things they put in your mouth likely have been ordered using the product of ours.

The work we do helps countless people daily to get their job done more quickly allowing them to go home earlier. The work we do is essential for the operations of many, many companies here in Switzerland, in Germany and in Austria.

From a technical perspective, the work we do is very interesting too: While the main part of the application is a web application, there are many components around it: Barcode Scanners, native Smartphone applications and our very own highly available cluster (real, physical hardware) that hosts the application for the majority of our customers.

As even our end users slowly start to use their mobile phones more and more, so do our native mobile applications gain in importance to the point where we really have to focus a lot more resources on them.

This is where you come in: In order to provide the best possible user experience, we have decided to develop our offlline-first, native mobile applications separately for both iOS and Android and while we have Android pretty much covered, iOS is lagging behind a bit

If you’re interested to help us out with iOS, here’s what you will be working with.

  • The application is written in Swift, so you’ll likely use a lot of Swift during your day, however, we don’t mind if you decide you prefer to use something else.
  • The native application talks to a web service API of our main web application. But as the API is mostly private, you have the ability to directly influence the application in many cases.
  • As some parts of the process are very customizable, we’re looking into embedding react native views into the existing application.
  • As we maintain our applications for a long time, code-archeology is an important part of our work. And archeology is much more easily done with useful self-contained commits, so you’ll likely have a bit of a culture-shock when you see us use every nook and cranny of git’s feature-set. But don’t worry: We’ll help you get up to speed quickly.
  • We have bi-weekly meetings focussed on development practices and challenges we’ve overcome. You will have the direct ability to influence how we work together.

The platform we use to develop on is everybodys own choice. Everybody here uses Macs, but whatever you are most productive with is what you use, though as we’re talking mostly iOS development here, you’re probably going to use a Mac. Be it an iMac or a MacBook Pro – you tell us what you need and we’ll make it possible.

All of the code that we work with daily is home-grown (minus some libraries, of course). We control all of it and we get to play with all the components of the big thing. No component can’t be changed, though we certainly prefer changing some over the others :-)

Between the Cola tests and the technical versatility and challenges described above: If I can interest you, dear reader, to join our crazy productive team in order to improve one hell of a suite of applications, then now is your chance to join up: We need more people
to join our team of developers.

Also, if your particular problem is better solved in $LANGUAGE of your choice, feel free to just do it. Part of the secret behind our productivity is that we know our tools and know when to use them. Good code is readable in any language (though I’d hve to brush up my lisp if you chose to go that route).

Interested? I would love to hear from you at
phofstetter@sensational.ch.