Files
the-cycle/src/Prospect.Server.Api/Services/CloudScript/Functions/VivoxLogin.cs
T
2025-02-24 01:06:32 +02:00

107 lines
3.6 KiB
C#

using Prospect.Server.Api.Services.CloudScript.Models;
using System.Security.Cryptography;
using System.Text.Json;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
public class TokenGenerator
{
public static int TokenSequenceId = 0;
// Header is static - base64url encoded {}
private static readonly string Header = "e30";
public static string vxGenerateToken(string key, string issuer, int exp, string vxa, string f, string t)
{
TokenSequenceId++;
var claims = new Claims
{
iss = issuer,
exp = exp,
vxa = vxa,
vxi = TokenSequenceId,
f = f,
t = t
};
List<string> segments = new List<string>();
segments.Add(Header);
// Encode payload
var claimsString = JsonSerializer.Serialize(claims);
var encodedClaims = Base64URLEncode(claimsString);
// Join segments to prepare for signing
segments.Add(encodedClaims);
string toSign = String.Join(".", segments);
// Sign token with key and SHA256
string sig = SHA256Hash(key, toSign);
segments.Add(sig);
// Join all 3 parts of token with . and return
string token = String.Join(".", segments);
return token;
}
private static string Base64URLEncode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
// Remove padding at the end
var encodedString = Convert.ToBase64String(plainTextBytes).TrimEnd('=');
// Substitute URL-safe characters
string urlEncoded = encodedString.Replace("+", "-").Replace("/", "_");
return urlEncoded;
}
private static string SHA256Hash(string secret, string message)
{
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(message);
// The instance of HMACSHA256 is constructed and disposed in this method because it is not thread safe
using var hmacsha256 = new HMACSHA256(keyByte);
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
var hashString = Convert.ToBase64String(hashmessage).TrimEnd('=');
string urlEncoded = hashString.Replace("+", "-").Replace("/", "_");
return urlEncoded;
}
public class Claims
{
public string iss { get; set; }
public int exp { get; set; }
public string vxa { get; set; }
public int vxi { get; set; }
public string f { get; set; }
public string t { get; set; }
public string sub { get; set; }
}
}
[CloudScriptFunction("VivoxLogin")]
public class VivoxLogin : ICloudScriptFunction<FYVivoxLoginTokenRequest, FYVivoxJoinData>
{
public async Task<FYVivoxJoinData> ExecuteAsync(FYVivoxLoginTokenRequest request)
{
// TODO: Replace with app configuration
var channel = "sip:confctl-g-<issuer>.testchannel@mtu1xp.vivox.com"; // e - echo channel, g - global, p - positional
var exp = (int)DateTimeOffset.UtcNow.AddSeconds(90).ToUnixTimeSeconds();
var token = TokenGenerator.vxGenerateToken("key", "issuer", exp, "login", request.Username, channel);
return new FYVivoxJoinData
{
Request = new Models.Data.FYVivoxJoinTokenRequest{
Username = request.Username,
Channel = channel,
HasAudio = false,
HasText = true,
ChannelType = 2,
ChannelID = "testchannel",
},
Token = token
};
}
}