Firebase 3: creating a custom authentication token using .net and c#

前端 未结 4 1590
[愿得一人]
[愿得一人] 2020-12-05 01:25

I\'m trying to implement Firebase 3 Authentication mechanism using Custom Tokens (as described at https:// firebase.google.com/docs/auth/server/create-custom-tokens).

<
4条回答
  •  情话喂你
    2020-12-05 01:56

    @Elliveny's answer worked great for me. I am using it in a .NET Core 2.0 application and have built upon the accepted answer to turn this solution into a class that can be registered as a singleton dependency in the app services container, as well as have configuration passed in via constructor so that we can leverage .NET secrets for local development configuration and environment variables for production configuration.

    I have also tidied up the stream handling a bit.

    Note for .NET Core devs - you'll need to use Portable.BouncyCastle

    You can test your encoded results by parsing the output JWT token with Jwt.IO

    using Jose;
    using Org.BouncyCastle.Crypto.Parameters;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    
    public class FirebaseTokenGenerator
    {
        // private_key from the Service Account JSON file
        public static string firebasePrivateKey;
    
        // Same for everyone
        public static string firebasePayloadAUD = "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit";
    
        // client_email from the Service Account JSON file
        public static string firebasePayloadISS;
        public static string firebasePayloadSUB;
    
        // the token 'exp' - max 3600 seconds - see https://firebase.google.com/docs/auth/server/create-custom-tokens
        public static int firebaseTokenExpirySecs = 3600;
    
        private static RsaPrivateCrtKeyParameters _rsaParams;
        private static object _rsaParamsLocker = new object();
    
        public FirebaseTokenGenerator(string privateKey, string clientEmail)
        {
            firebasePrivateKey = privateKey ?? throw new ArgumentNullException(nameof(privateKey));
            firebasePayloadISS = clientEmail ?? throw new ArgumentNullException(nameof(clientEmail));
            firebasePayloadSUB = clientEmail;
        }
    
        public static string EncodeToken(string uid)
        {
            return EncodeToken(uid, null);
        }
    
        public static string EncodeToken(string uid, Dictionary claims)
        {
            // Get the RsaPrivateCrtKeyParameters if we haven't already determined them
            if (_rsaParams == null)
            {
                lock (_rsaParamsLocker)
                {
                    if (_rsaParams == null)
                    {
                        using (var streamWriter = WriteToStreamWithString(firebasePrivateKey.Replace(@"\n", "\n")))
                        {
                            using (var sr = new StreamReader(streamWriter.BaseStream))
                            {
                                var pr = new Org.BouncyCastle.OpenSsl.PemReader(sr);
                                _rsaParams = (RsaPrivateCrtKeyParameters)pr.ReadObject();
                            }
                        }
                    }
                }
            }
    
            var payload = new Dictionary {
            {"uid", uid}
            ,{"iat", SecondsSinceEpoch(DateTime.UtcNow)}
            ,{"exp", SecondsSinceEpoch(DateTime.UtcNow.AddSeconds(firebaseTokenExpirySecs))}
            ,{"aud", firebasePayloadAUD}
            ,{"iss", firebasePayloadISS}
            ,{"sub", firebasePayloadSUB}
        };
    
            if (claims != null && claims.Any())
            {
                payload.Add("claims", claims);
            }
    
            return JWT.Encode(payload, Org.BouncyCastle.Security.DotNetUtilities.ToRSA(_rsaParams), JwsAlgorithm.RS256);
        }
    
    
        private static long SecondsSinceEpoch(DateTime dt)
        {
            TimeSpan t = dt - new DateTime(1970, 1, 1);
            return (long) t.TotalSeconds;
        }
    
        private static StreamWriter WriteToStreamWithString(string s)
        {
            MemoryStream stream = new MemoryStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.Write(s);
            writer.Flush();
            stream.Position = 0;
            return writer;
        }
    }
    

提交回复
热议问题