Thursday, 21 November 2024

JWT token secured with RSA256

The purpose of this article is to create a JWT token secured with RSA256 private key.

The first step is to generate the private key used by the sending Application. To generate the key we need to use OpenSSL. If we are using Windows 10/11 OS, this is easy since the OpenSSL is already available at C:\Program Files\Git\usr\bin. If not available, it can be downloaded. The next step is to open Git Bash and start OpenSSL command. The next steps are mentioned below:

   - openssl genrsa -out mbprivate.key 2048

Next we need to generate .csr file for submitting to Certificate Authority

   - openssl req -new -key mbprivate.key -out mbrequest.csr

The .crt file that will be used by the application that will be needed by the receiving Application                - openssl x509 -req -days 365 -in mbrequest.csr -signkey mbprivate.key -out mbcertificate.crt

If we need the JWT token to have a key id in the header we need to generate that:
    - openssl rsa -in mbprivate.key -pubout -outform DER | openssl dgst -sha256 -binary | openssl enc -base64

 

        [HttpGet]
        public async Task<IActionResult> GenerateToken(string UserName)
        {
            var authClaims = new List<Claim>
            {
                new Claim(JwtRegisteredClaimNames.Sub, UserName),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            };
            var token = CreateRsaToken(authClaims);

            return Ok(token);
        }

        private string CreateRsaToken(List<Claim> authClaims)
        {            
            var rsaPrivateKey = System.IO.File.ReadAllText(System.IO.Path.Combine(Environment.CurrentDirectory, "mbprivate.key"));
            using var rsa = RSA.Create();
            rsa.ImportFromPem(rsaPrivateKey);
            RsaSecurityKey rsaSecurityKey = new RsaSecurityKey(rsa);
            rsaSecurityKey.KeyId = "gdNz9m5dR/tFD5AQ0SghAkiM8VAC2yWSkTb+K2Nv/k=";

            var signingCredentials = new SigningCredentials(rsaSecurityKey, SecurityAlgorithms.RsaSha256)
            {
                CryptoProviderFactory = new CryptoProviderFactory { CacheSignatureProviders = false }
            };            

            var now = DateTime.Now;

            var jwt = new JwtSecurityToken(
              issuer: _configuration["JWT:ValidIssuer"],
              audience: _configuration["JWT:ValidAudience"],
              claims: authClaims,
              notBefore: now,
              expires: now.AddHours(1),
              signingCredentials: signingCredentials
            );
            
            return new JwtSecurityTokenHandler().WriteToken(jwt);
        }

Friday, 10 May 2024

 How do I send a server side Push Notification on Firebase Http V1 for Android

Here I am using the FirebaseAdmin Nuget package


Create a NotificationPayload class

    public class NotificationPayload
    {
        public string Title { get; set; }
        public string Body { get; set; }        
        public Dictionary<string, string> CustomFields { get; set; }
    }


Now you can create the method "SendAndroidPushNotificationAsync" that is going to send the Push Notification:

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using FirebaseAdmin.Messaging;
using FirebaseAdmin;
using Google.Apis.Auth.OAuth2;
using System.IO;

    public async Task SendAndroidPushNotificationAsync(string deviceId, NotificationPayload notificationPayload)
    {
        var customFields = new Dictionary<string, string>();
        if (notificationPayload.CustomFields != null && notificationPayload.CustomFields.Count > 0)
        {
            foreach (var field in notificationPayload.CustomFields)
            {
                customFields.Add(field.Key.ToString(), field.Value);
            }
        }
        FirebaseApp.Create(new AppOptions()
        {
            Credential = GoogleCredential.FromFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "firebase-adminsdk.json")),
        });
        var notificationMessage = new FirebaseAdmin.Messaging.Message()
        {
            Data = customFields,
            Notification = new FirebaseAdmin.Messaging.Notification
            {
                Title = notificationPayload.Title,
                Body = notificationPayload.Body
            },
            Android = new FirebaseAdmin.Messaging.AndroidConfig()
            {
                Priority = Priority.Normal,
                TimeToLive = TimeSpan.FromHours(1),
            },
            Token = deviceId
        };
        var result = await FirebaseMessaging.DefaultInstance.SendAsync(notificationMessage);

        Console.WriteLine(result);
    }


The "firebase-adminsdk.json" is the private key json file that you need to generate from your Firebase Project and store in your Application's root folder.

Now you can call this method "SendAndroidPushNotificationAsync" from whichever project that you want to sent the Push Notification. You will need an App to which you want to send the Notification and the deviceId/channelId to which the Notification need to be sent.

If we are getting a result like "//projects/myapp/messages/2492588335721724324" we should be good