9

I have a Xamarin Forms app which is being built using App Center. The app contains some code that looks like:

var secret= "secretvaluegoeshere";

I then use the secret to communicate with an API. Now I want to extract that secret from code so as not to having it in source control and inject it when building on App Center. Environment Variables seem like they should solve this very problem but the examples in the docs don't mention how they can get into code (only nuget and gradle config). Is there a way to do what I want with Environment Variables or should I be doing this another way?

Adam Cooper
  • 8,077
  • 2
  • 33
  • 51

3 Answers3

19

So it turns out this is surprisingly easy by following these steps:

Install the Mobile.BuildTools NuGet package in your project.

Add a secrets.json file in the root of your project (this should be excluded from source control using .gitignore).

Add your secret to the secrets.json file, so in my case I'm going to add a SearchApiKey, obviously you can add as many secrets as you want:

{
  "SearchApiKey": "SUPERSECRETGOESHERE"
}

Build your project and this will generate a static class called Secrets with a property SearchApiKey, you can find it under the obj folder if you want to have a look at it.

You can now access this class and it's properties in your code so I just do:

var secret = Secrets.SearchApiKey;

Finally to pass the secret into your build on AppCenter you need to add an Environment Variable that matches the property name prepended with Secret_ so in my case it's name is Secret_SearchApiKey and set it's value.

You can check out the Mobile.BuildTools GitHub repository for more information.

Adam Cooper
  • 8,077
  • 2
  • 33
  • 51
  • 3
    I also wrote this up in a short blog post with some extra details https://sequence7.net/2018/09/21/keeping-secrets-out-of-your-source-code-with-mobile-buildtools-and-appcenter/ – Adam Cooper Sep 22 '18 at 18:57
  • Hi Adam, but we need to add this file in our solution or it will be added by default? – soydachi Nov 27 '18 at 11:39
  • 1
    Which file do you mean @soydachi? The Secrets.cs file is generated automatically you will need to create the secrets.json file – Adam Cooper Dec 07 '18 at 19:16
  • Hi Adam, I may be asking an obvious question here, but can this secret info be obtained by decompiling the end binaries say? – Ishyc Feb 25 '19 at 10:30
  • 1
    @Ishyc You can always obtain information via decompilation. Tools like Proguard make this more difficult but in the end mobile apps cannot be trusted. – torchhound Apr 12 '19 at 17:44
  • so how is this different from just creating a static class with keys and excluding it in .gitignore ? – ihor.eth Nov 21 '19 at 20:22
  • 1
    the work of inserting secrets, specified in the AppCenter, is done for you – Yehor Hromadskyi Jan 10 '20 at 11:13
  • Thanks for this explanation! With Mobile.buildtools 2.0 this seems to have changed a bit. No more secrets, but appsettings.json. I can't make that working for me (with the correct configuration and appsettings.json a class has been made, but I can't access it). With version 1.4 and your explanation it works! – Rub3s Aug 20 '21 at 16:35
  • I have been unable to make this package actually generate any class at all, even using their examples. – Owen Burns Oct 16 '21 at 20:04
  • @AdamCooper Thanks, the url of your blog post is dead seemingly so let me attach the valid one https://www.admcpr.com/keeping-secrets-out-of-your-source-code-with-mobile-buildtools-and-appcenter/ – Bryce Friha Sep 10 '22 at 12:57
  • 1
    Thanks @BryceFriha I fixed the original url so both should work now :) – Adam Cooper Sep 11 '22 at 19:22
4

You can inject it via pre-build script into your project (replace some placeholder directly in the code, create some resource file or so) and then read it from there at runtime.

Ivan
  • 673
  • 7
  • 15
  • Can you give some more specific details of how I would do this with Xamarin & App Center Ivan? – Adam Cooper Aug 09 '18 at 12:31
  • I mean there is no specific way to do it for Xamarin. More than this var will be available only on build-time but not runtime. So, if you want to access it at runtime, you should save it (via pre-build step in bash script) to place which accessible in run-time. Simplest way - write it right in code (some `*.cs` file) and then compile it into your app. You can do this via regex for example. Keep some placeholder in this constant to simplify search. – Ivan Aug 13 '18 at 06:35
2

If you don't want to use additional nuget packages, you can follow example posted from the official AppCenter project on GitHub

What you have to do is create a new environment variable on AppCenter with the value you want to set. Then save a file named appcenter-pre-build.sh at the same lever of your .csproj file and create your own code like in the example.

Once you have added the file to your repo, in order to save the detected scripts to the build configuration, you have to hit the “Save” or “Save & Build” button in the build configuration

It worked for me like a charm a momment ago, hope it helps someone!

David López
  • 366
  • 3
  • 12