ikawidget2がログインできない問題を修正した

原因について

調べてみたけれど、どうもアプリの更新ではないのでAPIだけの更新であるみたいである。

プログラムの知識がない人は「なんでこんなにも使えなくなるの!?」というところがまず疑問であると思うので、まずはikawidget2がどのような仕組みで動き、何故使えなくなるのかというところについて説明したい。

仕組みが気にならない人は最後のまとめから読んでください。

iksm_session

自作ツールでデータを取得したりしている方ならご存知かもしれないが、ニンテンドーサーバからガチマッチやサーモンランのリザルトを取得するには必ずこのiksm_sessionという固有のトークンが必要になります。

iksm_session生成のチャート

このうち、id_token・Timestampからhashを計算するs2s APIをfrozenpandaman氏が、UUID・hash・Timestamp・id_tokenからfを計算するflapg APIをnexusmine氏が運営しています。

これら二つの外部APIがあるおかげで、わたしたちは公式アプリ以外でもログインできるiksm_sessionを生成することができるのです。

そして、これら二つのAPIはfを計算するためだけにあるということも覚えておかなければいけないでしょう。

これは去年の九月にニンテンドーオンラインが有料化される際に追加された新たなパラメータで、ニンテンドーなりの切り札のようなものですね。

つまり、fを計算するパラメータをちょっと変えるだけで直ちに今までの認証方法は使えなくなり、flapg APIとs2s APIは再設計を余儀なくされるのです。

flapg APIとs2s APIについて

ニンテンドーの公式アプリではこれらのAPIは不要です。何故なら、アプリ内部にパラメータfを計算するための関数が存在するからです。

ここちょっと自信がない、間違ってたらごめんなさい。

ではどうやってflapg APIとs2s APIがつくられたかというとニンテンドー公式アプリを逆アセンブラしてfを生成する計算式を求めたからです。

これは大変に技術・知識・時間のかかる作業で、一朝一夕でできるものではありません。つまり、誰もがほいほい真似できるものではないということです。

これだけでも開発者の方々には頭が上がらないですね。

ちなみにこれらの作業はぼく程度ではとてもとてもできません。それくらいにすごい功績だということです。

APIが動作しなくなる仕組み

これらの外部APIが使えなくなる仕組みはおおよそ、次の三つが考えられます。

APIの軽微な変更

実際、前回変更があったのはこの部分でした。

UAのバージョンが1.5.0から1.5.2に変更になったので、そこを修正するだけで対応することができました。

fの仕様変更

fの計算式を変更するのが最もいやらしい変更の一つでしょう。

ただ、以前のバージョンで計算式を求めることに成功しているので多少の数値の変更程度であればその時の経験を活かすことができるので前回より(前は一ヶ月程度かかった気がする)は早く対応ができるのではないかという気がします。

先程も述べたようにfの計算はアプリ内で行われているので、アプリの更新がない限りはfの仕様変更はないと思われます。

認証の大幅な変更

するとは思えないけれど、APIに大幅な変更があったときはすごくめんどくさいと思います。

今回のエラーの原因

Error from the flapg API: Error 404 (offline or incorrect headers).

となり、flapg APIへアクセスする際にエラーが発生していることがわかります。

該当箇所は以下のようなコードです。

try:
  api_app_head = {
    'x-token': id_token,
    'x-time':  str(timestamp),
    'x-guid':  guid,
    'x-hash':  get_hash_from_s2s_api(id_token, timestamp),
    'x-ver':   '2',
    'x-iid':   ''.join([random.choice(string.ascii_letters + string.digits) for n in range(8)])
		}
  api_response = requests.get("https://flapg.com/ika2/api/login", headers=api_app_head)
  f = json.loads(api_response.text)
  return f

api_responseでエラーが発生しているのでここの処理が正しく終了していないようです。

つまり、原因はflapg APIのエラーということになります。

ではなぜflapg APIが正しいfを返さなくなったのかということになりますが、サーバはオフラインにはなっていないのでAPIの仕様が変わったのが原因でしょう。

要するに、API自体が悪いのではなくAPIに送られるデータがAPIが受け付けない形になってしまっているということです。

flapg APIに送信されるデータはid_tokenなのでここらへんを生成するコードが怪しい気がしますね…

というわけで実際に調べてみました。

connect/1.0.0/api/session_token

ここにアクセスする際に使われているのは三つのパラメータです。

client_id71b963c1b7b6d119
session_token_code
session_token_code_verifier

このうち、cliend_idはAndroidのNSOアプリを使うと “71b963c1b7b6d119” で固定で、splatnet2statinkでもこの値が使われています。

このパラメータは多分Splatoon2に割り当てられてゲームIDのようなものだと思います。

connect/1.0.0/api/token

client_id71b963c1b7b6d119
grant-typeurn:ietf:params:oauth:grant-type:jwt-bearer-session-token
session_token

送信されているデータはこんな感じです。

で、ここを見ていて気づいたんです。

なんか変わっとらん?

ヘッダーの長さが変わってる!!!

BeforeAfter
Content-Length: 437Content-Length: 439

まあこの問題はiksm.pyが返ってくるContent-Lengthを決め打ちで437としていたことが原因なんですが、常に長さが固定なら考えなくてもいいですしね。

ただ、何かしらの問題でこのヘッダーが二文字長くなってしまいました。

多分session_tokenを生成する際の計算式の問題とかそんなんだと思います。

まとめ

というわけで、今回もアプリの問題ではなくヘッダーの問題でしたのでおそらくikawidget2は数日以内に修正されると思います。

splatnet2statinkに関してはpull requestを送ったら五分くらいで受理されました(早い)

というわけで、splatnet2statinkに関してはもう使えるようになっているのでどうぞ!

Salmoniaに関してはiksm.pyに依存しているので修正が必要ですね。