I am developing a program for OS X that interacts with the VK API and the latest update did not accept the Mac App Store censors. After a few clarifications, they sent me a video of the work of the program, on which I racked my mind for several days.
The reasons for this behavior, I will discuss in this article. Just want to say that I do not consider this a bug of vk.com or OS X, but they both can correct this situation.
Flashing window
For a start, tell you what kind of window flashes on the video. For this, a few words about working with the VK API. And so for requests to the server api.vk.com, you need a token that must be obtained by authorization than the web interface at oauth.vk.com. The algorithm is as follows:
We appeal to any method vk.com, passing the last known token
If the response received an authorization error, go to the authorization
Show a window with a loaded web form, we get a token
Repeat everything from step 1
It immediately became clear that the authorization window was flashing on the screen of the censor. The only catch is that the window disappeared by itself. This is due to the fact that cookies are saved and no login / password input is required, the web form immediately redirects to a new token. The authorization system in the program has not changed since the very first version, and yet no user has addressed this problem. I immediately got into the code in an attempt to simulate such a situation by generating errors of different types. I spent a lot of time looking for and still settled on the fact that this is an authorization problem with any request, but why this happened for me remained a mystery.
hint
I don’t remember for what reason, but I decided to see where the requests came from and to my surprise, the list contained an IPv6 address! Well, the next task was to get the IPv6 channel. Helped section Q & A Habra. I immediately picked up the tunnel and began to play out. To great disappointment, everything worked as it should.
Cause
Tuning the tunnel, I noticed that not all traffic goes through IPv6, in addition, only a small part of it falls on this stack. Then I went to google about how all the same to put IPv6 priority. It turned out that this is impossible. You can only disable IPv4 completely and then only IPv6 will remain. Breaking a lot of information on the Internet, I found that OS X chooses which one to use when both stacks are available both on the server side and on the client side, based on the speed of past queries and caches. Here it is the cause of problems! After several reboots, DNS drops and tunnel shutdowns / connections, I got the bug to repeat. That's how it was:
Appeal to oauth.vk.com, the system chooses IPv6
The oauth.vk.com server generates a token associated with the IPv6 user address
Appeal to api.vk.com, the system chooses IPv4
The server api.vk.com rejects the request, because the token was not valid, the user’s address has changed
')
Possible solutions:
1. From the side of vk.com
The token must be bound to both addresses, both IPv4 and IPv6. Right at the time of this writing, I was told from vk that this is impossible: “At the expense of the stacks. We can not precisely bind the token to the two ip, since they are not connected to each other ”.
2. Direct authorization
VK API has a method for direct authorization , but for a week of calls to the vk command I could not get access to it.
3. From OS X
Make a convenient program mechanism for forcing traffic through one of the stacks.
4. From the client.
WebView uses the WebView component for displaying web forms, NSURLConnection for queries. If you manage to force all traffic through one stack, then everything should work. You can do this by writing your NSURLProtocol, but this is an incredibly large amount of work - you have to describe the entire HTTP and HTTPS + caching protocol yourself.
5. From the client.
When logging in, ask for scope = offline permissions, this will make it possible to get rid of IP, but I am very suspicious about programs that request such access.
I hope this information will be useful for other developers.