title: Firebase Custom Authentication in .NET gives "The custom token format is incorrect"
body: <p>We're trying to setup Custom Authentication so that an Android application can leverage our existing Auth system to get access to a Firebase Database.</p>
  
  <p>The mobile app authenticates against an .NET WebAPI endpoint. We send back a firebase auth token in the response that the app can then use to authenticate in the Firebase SDK.</p>
  
  <p>We thought this would be pretty simple according to the documentation. Using the FirebaseTokenGenerator package from Nuget, we generate this token from the secret that is found in the Firebase Console > Project > Manage > Database > Database secrets.</p>
  
  <p>However we see this exception come back from the Android SDK when we use the token generated here:</p>
  
  <pre><code>com.google.firebase.auth.FirebaseAuthInvalidCredentialsException: The custom token format is incorrect. Please check the documentation.
  at com.google.android.gms.internal.zzafd.zzes(Unknown Source)
  at com.google.android.gms.internal.zzafa$zzg.zza(Unknown Source)
  at com.google.android.gms.internal.zzafl.zzet(Unknown Source)
  at com.google.android.gms.internal.zzafl$zza.onFailure(Unknown Source)
  at com.google.android.gms.internal.zzafg$zza.onTransact(Unknown Source)
  </code></pre>
  
  <p>Looking through the documentation has confused me even more because it is not clear what the issue might be. There seems to be many candidate solutions, but I am not able to figure out which is correct. Following are some things that are talked about in the docs:</p>
  
  <ul>
  <li>Creating a service account, downloading the JWT json file, including that in the .NET WebApi project and some how using that with the FirebaseTokenGenerator</li>
  <li>Using 3rd party JWT libraries to generate the token from the secret</li>
  </ul>
  
  <p>These two strategies seem to be getting at the same thing, but don't appear to be related in any way.</p>
  
  <p>Am I using the wrong secret? Do I need to do some more setup on my WebAPI project to get it generating the correct token?</p>
  
  <p>For reference, this is the method that generates my token:</p>
  
  <pre><code>public string GetSignedFirebaseAuthToken(Agent agent, DateTime expires)
  {
      var tokenGenerator = new Firebase.TokenGenerator(BusinessLogicResources.FirebaseSecret);
      var authPayload = new Dictionary&lt;string, object&gt;()
      {
          { "uid", agent.AgentId.ToString() },
          { "UserName", agent.FullName },
          { "AgencyId", agent.AgencyId },
          { "AgencyName", agent.AgencyName }
      };
      return tokenGenerator.CreateToken(authPayload, new Firebase.TokenOptions(expires:expires));
  }
  </code></pre>
  
  <p><strong>Update:</strong>
  This is the new code I'm using to mint my firebase token.</p>
  
  <pre><code>public string GetSignedFirebaseAuthToken(Agent agent, DateTime expires)
      {
          // I set the expiry time to 3600 because this is the maximum number of seconds
          // allowed according the the Firebase documenation.
          var expiryTime = 3600;
          // This claims object contains some additional information that Telenotes would
          // like to track for each user of Firebase. This is used for reporting and
          // security rules in Firebase.
          var claims = new Dictionary&lt;string, object&gt;()
          {
              { "UserName", agent.FullName },
              { "AgencyId", agent.AgencyId.ToString() },
              { "AgencyName", agent.AgencyName }
          };
          // In order for the cryptography algorithms to be happy, I need to put our
          // keys into stream objects.
          var memoryStream = new MemoryStream();
          var streamWriter = new StreamWriter(memoryStream);
          streamWriter.Write(BusinessLogicResources.FirebaseSecret.Replace(@"\n", "\n"));
          streamWriter.Flush();
          memoryStream.Position = 0;
          var streamReader = new StreamReader(memoryStream);
          // BouncyCastle takes care of the cryptography stuff, so we'll hand our
          // secret over to BouncyCastle to read and encode.
          var bouncyCastleReader = new PemReader(streamReader);
          var rsaParams = (RsaPrivateCrtKeyParameters) bouncyCastleReader.ReadObject();
          // Now that the secret is packed up all nicely in rsaParams, I need to
          // put together the rest of the payload that Firebase needs in my auth token.
          var tokenPayload = new Dictionary&lt;string, object&gt;()
          {
              { "claims", claims },
              { "uid", agent.AgentId },
              { "iat", (DateTime.Now).SecondsSinceEpoch() },
              { "exp", (DateTime.Now).AddSeconds(expiryTime).SecondsSinceEpoch() },
              { "aud", BusinessLogicResources.FirebasePayloadAud },
              { "iss", BusinessLogicResources.FirebasePayloadISS },
              { "sub", BusinessLogicResources.FirebasePayloadSUB },
              { "alg", "RS256" }
          };
  
          // Lastly, we need to put it all together using JOSE JWT (see https://github.com/dvsekhvalnov/jose-jwt)
          // and BouncyCastle encoding magic.
          var rsaKey = DotNetUtilities.ToRSA(rsaParams);
          return JWT.Encode(tokenPayload, rsaKey, JwsAlgorithm.RS256);
      }
  </code></pre>