using Quizzer.OpenIDConnect;
using Newtonsoft.Json;
using Quizzer.OpenIDConnect;
namespace Quizzer.Implementations
{
public class KeyCloak
{
private bool isDebug;
private bool isOK;
private bool isTeacher;
private string? accessToken;
private string? classlessId;
private string? teachersId;
private string? developersId;
private string? studentsId;
///
/// This method uses the OAuth Resource Owners Credentials Flow to get an Access Token to provide
/// Authorization to the APIs.
///
///
private string GetAccessToken()
{
var client = new HttpClient();
// https://auth.c.ucnit.eu/realms/UCNit/protocol/openid-connect/token
string theURL = "https://" + MyConfiguration.Get()["API_SERVER"] + "/realms/" + MyConfiguration.Get()["API_REALM"] + "/protocol/openid-connect/token";
var request = new HttpRequestMessage(HttpMethod.Post, theURL);
var collection = new List>();
collection.Add(new("client_id", MyConfiguration.Get()["API_CLIENTID"]));
collection.Add(new("client_secret", MyConfiguration.Get()["API_SECRET"]));
collection.Add(new("grant_type", "client_credentials"));
var content = new FormUrlEncodedContent(collection);
request.Content = content;
if (isDebug)
{
Console.WriteLine("GetAccessToken");
Console.WriteLine("(POST) " + theURL);
Console.WriteLine("client_id: " + MyConfiguration.Get()["API_CLIENTID"]);
Console.WriteLine("client_secret: " + MyConfiguration.Get()["API_SECRET"]);
Console.WriteLine("grant_type: client_credentials");
}
var response = client.SendAsync(request).Result;
try
{
response.EnsureSuccessStatusCode();
string jsonString = response.Content.ReadAsStringAsync().Result;
object responseData = JsonConvert.DeserializeObject(jsonString);
// return the Access Token.
accessToken = ((dynamic)responseData).access_token;
}
catch (Exception ex)
{
Console.WriteLine(request.RequestUri);
Console.WriteLine(ex.Message);
accessToken = null;
}
// return the Access Token.
return accessToken;
}
public KeyCloak()
{
isDebug = MyConfiguration.Get()["DEBUG"] == "Y";
try
{
accessToken = GetAccessToken();
this.isOK = true;
}
catch
{
this.isOK = false;
}
}
public bool KeyCloakIsOK() { return isOK; }
public List KeyCloakGetGroups()
{
var client = new HttpClient();
// https://{{Server}}/admin/realms/{{Realm}}/groups
string theURL = "https://" + MyConfiguration.Get()["API_SERVER"] + "/admin/realms/" + MyConfiguration.Get()["API_REALM"] + "/groups";
var request = new HttpRequestMessage(HttpMethod.Get, theURL);
request.Headers.Add("Authorization", "Bearer " + accessToken);
if (isDebug)
{
Console.WriteLine("KeyCloakGetGroups");
Console.WriteLine("(GET) " + theURL);
Console.WriteLine("Authorization Bearer " + accessToken);
}
var response = client.SendAsync(request).Result;
try
{
response.EnsureSuccessStatusCode();
}
catch (HttpRequestException ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine("KeyCloakGetGroupsAsync");
}
string jsonString = response.Content.ReadAsStringAsync().Result;
List groups = JsonConvert.DeserializeObject>(jsonString);
foreach (KCGroups group in groups)
{
if (group.name == "ClassLess") classlessId = group.id;
if (group.name == "developer") developersId = group.id;
if (group.name == "teacher") teachersId = group.id;
if (group.name == "student") studentsId = group.id;
}
return groups;
}
public string? KeyCloakClassLess()
{
if (classlessId == null) _ = KeyCloakGetGroups();
return classlessId;
}
public string? KeyCloakTeacher()
{
if (teachersId == null) _ = KeyCloakGetGroups();
return teachersId;
}
public string? KeyCloakStudent()
{
if (studentsId == null) _ = KeyCloakGetGroups();
return studentsId;
}
public List KeyCloakGetUsersGroups(string theUser)
{
var client = new HttpClient();
// https://{{Server}}/admin/realms/{{Realm}}/users/{{kajeID}}/groups
string theURL = "https://" + MyConfiguration.Get()["API_SERVER"] + "/admin/realms/" + MyConfiguration.Get()["API_REALM"] + "/users/" + theUser + "/groups";
var request = new HttpRequestMessage(HttpMethod.Get, theURL);
request.Headers.Add("Authorization", "Bearer " + accessToken);
if (isDebug)
{
Console.WriteLine("KeyCloakGetUsersGroups");
Console.WriteLine("(GET) " + theURL);
Console.WriteLine("Authorization Bearer " + accessToken);
}
var response = client.SendAsync(request).Result;
try
{
response.EnsureSuccessStatusCode();
}
catch (HttpRequestException ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine("KeyCloakGetUsersGroupsAsync for user: [" + theUser + "]");
}
string jsonString = response.Content.ReadAsStringAsync().Result;
List groups = JsonConvert.DeserializeObject>(jsonString);
isTeacher = false;
foreach (KCGroups group in groups)
{
if (group.name == "teacher" || group.name == "developer") isTeacher = true;
if (isDebug)
{
Console.WriteLine("in group: " + group.name);
}
}
return groups;
}
public bool KeyCloakLeaveGroup(string theUser, string theGroup)
{
var client = new HttpClient();
string theURL = "https://" + MyConfiguration.Get()["API_SERVER"] + "/admin/realms/" + MyConfiguration.Get()["API_REALM"] + "/users/" + theUser + "/groups/" + theGroup;
var request = new HttpRequestMessage(HttpMethod.Delete, theURL);
request.Headers.Add("Authorization", "Bearer " + accessToken);
if (isDebug)
{
Console.WriteLine("KeyCloakLeaveGroup");
Console.WriteLine("(DELETE) " + theURL);
Console.WriteLine("Authorization Bearer " + accessToken);
}
var response = client.SendAsync(request).Result;
try
{
response.EnsureSuccessStatusCode();
return true;
}
catch (Exception ex)
{
return false;
}
}
public bool KeyCloakJoinGroup(string theUser, string theGroup)
{
var client = new HttpClient();
string theURL = "https://" + MyConfiguration.Get()["API_SERVER"] + "/admin/realms/" + MyConfiguration.Get()["API_REALM"] + "/users/" + theUser + "/groups/" + theGroup;
var request = new HttpRequestMessage(HttpMethod.Put, theURL);
request.Headers.Add("Authorization", "Bearer " + accessToken);
if (isDebug)
{
Console.WriteLine("KeyCloakJoinGroup");
Console.WriteLine("(PUT) " + theURL);
Console.WriteLine("Authorization Bearer " + accessToken);
}
var response = client.SendAsync(request).Result;
try
{
response.EnsureSuccessStatusCode();
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine("KeyCloakJoinGroup: [" + theGroup + "] for user: [" + theUser + "]");
return false;
}
}
public void KeyCloakToggleMembership(string theUser, string theGroup)
{
List myGroups = KeyCloakGetUsersGroups(theUser);
if (isDebug)
{
foreach (KCGroups group in myGroups)
{
Console.WriteLine("{0} member of {1}", theUser, group.name);
}
}
foreach (KCGroups group in myGroups)
{
if (group.id == theGroup)
{
KeyCloakLeaveGroup(theUser, theGroup);
if (isDebug) Console.WriteLine("{0} left {1}", theUser, theGroup);
return;
}
}
// if we get here, then create membership
KeyCloakJoinGroup(theUser, theGroup);
if (isDebug) Console.WriteLine("{0} joined {1}", theUser, theGroup);
}
public bool KeyCloakIsTeacher() { return isTeacher; }
}
public class KCUserGroups
{
public string? id { get; set; }
public string? name { get; set; }
public string? path { get; set; }
}
public class KCGroups : KCUserGroups
{
public List