Xamarin で秘密情報を管理するいくつかあるうちひとつの冴えたやりかた

この記事は、Xamarin Advent Calendar 2019 の三日目の記事です。

qiita.com

OAuth で使う ClientId と ClientSecret の管理で悩み中。 ハードコードしてはダメだし、Git リポジトリにコミットするのもダメ。

Xamarin.Android なら AndroidManifest.xml placeholders をサポートしているようなので、 この機能を使えば良いだろう。

github.com

ただ、Xamarin.iOS というか Xamarin. Forms ではどうしたものか。 2019 年も終わり間近だというのに、ベストプラクティスが見当たらない。

これが React + create-react-app での開発なら、 .env ファイルに REACT_APP_KEY=VALUE 形式で秘密情報を記述しておけば、 コードから process.env.REACT_APP_KEY で参照できるんだけどな。 同じようなことが Xamarin でもやりたい。 例えば、秘密情報を JSON ファイルに記述したら、 obj 下に自動的にコードが生成されたらいいんじゃないだろうか。

.NET Core 3.0 で gRPC が正式サポートされ、 Visual Studio で gRPC サービスプロジェクトの .proto ファイルを編集したら、 obj 下にコードが生成されるようになった。 それと同じような仕組みで実現できるかも、 と思って方法を調べていたら、 やろうとしていたことズバリそのものな NuGet パッケージを見つけてしまった。

github.com

NuGet で Mobile.BuildTools をインストールし、 プロジェクトのルートに secrets.json を作成。 この secrets.json に、例えば次のような秘密情報を記述したとする。

{
    "ClientId": "{Your ClientId HERE}",
    "ClientSecret": "{Your ClientSecret HERE}"
}

すると、{プロジェクトのルート}.Helpers 名前空間に次のような Secrets クラスが生成される。

// ------------------------------------------------------------------------------
//  <autogenerated>
//      This code was generated by Mobile.BuildTools. For more information or to
//      file an issue please see https://github.com/dansiegel/Mobile.BuildTools
//
//      Changes to this file may cause incorrect behavior and will be lost when 
//      the code is regenerated. 
//
//      NOTE: This file should be excluded from source control.
//  </autogenerated>
// ------------------------------------------------------------------------------

namespace SecretsSample.Helpers
{
    internal static class Secrets
    {
        internal const string ClientId = "{Your ClientId HERE}";

        internal const string ClientSecret = "{Your ClientSecret HERE}";
    }
}

あとは秘密情報が必要な箇所で、この Secrets クラスを使えばいい。 secrets.json と Secrets.cs は誤ってリポジトリにコミットしないよう、.gitignore に追加しておく。 なんだ、これでいいじゃん。

ちなみに、Mobile.BuildTools の Wikiデモアプリによると App Center にも対応しているみたいで、秘密情報を App Center の環境変数に設定しておいて、ビルド時に組み込むことができそうだ。ただ、App Center は使ってないので試していないけど。